* doc/sdccman.lyx,
[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   Bug Fixes  -  Mauro Giachero <maurogiachero AT users.sourceforge.net> (2008)
13
14   This program is free software; you can redistribute it and/or modify it
15   under the terms of the GNU General Public License as published by the
16   Free Software Foundation; either version 2, or (at your option) any
17   later version.
18
19   This program is distributed in the hope that it will be useful,
20   but WITHOUT ANY WARRANTY; without even the implied warranty of
21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22   GNU General Public License for more details.
23
24   You should have received a copy of the GNU General Public License
25   along with this program; if not, write to the Free Software
26   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27
28   In other words, you are welcome to use, share and improve this program.
29   You are forbidden to forbid anyone else to use, share and improve
30   what you give them.   Help stamp out software-hoarding!
31
32   Notes:
33   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
34                 Made everything static
35 -------------------------------------------------------------------------*/
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <ctype.h>
41 #include "SDCCglobl.h"
42 #include "newalloc.h"
43
44 #include "common.h"
45 #include "SDCCpeeph.h"
46 #include "ralloc.h"
47 #include "pcode.h"
48 #include "gen.h"
49 #include "genutils.h"
50 #include "device.h"
51 #include "main.h"
52 #include "glue.h"
53
54 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
55 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
56 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
57 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
58 #define IS_DIRECT(op)           ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
59
60 /* Wrapper to execute `code' at most once. */
61 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
62
63 void pic16_genMult8X8_n (operand *, operand *,operand *);
64 extern void pic16_printpBlock(FILE *of, pBlock *pb);
65 static asmop *newAsmop (short type);
66 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
67 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
68 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
69 static pCodeOp *pic16_popRegFromIdx(int rIdx);
70
71 int pic16_labelOffset=0;
72 extern int pic16_debug_verbose;
73
74 extern set *externs;
75
76 /* max_key keeps track of the largest label number used in
77    a function. This is then used to adjust the label offset
78    for the next function.
79 */
80 static int max_key=0;
81 static int GpsuedoStkPtr=0;
82
83 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
84
85 const char *pic16_AopType(short type);
86 static iCode *ifxForOp ( operand *op, iCode *ic );
87
88 void pic16_pushpCodeOp(pCodeOp *pcop);
89 void pic16_poppCodeOp(pCodeOp *pcop);
90
91
92 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
93
94 /* set the following macro to 1 to enable passing the
95  * first byte of functions parameters via WREG */
96 #define USE_WREG_IN_FUNC_PARAMS 0
97
98
99 /* this is the down and dirty file with all kinds of
100    kludgy & hacky stuff. This is what it is all about
101    CODE GENERATION for a specific MCU . some of the
102    routines may be reusable, will have to see */
103 static char *zero = "#0x00";
104 static char *one  = "#0x01";
105
106
107 /*
108  * Function return value policy (MSB-->LSB):
109  *  8 bits      -> WREG
110  * 16 bits      -> PRODL:WREG
111  * 24 bits      -> PRODH:PRODL:WREG
112  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
113  * >32 bits     -> on stack, and FSR0 points to the beginning
114  */
115 char *fReturnpic16[] = { "WREG", "PRODL", "PRODH", "FSR0L" };
116 int fReturnIdx[] = { IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
117 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
118 static char **fReturn = fReturnpic16;
119
120 static char *accUse[] = {"WREG"};
121
122 static struct {
123     short accInUse;
124     short inLine;
125     short debugLine;
126     short nRegsSaved;
127     set *sendSet;
128     set *stackRegSet;
129     int usefastretfie;
130     bitVect *fregsUsed;                 /* registers used in function */
131     bitVect *sregsAlloc;
132     set *sregsAllocSet;                 /* registers used to store stack variables */
133     int stack_lat;                      /* stack offset latency */
134     int resDirect;
135     int useWreg;                        /* flag when WREG is used to pass function parameter */
136 } _G;
137
138 extern struct dbuf_s *codeOutBuf;
139
140 static lineNode *lineHead = NULL;
141 static lineNode *lineCurr = NULL;
142
143 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
144 0xE0, 0xC0, 0x80, 0x00};
145 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
146 0x07, 0x03, 0x01, 0x00};
147
148 static  pBlock *pb;
149
150 /*-----------------------------------------------------------------*/
151 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
152 /*                 exponent of 2 is returned, otherwise -1 is      */
153 /*                 returned.                                       */
154 /* note that this is similar to the function `powof2' in SDCCsymt  */
155 /* if(n == 2^y)                                                    */
156 /*   return y;                                                     */
157 /* return -1;                                                      */
158 /*-----------------------------------------------------------------*/
159 int pic16_my_powof2 (unsigned long num)
160 {
161   if(num) {
162     if( (num & (num-1)) == 0) {
163       int nshifts = -1;
164       while(num) {
165         num>>=1;
166         nshifts++;
167       }
168       return nshifts;
169     }
170   }
171
172   return -1;
173 }
174
175 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
176 {
177   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
178                        line_no,
179                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
180                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
181                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
182                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
183                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
184                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
185                        ((result) ? AOP_SIZE(result) : 0));
186 }
187
188 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
189 {
190
191   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
192                        line_no,
193                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
194                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
195                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
196                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
197                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
198                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
199
200 }
201
202 void pic16_emitpcomment (char *fmt, ...)
203 {
204     va_list ap;
205     char lb[INITIAL_INLINEASM];
206     unsigned char *lbp = (unsigned char *)lb;
207
208     va_start(ap,fmt);
209
210     lb[0] = ';';
211     vsprintf(lb+1,fmt,ap);
212
213     while (isspace(*lbp)) lbp++;
214
215     if (lbp && *lbp)
216         lineCurr = (lineCurr ?
217                     connectLine(lineCurr,newLineNode(lb)) :
218                     (lineHead = newLineNode(lb)));
219     lineCurr->isInline = _G.inLine;
220     lineCurr->isDebug  = _G.debugLine;
221     lineCurr->isComment = 1;
222
223     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
224     va_end(ap);
225
226 //      fprintf(stderr, "%s\n", lb);
227 }
228
229 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
230 {
231     va_list ap;
232     char lb[INITIAL_INLINEASM];
233     unsigned char *lbp = (unsigned char *)lb;
234
235     if(!pic16_debug_verbose)
236       return;
237
238     va_start(ap,fmt);
239
240     if (inst && *inst) {
241         if (fmt && *fmt)
242             sprintf(lb,"%s\t",inst);
243         else
244             sprintf(lb,"%s",inst);
245         vsprintf(lb+(strlen(lb)),fmt,ap);
246     }  else
247         vsprintf(lb,fmt,ap);
248
249     while (isspace(*lbp)) lbp++;
250
251     if (lbp && *lbp)
252         lineCurr = (lineCurr ?
253                     connectLine(lineCurr,newLineNode(lb)) :
254                     (lineHead = newLineNode(lb)));
255     lineCurr->isInline = _G.inLine;
256     lineCurr->isDebug  = _G.debugLine;
257
258     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
259     va_end(ap);
260
261 //      fprintf(stderr, "%s\n", lb);
262 }
263
264
265
266 void pic16_emitpLabel(int key)
267 {
268   if(key>max_key)
269     max_key = key;
270
271   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
272 }
273
274 void pic16_emitpLabelFORCE(int key)
275 {
276   if(key>max_key)
277     max_key = key;
278
279   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
280 }
281
282 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
283  * NEVER call pic16_emitpcode_real directly, please... */
284 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
285 {
286
287   if(pcop)
288     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
289   else
290     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
291 }
292
293 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
294 {
295   if(pcop)
296     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
297   else
298     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
299 }
300
301 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
302 {
303
304   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
305
306 }
307
308
309 #if 1
310 #define pic16_emitcode  DEBUGpic16_emitcode
311 #else
312 /*-----------------------------------------------------------------*/
313 /* pic16_emitcode - writes the code into a file : for now it is simple    */
314 /*-----------------------------------------------------------------*/
315 void pic16_emitcode (char *inst,char *fmt, ...)
316 {
317     va_list ap;
318     char lb[INITIAL_INLINEASM];
319     unsigned char *lbp = lb;
320
321     va_start(ap,fmt);
322
323     if (inst && *inst) {
324         if (fmt && *fmt)
325             sprintf(lb,"%s\t",inst);
326         else
327             sprintf(lb,"%s",inst);
328         vsprintf(lb+(strlen(lb)),fmt,ap);
329     }  else
330         vsprintf(lb,fmt,ap);
331
332     while (isspace(*lbp)) lbp++;
333
334     if (lbp && *lbp)
335         lineCurr = (lineCurr ?
336                     connectLine(lineCurr,newLineNode(lb)) :
337                     (lineHead = newLineNode(lb)));
338     lineCurr->isInline = _G.inLine;
339     lineCurr->isDebug  = _G.debugLine;
340     lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
341     lineCurr->isComment = (*lbp == ';');
342
343 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
344
345 //    if(pic16_debug_verbose)
346 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
347
348     va_end(ap);
349 }
350 #endif
351
352
353 /*-----------------------------------------------------------------*/
354 /* pic16_emitDebuggerSymbol - associate the current code location  */
355 /*   with a debugger symbol                                        */
356 /*-----------------------------------------------------------------*/
357 void
358 pic16_emitDebuggerSymbol (char * debugSym)
359 {
360   _G.debugLine = 1;
361   pic16_emitcode (";", "%s ==.", debugSym);
362   _G.debugLine = 0;
363 }
364
365 /*-----------------------------------------------------------------*/
366 /* newAsmop - creates a new asmOp                                  */
367 /*-----------------------------------------------------------------*/
368 static asmop *newAsmop (short type)
369 {
370     asmop *aop;
371
372     aop = Safe_calloc(1,sizeof(asmop));
373     aop->type = type;
374     return aop;
375 }
376
377 /*-----------------------------------------------------------------*/
378 /* resolveIfx - converts an iCode ifx into a form more useful for  */
379 /*              generating code                                    */
380 /*-----------------------------------------------------------------*/
381 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
382 {
383   FENTRY2;
384
385 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
386
387   if(!resIfx)
388     return;
389
390
391   resIfx->condition = 1;    /* assume that the ifx is true */
392   resIfx->generated = 0;    /* indicate that the ifx has not been used */
393
394   if(!ifx) {
395     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
396
397 #if 1
398     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
399                         __FUNCTION__,__LINE__,resIfx->lbl->key);
400 #endif
401
402   } else {
403     if(IC_TRUE(ifx)) {
404       resIfx->lbl = IC_TRUE(ifx);
405     } else {
406       resIfx->lbl = IC_FALSE(ifx);
407       resIfx->condition = 0;
408     }
409
410 #if 1
411     if(IC_TRUE(ifx))
412       DEBUGpic16_emitcode("; +++","ifx true is non-null");
413     else
414       DEBUGpic16_emitcode("; +++","ifx true is null");
415     if(IC_FALSE(ifx))
416       DEBUGpic16_emitcode("; +++","ifx false is non-null");
417     else
418       DEBUGpic16_emitcode("; +++","ifx false is null");
419 #endif
420   }
421
422   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
423
424 }
425 #if 0
426 /*-----------------------------------------------------------------*/
427 /* pointerCode - returns the code for a pointer type               */
428 /*-----------------------------------------------------------------*/
429 static int pointerCode (sym_link *etype)
430 {
431
432     return PTR_TYPE(SPEC_OCLS(etype));
433
434 }
435 #endif
436
437 /*-----------------------------------------------------------------*/
438 /* aopForSym - for a true symbol                                   */
439 /*-----------------------------------------------------------------*/
440 static asmop *aopForSym (iCode *ic, operand *op, bool result)
441 {
442     symbol *sym=OP_SYMBOL(op);
443     asmop *aop;
444     memmap *space= SPEC_OCLS(sym->etype);
445
446     FENTRY2;
447
448     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
449
450 //    sym = OP_SYMBOL(op);
451
452     /* if already has one */
453     if (sym->aop) {
454             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
455         return sym->aop;
456     }
457
458 #if 0
459     /* if symbol was initially placed onStack then we must re-place it
460      * to direct memory, since pic16 does not have a specific stack */
461     if(sym->onStack) {
462         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
463     }
464 #endif
465
466
467 #if 0
468     if(sym->iaccess) {
469       if(space->paged) {
470         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
471
472         sym->aop = aop = newAsmop (AOP_PAGED);
473         aop->aopu.aop_dir = sym->rname ;
474         aop->size = getSize(sym->type);
475         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
476         pic16_allocDirReg( IC_LEFT(ic) );
477         return aop;
478       }
479       assert( 0 );
480     }
481 #endif
482
483 #if 1
484     /* assign depending on the storage class */
485     /* if it is on the stack or indirectly addressable */
486     /* space we need to assign either r0 or r1 to it   */
487     if (sym->onStack)   // || sym->iaccess)
488     {
489       pCodeOp *pcop[4];
490       int i;
491
492         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
493                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
494
495         /* acquire a temporary register -- it is saved in function */
496
497         sym->aop = aop = newAsmop(AOP_STA);
498         aop->aopu.stk.stk = sym->stack;
499         aop->size = getSize(sym->type);
500
501
502         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
503         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
504           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
505 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
506
507           for(i=0;i<aop->size;i++)
508             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
509             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
510         } else
511         if(1 && ic->op == SEND) {
512
513           /* if SEND do the send here */
514           _G.resDirect = 1;
515         } else {
516 //                debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
517           for(i=0;i<aop->size;i++) {
518             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
519             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
520           }
521         }
522
523
524 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
525
526 #if 1
527         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
528
529         // we do not need to load the value if it is to be defined...
530         if (result) return aop;
531
532         if(_G.accInUse) {
533                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
534         }
535
536         for(i=0;i<aop->size;i++) {
537
538           /* initialise for stack access via frame pointer */
539           // operands on stack are accessible via "{FRAME POINTER} + index" with index
540           // starting at 2 for arguments and growing from 0 downwards for
541           // local variables (index == 0 is not assigned so we add one here)
542           {
543             int soffs = sym->stack;
544             if (soffs <= 0) {
545               assert (soffs < 0);
546               soffs++;
547             } // if
548
549             if(1 && ic->op == SEND) {
550               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
551               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
552                     pic16_popCopyReg( pic16_frame_plusw ),
553                     pic16_popCopyReg(pic16_stack_postdec )));
554             } else {
555               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
556               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
557                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
558             }
559           }
560         }
561
562         if(_G.accInUse) {
563                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
564         }
565
566         return (aop);
567 #endif
568
569 #if 0
570         /* now assign the address of the variable to
571         the pointer register */
572         if (aop->type != AOP_STK) {
573
574             if (sym->onStack) {
575                     if ( _G.accInUse )
576                         pic16_emitcode("push","acc");
577
578                     pic16_emitcode("mov","a,_bp");
579                     pic16_emitcode("add","a,#0x%02x",
580                              ((sym->stack < 0) ?
581                               ((char)(sym->stack - _G.nRegsSaved )) :
582                               ((char)sym->stack)) & 0xff);
583                     pic16_emitcode("mov","%s,a",
584                              aop->aopu.aop_ptr->name);
585
586                     if ( _G.accInUse )
587                         pic16_emitcode("pop","acc");
588             } else
589                 pic16_emitcode("mov","%s,#%s",
590                          aop->aopu.aop_ptr->name,
591                          sym->rname);
592             aop->paged = space->paged;
593         } else
594             aop->aopu.aop_stk = sym->stack;
595         return aop;
596 #endif
597
598     }
599 #endif
600
601 #if 1
602     /* special case for a function */
603     if (IS_FUNC(sym->type)) {
604         sym->aop = aop = newAsmop(AOP_PCODE);
605         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
606         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
607         PCOI(aop->aopu.pcop)->index = 0;
608         aop->size = FPTRSIZE;
609         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
610         return aop;
611     }
612 #endif
613
614
615
616     //DEBUGpic16_emitcode(";","%d",__LINE__);
617     /* if in bit space */
618     if (IN_BITSPACE(space)) {
619         sym->aop = aop = newAsmop (AOP_CRY);
620         aop->aopu.aop_dir = sym->rname ;
621         aop->size = getSize(sym->type);
622         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
623         return aop;
624     }
625     /* if it is in direct space */
626     if (IN_DIRSPACE(space)) {
627                 if(!strcmp(sym->rname, "_WREG")) {
628                         sym->aop = aop = newAsmop (AOP_ACC);
629                         aop->size = getSize(sym->type);         /* should always be 1 */
630                         assert(aop->size == 1);
631                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
632                         return (aop);
633                 } else {
634                         sym->aop = aop = newAsmop (AOP_DIR);
635                 aop->aopu.aop_dir = sym->rname ;
636             aop->size = getSize(sym->type);
637                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
638                         pic16_allocDirReg( IC_LEFT(ic) );
639                         return (aop);
640                 }
641         }
642
643     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
644         sym->aop = aop = newAsmop (AOP_DIR);
645         aop->aopu.aop_dir = sym->rname ;
646         aop->size = getSize(sym->type);
647         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
648         pic16_allocDirReg( IC_LEFT(ic) );
649         return aop;
650     }
651
652
653     /* only remaining is far space */
654     sym->aop = aop = newAsmop(AOP_PCODE);
655
656 /* change the next if to 1 to revert to good old immediate code */
657         if(IN_CODESPACE(space)) {
658                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
659                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
660                 PCOI(aop->aopu.pcop)->index = 0;
661         } else {
662                 /* try to allocate via direct register */
663                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
664 //              aop->size = getSize( sym->type );
665         }
666
667         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
668                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
669
670 #if 0
671         if(!pic16_allocDirReg (IC_LEFT(ic)))
672                 return NULL;
673 #endif
674
675         if(IN_DIRSPACE( space ))
676                 aop->size = PTRSIZE;
677         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
678                 aop->size = FPTRSIZE;
679         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
680         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
681         else if(sym->onStack) {
682                 aop->size = PTRSIZE;
683         } else {
684           if(SPEC_SCLS(sym->etype) == S_PDATA) {
685             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
686             aop->size = FPTRSIZE;
687           } else
688                 assert( 0 );
689         }
690
691     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
692
693     /* if it is in code space */
694     if (IN_CODESPACE(space))
695         aop->code = 1;
696
697     return aop;
698 }
699
700 /*-----------------------------------------------------------------*/
701 /* aopForRemat - rematerialzes an object                           */
702 /*-----------------------------------------------------------------*/
703 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
704 {
705   symbol *sym = OP_SYMBOL(op);
706   operand *refop;
707   iCode *ic = NULL, *oldic;
708   asmop *aop = newAsmop(AOP_PCODE);
709   int val = 0;
710   int offset = 0;
711   int viaimmd=0;
712
713     FENTRY2;
714
715         ic = sym->rematiCode;
716
717         if(IS_OP_POINTER(op)) {
718                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
719         }
720
721 //    if(!result)               /* fixme-vr */
722         for (;;) {
723                 oldic = ic;
724
725 //              chat *iLine = printILine(ic);
726 //              pic16_emitpcomment("ic: %s\n", iLine);
727 //              dbuf_free(iLine);
728
729                 if (ic->op == '+') {
730                         val += (int) operandLitValue(IC_RIGHT(ic));
731                 } else if (ic->op == '-') {
732                         val -= (int) operandLitValue(IC_RIGHT(ic));
733                 } else
734                         break;
735
736                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
737         }
738
739         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
740         refop = IC_LEFT(ic);
741
742         if(!op->isaddr)viaimmd++; else viaimmd=0;
743
744 /* set the following if to 1 to revert to good old immediate code */
745         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
746                 || viaimmd) {
747
748                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
749
750                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
751
752 #if 0
753                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
754 #else
755                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
756 #endif
757
758                 PCOI(aop->aopu.pcop)->index = val;
759
760                 aop->size = getSize( sym->type );
761         } else {
762                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
763
764                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
765                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
766
767                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
768         }
769
770
771         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
772                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
773 #if 0
774                 val, IS_PTR_CONST(operandType(op)));
775 #else
776                 val, IS_CODEPTR(operandType(op)));
777 #endif
778
779 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
780
781         pic16_allocDirReg (IC_LEFT(ic));
782
783         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
784                 aop->code = 1;
785
786   return aop;
787 }
788
789 #if 0
790 static int aopIdx (asmop *aop, int offset)
791 {
792   if(!aop)
793     return -1;
794
795   if(aop->type !=  AOP_REG)
796     return -2;
797
798   return aop->aopu.aop_reg[offset]->rIdx;
799
800 }
801 #endif
802
803 /*-----------------------------------------------------------------*/
804 /* regsInCommon - two operands have some registers in common       */
805 /*-----------------------------------------------------------------*/
806 static bool regsInCommon (operand *op1, operand *op2)
807 {
808     symbol *sym1, *sym2;
809     int i;
810
811     /* if they have registers in common */
812     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
813         return FALSE ;
814
815     sym1 = OP_SYMBOL(op1);
816     sym2 = OP_SYMBOL(op2);
817
818     if (sym1->nRegs == 0 || sym2->nRegs == 0)
819         return FALSE ;
820
821     for (i = 0 ; i < sym1->nRegs ; i++) {
822         int j;
823         if (!sym1->regs[i])
824             continue ;
825
826         for (j = 0 ; j < sym2->nRegs ;j++ ) {
827             if (!sym2->regs[j])
828                 continue ;
829
830             if (sym2->regs[j] == sym1->regs[i])
831                 return TRUE ;
832         }
833     }
834
835     return FALSE ;
836 }
837
838 /*-----------------------------------------------------------------*/
839 /* operandsEqu - equivalent                                        */
840 /*-----------------------------------------------------------------*/
841 static bool operandsEqu ( operand *op1, operand *op2)
842 {
843     symbol *sym1, *sym2;
844
845     /* if they not symbols */
846     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
847         return FALSE;
848
849     sym1 = OP_SYMBOL(op1);
850     sym2 = OP_SYMBOL(op2);
851
852     /* if both are itemps & one is spilt
853        and the other is not then false */
854     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
855         sym1->isspilt != sym2->isspilt )
856         return FALSE ;
857
858     /* if they are the same */
859     if (sym1 == sym2)
860         return TRUE ;
861
862     if (sym1->rname[0] && sym2->rname[0]
863         && strcmp (sym1->rname, sym2->rname) == 0)
864         return TRUE;
865
866
867     /* if left is a tmp & right is not */
868     if (IS_ITEMP(op1)  &&
869         !IS_ITEMP(op2) &&
870         sym1->isspilt  &&
871         (sym1->usl.spillLoc == sym2))
872         return TRUE;
873
874     if (IS_ITEMP(op2)  &&
875         !IS_ITEMP(op1) &&
876         sym2->isspilt  &&
877         sym1->level > 0 &&
878         (sym2->usl.spillLoc == sym1))
879         return TRUE ;
880
881     return FALSE ;
882 }
883
884 /*-----------------------------------------------------------------*/
885 /* pic16_sameRegs - two asmops have the same registers                   */
886 /*-----------------------------------------------------------------*/
887 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
888 {
889     int i;
890
891     if (aop1 == aop2)
892         return TRUE ;
893
894     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
895                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
896
897     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
898
899     if (aop1->type != AOP_REG ||
900         aop2->type != AOP_REG )
901         return FALSE ;
902
903     /* This is a bit too restrictive if one is a subset of the other...
904     if (aop1->size != aop2->size )
905         return FALSE ;
906     */
907
908     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
909 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
910
911 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
912         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
913             return FALSE ;
914     }
915
916     return TRUE ;
917 }
918
919 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
920 {
921     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
922                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
923
924     if(aop1 == aop2)return TRUE;
925     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
926
927       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
928
929   return TRUE;
930 }
931
932
933 /*-----------------------------------------------------------------*/
934 /* pic16_aopOp - allocates an asmop for an operand  :                    */
935 /*-----------------------------------------------------------------*/
936 void pic16_aopOp (operand *op, iCode *ic, bool result)
937 {
938     asmop *aop;
939     symbol *sym;
940     int i;
941
942     if (!op)
943         return ;
944
945     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
946
947     /* if this a literal */
948     if (IS_OP_LITERAL(op)) {
949         op->aop = aop = newAsmop(AOP_LIT);
950         aop->aopu.aop_lit = op->operand.valOperand;
951         aop->size = getSize(operandType(op));
952         return;
953     }
954
955     {
956       sym_link *type = operandType(op);
957 #if 0
958       if(IS_PTR_CONST(type))
959 #else
960       if(IS_CODEPTR(type))
961 #endif
962         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
963     }
964
965     /* if already has a asmop then continue */
966     if (op->aop)
967         return ;
968
969     /* if the underlying symbol has a aop */
970     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
971       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
972         op->aop = OP_SYMBOL(op)->aop;
973         return;
974     }
975
976     /* if this is a true symbol */
977     if (IS_TRUE_SYMOP(op)) {
978         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
979       op->aop = aopForSym(ic, op, result);
980       return ;
981     }
982
983     /* this is a temporary : this has
984     only four choices :
985     a) register
986     b) spillocation
987     c) rematerialize
988     d) conditional
989     e) can be a return use only */
990
991     sym = OP_SYMBOL(op);
992
993     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
994     /* if the type is a conditional */
995     if (sym->regType == REG_CND) {
996         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
997         aop->size = 0;
998         return;
999     }
1000
1001     /* if it is spilt then two situations
1002     a) is rematerialize
1003     b) has a spill location */
1004     if (sym->isspilt || sym->nRegs == 0) {
1005
1006 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1007       DEBUGpic16_emitcode(";","%d",__LINE__);
1008         /* rematerialize it NOW */
1009         if (sym->remat) {
1010
1011             sym->aop = op->aop = aop = aopForRemat (op, result);
1012             return;
1013         }
1014
1015 #if 1
1016         if (sym->accuse) {
1017             int i;
1018             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1019             aop->size = getSize(sym->type);
1020             for ( i = 0 ; i < 1 ; i++ ) {
1021                 aop->aopu.aop_str[i] = accUse[i];
1022 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1023             }
1024             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1025             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1026             return;
1027         }
1028 #endif
1029
1030 #if 1
1031         if (sym->ruonly) {
1032           /*
1033           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1034           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1035           //pic16_allocDirReg (IC_LEFT(ic));
1036           aop->size = getSize(sym->type);
1037           */
1038
1039           unsigned i;
1040
1041           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1042           aop->size = getSize(sym->type);
1043           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1044             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1045
1046           DEBUGpic16_emitcode(";","%d",__LINE__);
1047           return;
1048         }
1049 #endif
1050         /* else spill location  */
1051         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1052             /* force a new aop if sizes differ */
1053             sym->usl.spillLoc->aop = NULL;
1054         }
1055
1056 #if 0
1057         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1058                             __FUNCTION__,__LINE__,
1059                             sym->usl.spillLoc->rname,
1060                             sym->rname, sym->usl.spillLoc->offset);
1061 #endif
1062
1063         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1064         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1065           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1066           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1067                                                   getSize(sym->type),
1068                                                   sym->usl.spillLoc->offset, op);
1069         } else if (getSize(sym->type) <= 1) {
1070           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1071           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1072           assert (getSize(sym->type) <= 1);
1073           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1074           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1075         } else {
1076           /* We need some kind of dummy area for getSize(sym->type) byte,
1077            * use WREG for all storage locations.
1078            * XXX: This only works if we are implementing a `dummy read',
1079            *      the stored value will not be retrievable...
1080            *      See #1503234 for a case requiring this. */
1081           sym->aop = op->aop = aop = newAsmop(AOP_REG);
1082           aop->size = getSize(sym->type);
1083           for ( i = 0 ; i < aop->size ;i++)
1084             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1085         }
1086         aop->size = getSize(sym->type);
1087
1088         return;
1089     }
1090
1091     {
1092       sym_link *type = operandType(op);
1093 #if 0
1094       if(IS_PTR_CONST(type))
1095 #else
1096       if(IS_CODEPTR(type))
1097 #endif
1098         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1099     }
1100
1101     /* must be in a register */
1102     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1103     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1104     aop->size = sym->nRegs;
1105     for ( i = 0 ; i < sym->nRegs ;i++)
1106         aop->aopu.aop_reg[i] = sym->regs[i];
1107 }
1108
1109 /*-----------------------------------------------------------------*/
1110 /* pic16_freeAsmop - free up the asmop given to an operand               */
1111 /*----------------------------------------------------------------*/
1112 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1113 {
1114     asmop *aop ;
1115
1116     if (!op)
1117         aop = aaop;
1118     else
1119         aop = op->aop;
1120
1121     if (!aop)
1122         return ;
1123
1124     if (aop->freed)
1125         goto dealloc;
1126
1127     aop->freed = 1;
1128
1129 #if 1
1130     switch (aop->type) {
1131         case AOP_STA:
1132           {
1133             int i;
1134
1135               /* we must store the result on stack */
1136               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1137                 // operands on stack are accessible via "FSR2 + index" with index
1138                 // starting at 2 for arguments and growing from 0 downwards for
1139                 // local variables (index == 0 is not assigned so we add one here)
1140                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1141                 if (soffs <= 0) {
1142                   assert (soffs < 0);
1143                   soffs++;
1144                 } // if
1145                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1146                 for(i=0;i<aop->size;i++) {
1147                   /* initialise for stack access via frame pointer */
1148                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1149                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1150                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1151                 }
1152
1153                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1154               }
1155
1156               if(!_G.resDirect) {
1157                 for(i=0;i<aop->size;i++) {
1158                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1159
1160                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1161                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1162 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1163                   }
1164                 }
1165
1166                 {
1167                   regs *sr;
1168
1169                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1170                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1171                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1172                       deleteSetItem( &_G.sregsAllocSet, sr );
1173                     }
1174                 }
1175               }
1176               _G.resDirect = 0;
1177           }
1178           break;
1179 #if 0
1180         case AOP_STK :
1181         {
1182             int sz = aop->size;
1183             int stk = aop->aopu.aop_stk + aop->size;
1184             bitVectUnSetBit(ic->rUsed,R0_IDX);
1185             bitVectUnSetBit(ic->rUsed,R1_IDX);
1186
1187             getFreePtr(ic,&aop,FALSE);
1188
1189             if (options.stack10bit)
1190             {
1191                 /* I'm not sure what to do here yet... */
1192                 /* #STUB */
1193                 fprintf(stderr,
1194                         "*** Warning: probably generating bad code for "
1195                         "10 bit stack mode.\n");
1196             }
1197
1198             if (stk) {
1199                 pic16_emitcode ("mov","a,_bp");
1200                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1201                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1202             } else {
1203                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1204             }
1205
1206             while (sz--) {
1207                 pic16_emitcode("pop","acc");
1208                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1209                 if (!sz) break;
1210                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1211             }
1212             op->aop = aop;
1213             pic16_freeAsmop(op,NULL,ic,TRUE);
1214             if (_G.r0Pushed) {
1215                 pic16_emitcode("pop","ar0");
1216                 _G.r0Pushed--;
1217             }
1218
1219             if (_G.r1Pushed) {
1220                 pic16_emitcode("pop","ar1");
1221                 _G.r1Pushed--;
1222             }
1223         }
1224 #endif
1225
1226     }
1227 #endif
1228
1229 dealloc:
1230     /* all other cases just dealloc */
1231     if (op ) {
1232         op->aop = NULL;
1233         if (IS_SYMOP(op)) {
1234             OP_SYMBOL(op)->aop = NULL;
1235             /* if the symbol has a spill */
1236             if (SPIL_LOC(op))
1237                 SPIL_LOC(op)->aop = NULL;
1238         }
1239     }
1240 }
1241
1242 /*-----------------------------------------------------------------*/
1243 /* pic16_aopGet - for fetching value of the aop                          */
1244 /*-----------------------------------------------------------------*/
1245 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1246 {
1247     char *s = buffer ;
1248     char *rs;
1249
1250     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1251
1252     /* offset is greater than size then zero */
1253     if (offset > (aop->size - 1) &&
1254         aop->type != AOP_LIT)
1255         return zero;
1256
1257     /* depending on type */
1258     switch (aop->type) {
1259     case AOP_DIR:
1260       if (offset) {
1261         sprintf(s,"(%s + %d)",
1262                 aop->aopu.aop_dir,
1263                 offset);
1264         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1265       } else
1266             sprintf(s,"%s",aop->aopu.aop_dir);
1267         rs = Safe_calloc(1,strlen(s)+1);
1268         strcpy(rs,s);
1269         return rs;
1270
1271     case AOP_REG:
1272       return aop->aopu.aop_reg[offset]->name;
1273
1274     case AOP_CRY:
1275       return aop->aopu.aop_dir;
1276
1277     case AOP_ACC:
1278         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1279 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1280 //        assert( 0 );
1281 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1282         rs = Safe_strdup("WREG");
1283         return (rs);
1284
1285     case AOP_LIT:
1286         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1287         rs = Safe_calloc(1,strlen(s)+1);
1288         strcpy(rs,s);
1289         return rs;
1290
1291     case AOP_STR:
1292         aop->coff = offset ;
1293
1294 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1295 //          dname)
1296 //          return "acc";
1297         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1298           aop->type = AOP_ACC;
1299           return Safe_strdup("_WREG");
1300         }
1301         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1302
1303         return aop->aopu.aop_str[offset];
1304
1305     case AOP_PCODE:
1306       {
1307         pCodeOp *pcop = aop->aopu.pcop;
1308         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1309         if(pcop->name) {
1310           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1311           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1312           if (offset) {
1313             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1314           } else {
1315             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1316           }
1317         } else
1318           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1319
1320       }
1321       rs = Safe_calloc(1,strlen(s)+1);
1322       strcpy(rs,s);
1323       return rs;
1324
1325 #if 0
1326     case AOP_PAGED:
1327       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1328       if (offset) {
1329         sprintf(s,"(%s + %d)",
1330                 aop->aopu.aop_dir,
1331                 offset);
1332       } else
1333             sprintf(s,"%s",aop->aopu.aop_dir);
1334       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1335       rs = Safe_calloc(1,strlen(s)+1);
1336       strcpy(rs,s);
1337       return rs;
1338 #endif
1339
1340     case AOP_STA:
1341         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1342         return (rs);
1343
1344     case AOP_STK:
1345 //        pCodeOp *pcop = aop->aop
1346         break;
1347
1348     }
1349
1350     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1351     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1352            "aopget got unsupported aop->type");
1353     exit(0);
1354 }
1355
1356
1357
1358 /* lock has the following meaning: When allocating temporary registers
1359  * for stack variables storage, the value of the temporary register is
1360  * saved on stack. Its value is restored at the end. This procedure is
1361  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1362  * a possibility that before a call to pic16_aopOp, a temporary register
1363  * is allocated for a while and it is freed after some time, this will
1364  * mess the stack and values will not be restored properly. So use lock=1
1365  * to allocate temporary registers used internally by the programmer, and
1366  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1367  * to inform the compiler developer about a possible bug. This is an internal
1368  * feature for developing the compiler -- VR */
1369
1370 int _TempReg_lock = 0;
1371 /*-----------------------------------------------------------------*/
1372 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1373 /*-----------------------------------------------------------------*/
1374 pCodeOp *pic16_popGetTempReg(int lock)
1375 {
1376   pCodeOp *pcop=NULL;
1377   symbol *cfunc;
1378
1379 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1380     if(_TempReg_lock) {
1381 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1382     }
1383
1384     _TempReg_lock += lock;
1385
1386     cfunc = currFunc;
1387     currFunc = NULL;
1388
1389     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1390     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1391       PCOR(pcop)->r->wasUsed=1;
1392       PCOR(pcop)->r->isFree=0;
1393
1394       /* push value on stack */
1395       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1396     }
1397
1398     currFunc = cfunc;
1399
1400   return pcop;
1401 }
1402
1403 /*-----------------------------------------------------------------*/
1404 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1405 /*                           is not part of f, but don't save if   */
1406 /*                           inside v                              */
1407 /*-----------------------------------------------------------------*/
1408 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1409 {
1410   pCodeOp *pcop=NULL;
1411   symbol *cfunc;
1412   int i;
1413
1414 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1415
1416     if(_TempReg_lock) {
1417 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1418     }
1419
1420     _TempReg_lock += lock;
1421
1422     cfunc = currFunc;
1423     currFunc = NULL;
1424
1425     i = bitVectFirstBit(f);
1426     while(i < 128) {
1427
1428       /* bypass registers that are used by function */
1429       if(!bitVectBitValue(f, i)) {
1430
1431         /* bypass registers that are already allocated for stack access */
1432         if(!bitVectBitValue(v, i))  {
1433
1434 //          debugf("getting register rIdx = %d\n", i);
1435           /* ok, get the operand */
1436           pcop = pic16_newpCodeOpReg( i );
1437
1438           /* should never by NULL */
1439           assert( pcop != NULL );
1440
1441
1442           /* sanity check */
1443           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1444             int found=0;
1445
1446               PCOR(pcop)->r->wasUsed=1;
1447               PCOR(pcop)->r->isFree=0;
1448
1449
1450               {
1451                 regs *sr;
1452
1453                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1454
1455                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1456                       /* already used in previous steps, break */
1457                       found=1;
1458                       break;
1459                     }
1460                   }
1461               }
1462
1463               /* caller takes care of the following */
1464 //              bitVectSetBit(v, i);
1465
1466               if(!found) {
1467                 /* push value on stack */
1468                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1469                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1470               }
1471
1472             break;
1473           }
1474         }
1475       }
1476       i++;
1477     }
1478
1479     currFunc = cfunc;
1480
1481   return pcop;
1482 }
1483
1484
1485 /*-----------------------------------------------------------------*/
1486 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1487 /*-----------------------------------------------------------------*/
1488 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1489 {
1490   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1491
1492   _TempReg_lock -= lock;
1493
1494   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1495     PCOR(pcop)->r->isFree = 1;
1496
1497     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1498   }
1499 }
1500 /*-----------------------------------------------------------------*/
1501 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1502 /*-----------------------------------------------------------------*/
1503 pCodeOp *pic16_popGetLabel(int key)
1504 {
1505
1506   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1507
1508   if(key>max_key)
1509     max_key = key;
1510
1511   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1512 }
1513
1514 /*-----------------------------------------------------------------*/
1515 /* pic16_popCopyReg - copy a pcode operator                              */
1516 /*-----------------------------------------------------------------*/
1517 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1518 {
1519   pCodeOpReg *pcor;
1520
1521   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1522   memcpy (pcor, pc, sizeof (pCodeOpReg));
1523   pcor->r->wasUsed = 1;
1524
1525   //pcor->pcop.type = pc->pcop.type;
1526   if(pc->pcop.name) {
1527     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1528       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1529   } else
1530     pcor->pcop.name = NULL;
1531
1532   //pcor->r = pc->r;
1533   //pcor->rIdx = pc->rIdx;
1534   //pcor->r->wasUsed=1;
1535   //pcor->instance = pc->instance;
1536
1537 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1538
1539   return PCOP(pcor);
1540 }
1541
1542 /*-----------------------------------------------------------------*/
1543 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1544 /*-----------------------------------------------------------------*/
1545 pCodeOp *pic16_popGetLit(int lit)
1546 {
1547   return pic16_newpCodeOpLit(lit);
1548 }
1549
1550 /* Allow for 12 bit literals (LFSR x, <here!>). */
1551 pCodeOp *pic16_popGetLit12(int lit)
1552 {
1553   return pic16_newpCodeOpLit12(lit);
1554 }
1555
1556 /*-----------------------------------------------------------------*/
1557 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1558 /*-----------------------------------------------------------------*/
1559 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1560 {
1561   return pic16_newpCodeOpLit2(lit, arg2);
1562 }
1563
1564
1565 /*-----------------------------------------------------------------*/
1566 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1567 /*-----------------------------------------------------------------*/
1568 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1569 {
1570   return pic16_newpCodeOpImmd(name, offset,index, 0);
1571 }
1572
1573
1574 /*-----------------------------------------------------------------*/
1575 /* pic16_popGet - asm operator to pcode operator conversion              */
1576 /*-----------------------------------------------------------------*/
1577 pCodeOp *pic16_popGetWithString(char *str)
1578 {
1579   pCodeOp *pcop;
1580
1581
1582   if(!str) {
1583     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1584     exit (1);
1585   }
1586
1587   pcop = pic16_newpCodeOp(str,PO_STR);
1588
1589   return pcop;
1590 }
1591
1592 /*-----------------------------------------------------------------*/
1593 /* pic16_popRegFromString -                                        */
1594 /*-----------------------------------------------------------------*/
1595 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1596 {
1597
1598   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1599   pcop->type = PO_DIR;
1600
1601   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1602   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1603
1604   if(!str)
1605     str = "BAD_STRING";
1606
1607   pcop->name = Safe_calloc(1,strlen(str)+1);
1608   strcpy(pcop->name,str);
1609
1610   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1611
1612   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1613 //  PCOR(pcop)->r->wasUsed = 1;
1614
1615   /* make sure that register doesn't exist,
1616    * and operand isn't NULL
1617    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1618   if((PCOR(pcop)->r == NULL)
1619     && (op)
1620     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1621 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1622 //              __FUNCTION__, __LINE__, str, size, offset);
1623
1624     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1625     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1626
1627   }
1628   PCOR(pcop)->instance = offset;
1629
1630   return pcop;
1631 }
1632
1633 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1634 {
1635   pCodeOp *pcop;
1636
1637 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1638 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1639
1640         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1641         PCOR(pcop)->rIdx = rIdx;
1642         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1643         if(!PCOR(pcop)->r)
1644                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1645
1646         PCOR(pcop)->r->isFree = 0;
1647         PCOR(pcop)->r->wasUsed = 1;
1648
1649         pcop->type = PCOR(pcop)->r->pc_type;
1650
1651   return pcop;
1652 }
1653
1654 /*---------------------------------------------------------------------------------*/
1655 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1656 /*                 VR 030601                                                       */
1657 /*---------------------------------------------------------------------------------*/
1658 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1659 {
1660   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1661         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
1662   return PCOP(pcop2);
1663 }
1664
1665
1666
1667 /*--------------------------------------------------------------------------------.-*/
1668 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1669 /*                  VR 030601 , adapted by Hans Dorn                                */
1670 /*--------------------------------------------------------------------------------.-*/
1671 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1672 {
1673   pCodeOp2 *pcop2;
1674   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
1675   return PCOP(pcop2);
1676 }
1677
1678 /*---------------------------------------------------------------------------------*/
1679 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1680 /*                     movff instruction                                           */
1681 /*---------------------------------------------------------------------------------*/
1682 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1683 {
1684   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1685         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
1686
1687   return PCOP(pcop2);
1688 }
1689
1690
1691 /*-----------------------------------------------------------------*/
1692 /* pic16_popGet - asm operator to pcode operator conversion              */
1693 /*-----------------------------------------------------------------*/
1694 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1695 {
1696 //  char *s = buffer ;
1697 //  char *rs;
1698   pCodeOp *pcop;
1699
1700     FENTRY2;
1701
1702       /* offset is greater than size then zero */
1703
1704 //    if (offset > (aop->size - 1) &&
1705 //        aop->type != AOP_LIT)
1706 //      return NULL;  //zero;
1707
1708     /* depending on type */
1709     switch (aop->type) {
1710                 case AOP_STA:
1711                         /* pCodeOp is already allocated from aopForSym */
1712                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1713                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1714                         return (pcop);
1715
1716                 case AOP_ACC:
1717                         {
1718                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
1719
1720                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1721
1722                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1723
1724                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1725                                 PCOR(pcop)->rIdx = rIdx;
1726                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1727                                 PCOR(pcop)->r->wasUsed=1;
1728                                 PCOR(pcop)->r->isFree=0;
1729
1730                                 PCOR(pcop)->instance = offset;
1731                                 pcop->type = PCOR(pcop)->r->pc_type;
1732 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1733                                 return pcop;
1734
1735
1736 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1737 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1738
1739 //      assert( 0 );
1740                         }
1741
1742     case AOP_DIR:
1743       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
1744       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1745
1746 #if 0
1747     case AOP_PAGED:
1748       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1749       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1750 #endif
1751
1752     case AOP_REG:
1753       {
1754         int rIdx;
1755
1756 //      debugf2("aop = %p\toffset = %d\n", aop, offset);
1757 //      assert (aop && aop->aopu.aop_reg[offset] != NULL);
1758         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1759
1760         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1761
1762         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1763 //      pcop->type = PO_GPR_REGISTER;
1764         PCOR(pcop)->rIdx = rIdx;
1765         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1766         PCOR(pcop)->r->wasUsed=1;
1767         PCOR(pcop)->r->isFree=0;
1768
1769         PCOR(pcop)->instance = offset;
1770         pcop->type = PCOR(pcop)->r->pc_type;
1771
1772         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
1773 //      rs = aop->aopu.aop_reg[offset]->name;
1774 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1775         return pcop;
1776       }
1777
1778     case AOP_CRY:
1779         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1780
1781       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1782       PCOR(pcop)->instance = offset;
1783       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1784       //if(PCOR(pcop)->r == NULL)
1785       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1786       return pcop;
1787
1788     case AOP_LIT:
1789         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1790       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1791
1792     case AOP_STR:
1793       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1794       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1795
1796       /*
1797       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1798       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1799       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1800       pcop->type = PCOR(pcop)->r->pc_type;
1801       pcop->name = PCOR(pcop)->r->name;
1802
1803       return pcop;
1804       */
1805
1806     case AOP_PCODE:
1807       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1808                           __LINE__,
1809                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1810       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1811       switch( aop->aopu.pcop->type ) {
1812         case PO_DIR: PCOR(pcop)->instance += offset; break;
1813         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1814         case PO_WREG:
1815             assert (offset==0);
1816             break;
1817         default:
1818           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
1819           assert( 0 );  /* should never reach here */;
1820       }
1821       return pcop;
1822     }
1823
1824     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1825            "pic16_popGet got unsupported aop->type");
1826     exit(0);
1827 }
1828 /*-----------------------------------------------------------------*/
1829 /* pic16_aopPut - puts a string for a aop                                */
1830 /*-----------------------------------------------------------------*/
1831 void pic16_aopPut (asmop *aop, char *s, int offset)
1832 {
1833     char *d = buffer ;
1834     symbol *lbl ;
1835
1836     return;
1837
1838     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1839
1840     if (aop->size && offset > ( aop->size - 1)) {
1841         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1842                "pic16_aopPut got offset > aop->size");
1843         exit(0);
1844     }
1845
1846     /* will assign value to value */
1847     /* depending on where it is ofcourse */
1848     switch (aop->type) {
1849     case AOP_DIR:
1850       if (offset) {
1851         sprintf(d,"(%s + %d)",
1852                 aop->aopu.aop_dir,offset);
1853         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1854
1855       } else
1856             sprintf(d,"%s",aop->aopu.aop_dir);
1857
1858         if (strcmp(d,s)) {
1859           DEBUGpic16_emitcode(";","%d",__LINE__);
1860           if(strcmp(s,"W"))
1861             pic16_emitcode("movf","%s,w",s);
1862           pic16_emitcode("movwf","%s",d);
1863
1864           if(strcmp(s,"W")) {
1865             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1866             if(offset >= aop->size) {
1867               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1868               break;
1869             } else
1870               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1871           }
1872
1873           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1874
1875
1876         }
1877         break;
1878
1879     case AOP_REG:
1880       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1881         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1882           /*
1883             if (*s == '@'           ||
1884                 strcmp(s,"r0") == 0 ||
1885                 strcmp(s,"r1") == 0 ||
1886                 strcmp(s,"r2") == 0 ||
1887                 strcmp(s,"r3") == 0 ||
1888                 strcmp(s,"r4") == 0 ||
1889                 strcmp(s,"r5") == 0 ||
1890                 strcmp(s,"r6") == 0 ||
1891                 strcmp(s,"r7") == 0 )
1892                 pic16_emitcode("mov","%s,%s  ; %d",
1893                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1894             else
1895           */
1896
1897           if(strcmp(s,"W")==0 )
1898             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1899
1900           pic16_emitcode("movwf","%s",
1901                    aop->aopu.aop_reg[offset]->name);
1902
1903           if(strcmp(s,zero)==0) {
1904             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1905
1906           } else if(strcmp(s,"W")==0) {
1907             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1908             pcop->type = PO_GPR_REGISTER;
1909
1910             PCOR(pcop)->rIdx = -1;
1911             PCOR(pcop)->r = NULL;
1912
1913             DEBUGpic16_emitcode(";","%d",__LINE__);
1914             pcop->name = Safe_strdup(s);
1915             pic16_emitpcode(POC_MOVFW,pcop);
1916             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1917           } else if(strcmp(s,one)==0) {
1918             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1919             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1920           } else {
1921             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1922           }
1923         }
1924         break;
1925
1926     case AOP_STK:
1927         if (strcmp(s,"a") == 0)
1928             pic16_emitcode("push","acc");
1929         else
1930             pic16_emitcode("push","%s",s);
1931
1932         break;
1933
1934     case AOP_CRY:
1935         /* if bit variable */
1936         if (!aop->aopu.aop_dir) {
1937             pic16_emitcode("clr","a");
1938             pic16_emitcode("rlc","a");
1939         } else {
1940             if (s == zero)
1941                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1942             else
1943                 if (s == one)
1944                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1945                 else
1946                     if (!strcmp(s,"c"))
1947                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1948                     else {
1949                         lbl = newiTempLabel(NULL);
1950
1951                         if (strcmp(s,"a")) {
1952                             MOVA(s);
1953                         }
1954                         pic16_emitcode("clr","c");
1955                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1956                         pic16_emitcode("cpl","c");
1957                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1958                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1959                     }
1960         }
1961         break;
1962
1963     case AOP_STR:
1964         aop->coff = offset;
1965         if (strcmp(aop->aopu.aop_str[offset],s))
1966             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1967         break;
1968
1969     case AOP_ACC:
1970         aop->coff = offset;
1971         if (!offset && (strcmp(s,"acc") == 0))
1972             break;
1973
1974         if (strcmp(aop->aopu.aop_str[offset],s))
1975             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1976         break;
1977
1978     default :
1979         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
1980 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1981 //             "pic16_aopPut got unsupported aop->type");
1982 //      exit(0);
1983     }
1984
1985 }
1986
1987 /*-----------------------------------------------------------------*/
1988 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
1989 /*-----------------------------------------------------------------*/
1990 void pic16_mov2w (asmop *aop, int offset)
1991 {
1992   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1993
1994   if(pic16_isLitAop(aop))
1995     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1996   else
1997     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1998 }
1999
2000 void pic16_mov2w_volatile (asmop *aop)
2001 {
2002   int i;
2003
2004   if(!pic16_isLitAop(aop)) {
2005     // may need to protect this from the peepholer -- this is not nice but works...
2006     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
2007     for (i = 0; i < aop->size; i++) {
2008       if (i > 0) {
2009         pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - MORE"));
2010       } // if
2011       pic16_emitpcode(POC_MOVFW, pic16_popGet(aop, i));
2012     } // for
2013     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
2014   }
2015 }
2016
2017 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2018 {
2019   if(pic16_isLitAop(src)) {
2020     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2021     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2022   } else {
2023     if(pic16_sameRegsOfs(src, dst, offset))return;
2024     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2025                       pic16_popGet(dst, offset)));
2026   }
2027 }
2028
2029 static void pic16_movLit2f(pCodeOp *pc, int lit)
2030 {
2031   if (0 == (lit & 0x00ff))
2032   {
2033     pic16_emitpcode (POC_CLRF, pc);
2034   } else if (0xff == (lit & 0x00ff))
2035   {
2036     pic16_emitpcode (POC_SETF, pc);
2037   } else {
2038     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2039     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2040   }
2041 }
2042
2043 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2044 {
2045   if(pic16_isLitAop(src)) {
2046     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2047     pic16_emitpcode(POC_MOVWF, dst);
2048   } else {
2049     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2050   }
2051 }
2052
2053 void pic16_testStackOverflow(void)
2054 {
2055 #define GSTACK_TEST_NAME        "_gstack_test"
2056
2057   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2058
2059   {
2060     symbol *sym;
2061
2062       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2063       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2064 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2065       checkAddSym(&externs, sym);
2066   }
2067
2068 }
2069
2070 /* push pcop into stack */
2071 void pic16_pushpCodeOp(pCodeOp *pcop)
2072 {
2073 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2074   if (pcop->type == PO_LITERAL) {
2075     pic16_emitpcode(POC_MOVLW, pcop);
2076     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2077   } else {
2078     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2079   }
2080   if(pic16_options.gstack)
2081     pic16_testStackOverflow();
2082
2083 }
2084
2085 /* pop pcop from stack */
2086 void pic16_poppCodeOp(pCodeOp *pcop)
2087 {
2088   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2089   if(pic16_options.gstack)
2090     pic16_testStackOverflow();
2091 }
2092
2093
2094 /*-----------------------------------------------------------------*/
2095 /* pushw - pushes wreg to stack                                    */
2096 /*-----------------------------------------------------------------*/
2097 void pushw(void)
2098 {
2099   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2100   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2101   if(pic16_options.gstack)
2102     pic16_testStackOverflow();
2103 }
2104
2105
2106 /*-----------------------------------------------------------------*/
2107 /* pushaop - pushes aop to stack                                   */
2108 /*-----------------------------------------------------------------*/
2109 void pushaop(asmop *aop, int offset)
2110 {
2111   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2112
2113   if(_G.resDirect)return;
2114
2115   if(pic16_isLitAop(aop)) {
2116     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2117     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2118   } else {
2119     pic16_emitpcode(POC_MOVFF,
2120       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2121   }
2122
2123   if(pic16_options.gstack)
2124     pic16_testStackOverflow();
2125 }
2126
2127 /*-----------------------------------------------------------------*/
2128 /* popaop - pops aop from stack                                    */
2129 /*-----------------------------------------------------------------*/
2130 void popaop(asmop *aop, int offset)
2131 {
2132   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2133   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2134   if(pic16_options.gstack)
2135     pic16_testStackOverflow();
2136 }
2137
2138 void popaopidx(asmop *aop, int offset, int index)
2139 {
2140   int ofs=1;
2141
2142     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2143
2144     if(STACK_MODEL_LARGE)ofs++;
2145
2146     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2147     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2148     if(pic16_options.gstack)
2149       pic16_testStackOverflow();
2150 }
2151
2152 /*-----------------------------------------------------------------*/
2153 /* pic16_getDataSize - get the operand data size                         */
2154 /*-----------------------------------------------------------------*/
2155 int pic16_getDataSize(operand *op)
2156 {
2157     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2158
2159
2160     return AOP_SIZE(op);
2161
2162     // tsd- in the pic port, the genptr size is 1, so this code here
2163     // fails. ( in the 8051 port, the size was 4).
2164 #if 0
2165     int size;
2166     size = AOP_SIZE(op);
2167     if (size == GPTRSIZE)
2168     {
2169         sym_link *type = operandType(op);
2170         if (IS_GENPTR(type))
2171         {
2172             /* generic pointer; arithmetic operations
2173              * should ignore the high byte (pointer type).
2174              */
2175             size--;
2176     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2177         }
2178     }
2179     return size;
2180 #endif
2181 }
2182
2183 /*-----------------------------------------------------------------*/
2184 /* pic16_outAcc - output Acc                                             */
2185 /*-----------------------------------------------------------------*/
2186 void pic16_outAcc(operand *result)
2187 {
2188   int size,offset;
2189   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2190   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2191
2192
2193   size = pic16_getDataSize(result);
2194   if(size){
2195     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2196     size--;
2197     offset = 1;
2198     /* unsigned or positive */
2199     while(size--)
2200       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2201   }
2202
2203 }
2204
2205 /*-----------------------------------------------------------------*/
2206 /* pic16_outBitC - output a bit C                                  */
2207 /*                 Move to result the value of Carry flag -- VR    */
2208 /*-----------------------------------------------------------------*/
2209 void pic16_outBitC(operand *result)
2210 {
2211   int i;
2212
2213     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2214
2215     /* if the result is bit */
2216     if (AOP_TYPE(result) == AOP_CRY) {
2217         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2218         pic16_aopPut(AOP(result),"c",0);
2219     } else {
2220
2221         i = AOP_SIZE(result);
2222         while(i--) {
2223                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2224         }
2225         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2226     }
2227 }
2228
2229 /*-----------------------------------------------------------------*/
2230 /* pic16_outBitOp - output a bit from Op                           */
2231 /*                 Move to result the value of set/clr op -- VR    */
2232 /*-----------------------------------------------------------------*/
2233 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2234 {
2235   int i;
2236
2237     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2238
2239     /* if the result is bit */
2240     if (AOP_TYPE(result) == AOP_CRY) {
2241         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2242         pic16_aopPut(AOP(result),"c",0);
2243     } else {
2244
2245         i = AOP_SIZE(result);
2246         while(i--) {
2247                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2248         }
2249         pic16_emitpcode(POC_RRCF, pcop);
2250         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2251     }
2252 }
2253
2254 /*-----------------------------------------------------------------*/
2255 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2256 /*-----------------------------------------------------------------*/
2257 void pic16_toBoolean(operand *oper)
2258 {
2259     int size = AOP_SIZE(oper) - 1;
2260     int offset = 1;
2261
2262     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2263
2264     if ( AOP_TYPE(oper) != AOP_ACC) {
2265       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2266     }
2267     while (size--) {
2268       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2269     }
2270 }
2271
2272 /*-----------------------------------------------------------------*/
2273 /* genUminusFloat - unary minus for floating points                */
2274 /*-----------------------------------------------------------------*/
2275 static void genUminusFloat(operand *op,operand *result)
2276 {
2277   int size ,offset =0 ;
2278
2279     FENTRY;
2280     /* for this we just need to flip the
2281     first it then copy the rest in place */
2282     size = AOP_SIZE(op);
2283     assert( size == AOP_SIZE(result) );
2284
2285     while(size--) {
2286       pic16_mov2f(AOP(result), AOP(op), offset);
2287       offset++;
2288     }
2289
2290     /* toggle the MSB's highest bit */
2291     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2292 }
2293
2294 /*-----------------------------------------------------------------*/
2295 /* genUminus - unary minus code generation                         */
2296 /*-----------------------------------------------------------------*/
2297 static void genUminus (iCode *ic)
2298 {
2299   int size, i;
2300   sym_link *optype, *rtype;
2301   symbol *label;
2302   int needLabel=0;
2303
2304     FENTRY;
2305
2306     /* assign asmops */
2307     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2308     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2309
2310     /* if both in bit space then special case */
2311     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2312       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2313
2314         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2315         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2316         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2317         goto release;
2318     }
2319
2320     optype = operandType(IC_LEFT(ic));
2321     rtype = operandType(IC_RESULT(ic));
2322
2323
2324     /* if float then do float stuff */
2325     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2326       if(IS_FIXED(optype))
2327         debugf("implement fixed16x16 type\n", 0);
2328
2329         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2330         goto release;
2331     }
2332
2333     /* otherwise subtract from zero by taking the 2's complement */
2334     size = AOP_SIZE(IC_LEFT(ic));
2335     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2336     label = newiTempLabel ( NULL );
2337
2338     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2339       for (i=size-1; i > 0; i--) {
2340         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2341       } // for
2342       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2343       for (i=1; i < size; i++) {
2344         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2345         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2346       } // for
2347     } else {
2348       for (i=size-1; i >= 0; i--) {
2349         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2350         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2351       } // for
2352       if (size > 1) {
2353         for (i=0; i < size-2; i++) {
2354           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2355           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2356         } // for
2357         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2358       } // if
2359       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2360     }
2361     if (needLabel)
2362       pic16_emitpLabel (label->key);
2363
2364 release:
2365     /* release the aops */
2366     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2367     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2368 }
2369
2370 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2371 {
2372   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2373     pic16_emitpcode(POC_MOVFW, src);
2374     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2375   } else {
2376     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2377         src, pic16_popGet(AOP(op), offset)));
2378   }
2379 }
2380
2381
2382 /*-----------------------------------------------------------------*/
2383 /* assignResultValue - assign results to oper, rescall==1 is       */
2384 /*                     called from genCall() or genPcall()         */
2385 /*-----------------------------------------------------------------*/
2386 static void assignResultValue(operand * oper, int res_size, int rescall)
2387 {
2388   int size = AOP_SIZE(oper);
2389   int offset=0;
2390
2391     FENTRY2;
2392 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2393     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2394
2395     if(rescall) {
2396       /* assign result from a call/pcall function() */
2397
2398       /* function results are stored in a special order,
2399        * see top of file with Function return policy, or manual */
2400
2401       if(size <= 4) {
2402         /* 8-bits, result in WREG */
2403         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2404
2405         if(size > 1 && res_size > 1) {
2406           /* 16-bits, result in PRODL:WREG */
2407           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2408         }
2409
2410         if(size > 2 && res_size > 2) {
2411           /* 24-bits, result in PRODH:PRODL:WREG */
2412           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2413         }
2414
2415         if(size > 3 && res_size > 3) {
2416           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2417           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2418         }
2419
2420         pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
2421
2422       } else {
2423         /* >32-bits, result on stack, and FSR0 points to beginning.
2424          * Fix stack when done */
2425         /* FIXME FIXME */
2426 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2427         while (size--) {
2428 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2429 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2430
2431           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2432           GpsuedoStkPtr++;
2433         }
2434
2435         /* fix stack */
2436         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2437         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2438         if(STACK_MODEL_LARGE) {
2439           emitSKPNC;
2440           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2441         }
2442       }
2443     } else {
2444       int areg = 0;             /* matching argument register */
2445
2446 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2447       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2448
2449
2450       /* its called from genReceive (probably) -- VR */
2451       /* I hope this code will not be called from somewhere else in the future!
2452        * We manually set the pseudo stack pointer in genReceive. - dw
2453        */
2454       if(!GpsuedoStkPtr && _G.useWreg) {
2455 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2456
2457         /* The last byte in the assignment is in W */
2458         if(areg <= GpsuedoStkPtr) {
2459           size--;
2460           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2461           offset++;
2462 //          debugf("receive from WREG\n", 0);
2463         }
2464         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2465       }
2466 //      GpsuedoStkPtr++;
2467       _G.stack_lat = AOP_SIZE(oper)-1;
2468
2469       while (size) {
2470         size--;
2471         GpsuedoStkPtr++;
2472         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2473 //        debugf("receive from STACK\n", 0);
2474         offset++;
2475       }
2476     }
2477 }
2478
2479
2480 /*-----------------------------------------------------------------*/
2481 /* genIpush - generate code for pushing this gets a little complex */
2482 /*-----------------------------------------------------------------*/
2483 static void genIpush (iCode *ic)
2484 {
2485 //  int size, offset=0;
2486
2487   FENTRY;
2488   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2489
2490   if(ic->parmPush) {
2491     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2492
2493     /* send to stack as normal */
2494     addSet(&_G.sendSet,ic);
2495 //    addSetHead(&_G.sendSet,ic);
2496     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2497   }
2498
2499
2500 #if 0
2501     int size, offset = 0 ;
2502     char *l;
2503
2504
2505     /* if this is not a parm push : ie. it is spill push
2506     and spill push is always done on the local stack */
2507     if (!ic->parmPush) {
2508
2509         /* and the item is spilt then do nothing */
2510         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2511             return ;
2512
2513         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2514         size = AOP_SIZE(IC_LEFT(ic));
2515         /* push it on the stack */
2516         while(size--) {
2517             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2518             if (*l == '#') {
2519                 MOVA(l);
2520                 l = "acc";
2521             }
2522             pic16_emitcode("push","%s",l);
2523         }
2524         return ;
2525     }
2526
2527     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2528 #endif
2529 }
2530
2531 /*-----------------------------------------------------------------*/
2532 /* genIpop - recover the registers: can happen only for spilling   */
2533 /*-----------------------------------------------------------------*/
2534 static void genIpop (iCode *ic)
2535 {
2536   FENTRY;
2537   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2538 #if 0
2539     int size,offset ;
2540
2541
2542     /* if the temp was not pushed then */
2543     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2544         return ;
2545
2546     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2547     size = AOP_SIZE(IC_LEFT(ic));
2548     offset = (size-1);
2549     while (size--)
2550         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2551                                    FALSE,TRUE));
2552
2553     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2554 #endif
2555 }
2556
2557 static int wparamCmp(void *p1, void *p2)
2558 {
2559   return (!strcmp((char *)p1, (char *)p2));
2560 }
2561
2562 int inWparamList(char *s)
2563 {
2564   return isinSetWith(wparamList, s, wparamCmp);
2565 }
2566
2567
2568 /*-----------------------------------------------------------------*/
2569 /* genCall - generates a call statement                            */
2570 /*-----------------------------------------------------------------*/
2571 static void genCall (iCode *ic)
2572 {
2573   sym_link *ftype;
2574   int stackParms=0;
2575   int use_wreg=0;
2576   int inwparam=0;
2577   char *fname;
2578
2579     FENTRY;
2580
2581     ftype = OP_SYM_TYPE(IC_LEFT(ic));
2582     /* if caller saves & we have not saved then */
2583 //    if (!ic->regsSaved)
2584 //      saveRegisters(ic);
2585
2586         /* initialise stackParms for IPUSH pushes */
2587 //      stackParms = psuedoStkPtr;
2588 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2589     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
2590     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
2591
2592 #if 0
2593     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
2594 #endif
2595
2596     /* if send set is not empty the assign */
2597     if (_G.sendSet) {
2598       iCode *sic;
2599       int psuedoStkPtr=-1;
2600       int firstTimeThruLoop = 1;
2601
2602
2603         /* reverse sendSet if function is not reentrant */
2604         if(!IFFUNC_ISREENT(ftype))
2605           _G.sendSet = reverseSet(_G.sendSet);
2606
2607         /* First figure how many parameters are getting passed */
2608         stackParms = 0;
2609         use_wreg = 0;
2610
2611         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2612           int size;
2613 //          int offset = 0;
2614
2615             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2616             size = AOP_SIZE(IC_LEFT(sic));
2617
2618             stackParms += size;
2619
2620             /* pass the last byte through WREG */
2621             if(inwparam) {
2622
2623               while (size--) {
2624                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2625                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2626                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2627
2628                 if(!firstTimeThruLoop) {
2629                   /* If this is not the first time we've been through the loop
2630                    * then we need to save the parameter in a temporary
2631                    * register. The last byte of the last parameter is
2632                    * passed in W. */
2633
2634                   pushw();
2635 //                  --psuedoStkPtr;             // sanity check
2636                   use_wreg = 1;
2637                 }
2638
2639                 firstTimeThruLoop=0;
2640
2641                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2642
2643 //                offset++;
2644               }
2645             } else {
2646               /* all arguments are passed via stack */
2647               use_wreg = 0;
2648
2649               while (size--) {
2650                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2651                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2652                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2653
2654 //                pushaop(AOP(IC_LEFT(sic)), size);
2655                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
2656
2657                 if(!_G.resDirect)
2658                   pushw();
2659               }
2660             }
2661
2662             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2663           }
2664
2665           if(inwparam) {
2666             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
2667               pushw();  /* save last parameter to stack if functions has varargs */
2668               use_wreg = 0;
2669             } else
2670               use_wreg = 1;
2671           } else use_wreg = 0;
2672
2673           _G.stackRegSet = _G.sendSet;
2674           _G.sendSet = NULL;
2675     }
2676
2677     /* make the call */
2678     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
2679
2680     GpsuedoStkPtr=0;
2681
2682     /* if we need to assign a result value */
2683     if ((IS_ITEMP(IC_RESULT(ic))
2684           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2685               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2686         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2687
2688       _G.accInUse++;
2689       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2690       _G.accInUse--;
2691
2692       /* Must not assign an 8-bit result to a 16-bit variable;
2693        * this would use (used...) the uninitialized PRODL! */
2694       /* FIXME: Need a proper way to obtain size of function result type,
2695        * OP_SYM_ETYPE does not work: it dereferences pointer types! */
2696       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
2697
2698       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2699                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2700
2701       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2702     }
2703
2704     if(!stackParms && ic->parmBytes) {
2705       stackParms = ic->parmBytes;
2706     }
2707
2708     stackParms -= use_wreg;
2709
2710     if(stackParms>0) {
2711       if(stackParms == 1) {
2712         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
2713       } else {
2714         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2715         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2716       }
2717       if(STACK_MODEL_LARGE) {
2718         emitSKPNC;
2719         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
2720       }
2721     }
2722
2723 #if 0
2724     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
2725 #endif
2726
2727     /* adjust the stack for parameters if required */
2728 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2729
2730 #if 0
2731       /* if register bank was saved then pop them */
2732       if (ic->bankSaved)
2733         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2734
2735       /* if we hade saved some registers then unsave them */
2736       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2737         unsaveRegisters (ic);
2738 #endif
2739 }
2740
2741
2742
2743 /*-----------------------------------------------------------------*/
2744 /* genPcall - generates a call by pointer statement                */
2745 /*            new version, created from genCall - HJD              */
2746 /*-----------------------------------------------------------------*/
2747 static void genPcall (iCode *ic)
2748 {
2749   sym_link *fntype;
2750   int stackParms=0;
2751   symbol *retlbl = newiTempLabel(NULL);
2752   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2753
2754     FENTRY;
2755
2756     fntype = operandType( IC_LEFT(ic) )->next;
2757
2758     /* if send set is not empty the assign */
2759     if (_G.sendSet) {
2760       iCode *sic;
2761       int psuedoStkPtr=-1;
2762
2763       /* reverse sendSet if function is not reentrant */
2764       if(!IFFUNC_ISREENT(fntype))
2765         _G.sendSet = reverseSet(_G.sendSet);
2766
2767       stackParms = 0;
2768
2769       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2770         int size;
2771
2772           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2773           size = AOP_SIZE(IC_LEFT(sic));
2774           stackParms += size;
2775
2776           /* all parameters are passed via stack, since WREG is clobbered
2777            * by the calling sequence */
2778           while (size--) {
2779             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2780             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2781             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2782
2783             pic16_mov2w (AOP(IC_LEFT(sic)), size);
2784             pushw();
2785           }
2786
2787           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2788       }
2789
2790       _G.stackRegSet = _G.sendSet;
2791       _G.sendSet = NULL;
2792     }
2793
2794     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2795
2796     // push return address
2797     // push $ on return stack, then replace with retlbl
2798
2799     /* Thanks to Thorsten Klose for pointing out that the following
2800      * snippet should be interrupt safe */
2801     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
2802     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
2803
2804     pic16_emitpcodeNULLop(POC_PUSH);
2805
2806     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2807     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2808     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2809     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2810     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2811     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2812
2813
2814     /* restore interrupt control register */
2815     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
2816     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
2817
2818     /* make the call by writing the pointer into pc */
2819     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
2820     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
2821
2822     // note: MOVFF to PCL not allowed
2823     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
2824     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2825
2826
2827     /* return address is here: (X) */
2828     pic16_emitpLabelFORCE(retlbl->key);
2829
2830     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2831
2832     GpsuedoStkPtr=0;
2833     /* if we need assign a result value */
2834     if ((IS_ITEMP(IC_RESULT(ic))
2835           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2836               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2837         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2838
2839       _G.accInUse++;
2840       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2841       _G.accInUse--;
2842
2843       /* FIXME: Need proper way to obtain the function result's type.
2844        * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
2845       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
2846
2847       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2848               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2849
2850       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2851     }
2852
2853 //    stackParms -= use_wreg;
2854
2855     if(stackParms>0) {
2856       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2857       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
2858       if(STACK_MODEL_LARGE) {
2859         emitSKPNC;
2860         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
2861       }
2862     }
2863 }
2864
2865 /*-----------------------------------------------------------------*/
2866 /* resultRemat - result  is rematerializable                       */
2867 /*-----------------------------------------------------------------*/
2868 static int resultRemat (iCode *ic)
2869 {
2870   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2871   if (SKIP_IC(ic) || ic->op == IFX)
2872     return 0;
2873
2874   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2875     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2876     if (sym->remat && !POINTER_SET(ic))
2877       return 1;
2878   }
2879
2880   return 0;
2881 }
2882
2883 #if 0
2884 /*-----------------------------------------------------------------*/
2885 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2886 /*-----------------------------------------------------------------*/
2887 static bool inExcludeList(char *s)
2888 {
2889   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2890     int i =0;
2891
2892     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2893     if (options.excludeRegs[i] &&
2894     STRCASECMP(options.excludeRegs[i],"none") == 0)
2895         return FALSE ;
2896
2897     for ( i = 0 ; options.excludeRegs[i]; i++) {
2898         if (options.excludeRegs[i] &&
2899         STRCASECMP(s,options.excludeRegs[i]) == 0)
2900             return TRUE;
2901     }
2902     return FALSE ;
2903 }
2904 #endif
2905
2906 /*-----------------------------------------------------------------*/
2907 /* genFunction - generated code for function entry                 */
2908 /*-----------------------------------------------------------------*/
2909 static void genFunction (iCode *ic)
2910 {
2911   symbol *sym;
2912   sym_link *ftype;
2913
2914     FENTRY;
2915     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
2916
2917     pic16_labelOffset += (max_key+4);
2918     max_key=0;
2919     GpsuedoStkPtr=0;
2920     _G.nRegsSaved = 0;
2921
2922     ftype = operandType(IC_LEFT(ic));
2923     sym = OP_SYMBOL(IC_LEFT(ic));
2924
2925     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
2926       /* create an absolute section at the interrupt vector:
2927        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
2928       symbol *asym;
2929       char asymname[128];
2930       pBlock *apb;
2931
2932 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
2933
2934         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
2935           sprintf(asymname, "ivec_%s", sym->name);
2936         else
2937           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
2938
2939         /* when an interrupt is declared as naked, do not emit the special
2940          * wrapper segment at vector address. The user should take care for
2941          * this instead. -- VR */
2942
2943         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
2944           asym = newSymbol(asymname, 0);
2945           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
2946           pic16_addpBlock( apb );
2947
2948           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
2949           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
2950           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
2951           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
2952           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
2953
2954           /* mark the end of this tiny function */
2955           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
2956         } else {
2957           sprintf(asymname, "%s", sym->rname);
2958         }
2959
2960         {
2961           absSym *abSym;
2962
2963             abSym = Safe_calloc(1, sizeof(absSym));
2964             strcpy(abSym->name, asymname);
2965
2966             switch( FUNC_INTNO(sym->type) ) {
2967               case 0: abSym->address = 0x000000; break;
2968               case 1: abSym->address = 0x000008; break;
2969               case 2: abSym->address = 0x000018; break;
2970
2971               default:
2972 //                fprintf(stderr, "no interrupt number is given\n");
2973                 abSym->address = -1; break;
2974             }
2975
2976             /* relocate interrupt vectors if needed */
2977             if(abSym->address != -1)
2978               abSym->address += pic16_options.ivt_loc;
2979
2980             addSet(&absSymSet, abSym);
2981         }
2982     }
2983
2984     /* create the function header */
2985     pic16_emitcode(";","-----------------------------------------");
2986     pic16_emitcode(";"," function %s",sym->name);
2987     pic16_emitcode(";","-----------------------------------------");
2988
2989     /* prevent this symbol from being emitted as 'extern' */
2990     pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
2991
2992     pic16_emitcode("","%s:",sym->rname);
2993     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2994
2995     {
2996       absSym *ab;
2997
2998         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
2999           if(!strcmp(ab->name, sym->rname)) {
3000             pic16_pBlockConvert2Absolute(pb);
3001             break;
3002           }
3003         }
3004     }
3005
3006     if(IFFUNC_ISNAKED(ftype)) {
3007       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3008       return;
3009     }
3010
3011     /* if critical function then turn interrupts off */
3012     if (IFFUNC_ISCRITICAL(ftype)) {
3013       //pic16_emitcode("clr","ea");
3014     }
3015
3016     currFunc = sym;             /* update the currFunc symbol */
3017     _G.fregsUsed = sym->regsUsed;
3018     _G.sregsAlloc = newBitVect(128);
3019
3020
3021     /* if this is an interrupt service routine then
3022      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3023     if (IFFUNC_ISISR(sym->type)) {
3024         _G.usefastretfie = 1;   /* use shadow registers by default */
3025
3026         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3027         if(!FUNC_ISSHADOWREGS(sym->type)) {
3028           /* do not save WREG,STATUS,BSR for high priority interrupts
3029            * because they are stored in the hardware shadow registers already */
3030           _G.usefastretfie = 0;
3031           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3032           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3033           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3034         }
3035
3036         /* these should really be optimized somehow, because not all
3037          * interrupt handlers modify them */
3038         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3039         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3040         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3041         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3042         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3043         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3044
3045 //        pic16_pBlockConvert2ISR(pb);
3046     }
3047
3048     /* emit code to setup stack frame if user enabled,
3049      * and function is not main() */
3050
3051 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3052     if(strcmp(sym->name, "main")) {
3053       if(0
3054         || !options.ommitFramePtr
3055 //        || sym->regsUsed
3056         || IFFUNC_ARGS(sym->type)
3057         || FUNC_HASSTACKPARM(sym->etype)
3058         ) {
3059         /* setup the stack frame */
3060         if(STACK_MODEL_LARGE)
3061           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3062         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3063
3064         if(STACK_MODEL_LARGE)
3065           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3066         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3067       }
3068     }
3069
3070     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3071           && sym->stack) {
3072
3073       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3074
3075       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3076       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3077       emitSKPC;
3078       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3079     }
3080
3081     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3082       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3083         _G.useWreg = 0;
3084       else
3085         _G.useWreg = 1;
3086     } else
3087       _G.useWreg = 0;
3088
3089     /* if callee-save to be used for this function
3090      * then save the registers being used in this function */
3091 //    if (IFFUNC_CALLEESAVES(sym->type))
3092     if(strcmp(sym->name, "main")) {
3093       int i;
3094
3095         /* if any registers used */
3096         if (sym->regsUsed) {
3097                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3098
3099           if(!pic16_options.xinst) {
3100             /* save the registers used */
3101             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3102             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3103               if (bitVectBitValue(sym->regsUsed,i)) {
3104 #if 0
3105                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3106 #endif
3107                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3108                 _G.nRegsSaved++;
3109
3110                 if(!pic16_regWithIdx(i)->wasUsed) {
3111                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3112                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3113                   pic16_regWithIdx(i)->wasUsed = 1;
3114                 }
3115               }
3116             }
3117           } else {
3118
3119             /* xinst */
3120             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3121             for(i=0;i<sym->regsUsed->size;i++) {
3122               if(bitVectBitValue(sym->regsUsed, i)) {
3123                 _G.nRegsSaved++;
3124               }
3125             }
3126
3127 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3128           }
3129
3130           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3131
3132         }
3133     }
3134
3135     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3136 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3137 }
3138
3139 /*-----------------------------------------------------------------*/
3140 /* genEndFunction - generates epilogue for functions               */
3141 /*-----------------------------------------------------------------*/
3142 static void genEndFunction (iCode *ic)
3143 {
3144   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3145
3146     FENTRY;
3147
3148     if(IFFUNC_ISNAKED(sym->type)) {
3149       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3150       return;
3151     }
3152
3153     _G.stack_lat = 0;
3154
3155     /* add code for ISCRITICAL */
3156     if(IFFUNC_ISCRITICAL(sym->type)) {
3157       /* if critical function, turn on interrupts */
3158
3159       /* TODO: add code here -- VR */
3160     }
3161
3162 //    sym->regsUsed = _G.fregsUsed;
3163
3164     /* now we need to restore the registers */
3165     /* if any registers used */
3166
3167     /* first restore registers that might be used for stack access */
3168     if(_G.sregsAllocSet) {
3169     regs *sr;
3170
3171       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3172       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3173         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3174       }
3175     }
3176
3177     if (strcmp(sym->name, "main") && sym->regsUsed) {
3178       int i;
3179
3180         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3181         /* restore registers used */
3182         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3183         for ( i = sym->regsUsed->size; i >= 0; i--) {
3184           if (bitVectBitValue(sym->regsUsed,i)) {
3185             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3186             _G.nRegsSaved--;
3187           }
3188         }
3189         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3190     }
3191
3192
3193
3194     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3195           && sym->stack) {
3196       if (sym->stack == 1) {
3197         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3198         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3199       } else {
3200         // we have to add more than one...
3201         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3202         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3203         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3204         emitSKPNC;
3205         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3206         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3207         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3208       }
3209     }
3210
3211     if(strcmp(sym->name, "main")) {
3212       if(0
3213         || !options.ommitFramePtr
3214 //        || sym->regsUsed
3215         || IFFUNC_ARGS(sym->type)
3216         || FUNC_HASSTACKPARM(sym->etype)
3217         ) {
3218         /* restore stack frame */
3219         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3220         if(STACK_MODEL_LARGE)
3221           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3222       }
3223     }
3224
3225     _G.useWreg = 0;
3226
3227     if (IFFUNC_ISISR(sym->type)) {
3228       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3229       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3230       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3231       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3232       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3233       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3234
3235       if(!FUNC_ISSHADOWREGS(sym->type)) {
3236         /* do not restore interrupt vector for WREG,STATUS,BSR
3237          * for high priority interrupt, see genFunction */
3238         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3239         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3240         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3241       }
3242 //      _G.interruptvector = 0;         /* sanity check */
3243
3244
3245       /* if debug then send end of function */
3246 /*      if (options.debug && currFunc)  */
3247       if (currFunc) {
3248         debugFile->writeEndFunction (currFunc, ic, 1);
3249       }
3250
3251       if(_G.usefastretfie)
3252         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3253       else
3254         pic16_emitpcodeNULLop(POC_RETFIE);
3255
3256       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3257
3258       _G.usefastretfie = 0;
3259       return;
3260     }
3261
3262     if (IFFUNC_ISCRITICAL(sym->type)) {
3263       pic16_emitcode("setb","ea");
3264     }
3265
3266     /* if debug then send end of function */
3267     if (currFunc) {
3268       debugFile->writeEndFunction (currFunc, ic, 1);
3269     }
3270
3271     /* insert code to restore stack frame, if user enabled it
3272      * and function is not main() */
3273
3274
3275     pic16_emitpcodeNULLop(POC_RETURN);
3276
3277     /* Mark the end of a function */
3278     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3279 }
3280
3281
3282 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3283 {
3284   unsigned long lit=1;
3285   operand *op;
3286
3287     op = IC_LEFT(ic);
3288
3289     // this fails for pic16_isLitOp(op) (if op is an AOP_PCODE)
3290     if(AOP_TYPE(op) == AOP_LIT) {
3291       if(!IS_FLOAT(operandType( op ))) {
3292         lit = ulFromVal (AOP(op)->aopu.aop_lit);
3293       } else {
3294         union {
3295           unsigned long lit_int;
3296           float lit_float;
3297         } info;
3298
3299         /* take care if literal is a float */
3300         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3301         lit = info.lit_int;
3302       }
3303     }
3304
3305     if (AOP_TYPE(op) == AOP_LIT) {
3306       /* FIXME: broken for
3307        *   char __at(0x456) foo;
3308        *   return &foo;
3309        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
3310       pic16_movLit2f(dest, (lit >> (8ul*offset)));
3311     } else if (AOP_TYPE(op) == AOP_PCODE
3312                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3313       /* char *s= "aaa"; return s; */
3314       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
3315        *      that the generic pointer is interpreted correctly
3316        *      as referring to __code space, but this is fragile! */
3317       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
3318       /* XXX: should check that dest != WREG */
3319       pic16_emitpcode(POC_MOVWF, dest);
3320     } else {
3321       if(dest->type == PO_WREG && (offset == 0)) {
3322         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3323         return;
3324       }
3325       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3326     }
3327 }
3328
3329 /*-----------------------------------------------------------------*/
3330 /* genRet - generate code for return statement                     */
3331 /*-----------------------------------------------------------------*/
3332 static void genRet (iCode *ic)
3333 {
3334   int size;
3335   operand *left;
3336
3337     FENTRY;
3338         /* if we have no return value then
3339          * just generate the "ret" */
3340
3341         if (!IC_LEFT(ic))
3342                 goto jumpret;
3343
3344         /* we have something to return then
3345          * move the return value into place */
3346         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3347         size = AOP_SIZE(IC_LEFT(ic));
3348
3349         if(size <= 4) {
3350           if(size>3)
3351             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3352
3353           if(size>2)
3354             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3355
3356           if(size>1)
3357             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3358
3359           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3360
3361         } else {
3362                 /* >32-bits, setup stack and FSR0 */
3363                 while (size--) {
3364 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3365 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3366
3367                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3368
3369 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3370                         GpsuedoStkPtr++;
3371                 }
3372
3373                 /* setup FSR0 */
3374                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3375                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3376
3377                 if(STACK_MODEL_LARGE) {
3378                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3379                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3380                 } else {
3381                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3382                 }
3383         }
3384
3385         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3386
3387 jumpret:
3388         /* generate a jump to the return label
3389          * if the next is not the return statement */
3390         if (!(ic->next && ic->next->op == LABEL
3391                 && IC_LABEL(ic->next) == returnLabel)) {
3392
3393                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3394                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3395         }
3396 }
3397
3398 /*-----------------------------------------------------------------*/
3399 /* genLabel - generates a label                                    */
3400 /*-----------------------------------------------------------------*/
3401 static void genLabel (iCode *ic)
3402 {
3403   FENTRY;
3404
3405   /* special case never generate */
3406   if (IC_LABEL(ic) == entryLabel)
3407     return ;
3408
3409   pic16_emitpLabel(IC_LABEL(ic)->key);
3410 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3411 }
3412
3413 /*-----------------------------------------------------------------*/
3414 /* genGoto - generates a goto                                      */
3415 /*-----------------------------------------------------------------*/
3416 //tsd
3417 static void genGoto (iCode *ic)
3418 {
3419   FENTRY;
3420   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3421 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3422 }
3423
3424
3425 /*-----------------------------------------------------------------*/
3426 /* genMultbits :- multiplication of bits                           */
3427 /*-----------------------------------------------------------------*/
3428 static void genMultbits (operand *left,
3429                          operand *right,
3430                          operand *result)
3431 {
3432   FENTRY;
3433
3434   if(!pic16_sameRegs(AOP(result),AOP(right)))
3435     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3436
3437   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3438   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3439   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3440
3441 }
3442
3443
3444 /*-----------------------------------------------------------------*/
3445 /* genMultOneByte : 8 bit multiplication & division                */
3446 /*-----------------------------------------------------------------*/
3447 static void genMultOneByte (operand *left,
3448                             operand *right,
3449                             operand *result)
3450 {
3451
3452   FENTRY;
3453   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3454   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3455
3456   /* (if two literals, the value is computed before) */
3457   /* if one literal, literal on the right */
3458   if (AOP_TYPE(left) == AOP_LIT){
3459     operand *t = right;
3460     right = left;
3461     left = t;
3462   }
3463
3464         /* size is already checked in genMult == 1 */
3465 //      size = AOP_SIZE(result);
3466
3467         if (AOP_TYPE(right) == AOP_LIT){
3468                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3469                                         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3470                                         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3471                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3472         } else {
3473                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3474                                         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3475                                         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3476                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3477         }
3478
3479         pic16_genMult8X8_n (left, right,result);
3480 }
3481
3482 #if 0
3483 /*-----------------------------------------------------------------*/
3484 /* genMultOneWord : 16 bit multiplication                          */
3485 /*-----------------------------------------------------------------*/
3486 static void genMultOneWord (operand *left,
3487                             operand *right,
3488                             operand *result)
3489 {
3490   FENTRY;
3491   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3492   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3493
3494   /* (if two literals, the value is computed before)
3495    * if one literal, literal on the right */
3496   if (AOP_TYPE(left) == AOP_LIT){
3497     operand *t = right;
3498     right = left;
3499     left = t;
3500   }
3501
3502   /* size is checked already == 2 */
3503 //  size = AOP_SIZE(result);
3504
3505   if (AOP_TYPE(right) == AOP_LIT) {
3506     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3507       pic16_aopGet(AOP(right),0,FALSE,FALSE),
3508       pic16_aopGet(AOP(left),0,FALSE,FALSE),
3509       pic16_aopGet(AOP(result),0,FALSE,FALSE));
3510   } else {
3511     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3512       pic16_aopGet(AOP(right),0,FALSE,FALSE),
3513       pic16_aopGet(AOP(left),0,FALSE,FALSE),
3514       pic16_aopGet(AOP(result),0,FALSE,FALSE));
3515   }
3516
3517   pic16_genMult16X16_16(left, right,result);
3518 }
3519 #endif
3520
3521 #if 0
3522 /*-----------------------------------------------------------------*/
3523 /* genMultOneLong : 32 bit multiplication                          */
3524 /*-----------------------------------------------------------------*/
3525 static void genMultOneLong (operand *left,
3526                             operand *right,
3527                             operand *result)
3528 {
3529   FENTRY;
3530   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3531   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3532
3533   /* (if two literals, the value is computed before)
3534    * if one literal, literal on the right */
3535   if (AOP_TYPE(left) == AOP_LIT){
3536     operand *t = right;
3537     right = left;
3538     left = t;
3539   }
3540
3541   /* size is checked already == 4 */
3542 //  size = AOP_SIZE(result);
3543
3544   if (AOP_TYPE(right) == AOP_LIT) {
3545     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3546         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3547         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3548         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3549   } else {
3550     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3551         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3552         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3553         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3554   }
3555
3556   pic16_genMult32X32_32(left, right,result);
3557 }
3558 #endif
3559
3560
3561
3562 /*-----------------------------------------------------------------*/
3563 /* genMult - generates code for multiplication                     */
3564 /*-----------------------------------------------------------------*/
3565 static void genMult (iCode *ic)
3566 {
3567   operand *left = IC_LEFT(ic);
3568   operand *right = IC_RIGHT(ic);
3569   operand *result= IC_RESULT(ic);
3570
3571     FENTRY;
3572         /* assign the amsops */
3573         pic16_aopOp (left,ic,FALSE);
3574         pic16_aopOp (right,ic,FALSE);
3575         pic16_aopOp (result,ic,TRUE);
3576
3577         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3578
3579         /* special cases first *
3580         * both are bits */
3581         if (AOP_TYPE(left) == AOP_CRY
3582                 && AOP_TYPE(right)== AOP_CRY) {
3583                 genMultbits(left,right,result);
3584           goto release ;
3585         }
3586
3587         /* if both are of size == 1 */
3588         if(AOP_SIZE(left) == 1
3589                 && AOP_SIZE(right) == 1) {
3590                 genMultOneByte(left,right,result);
3591           goto release ;
3592         }
3593
3594 #if 0
3595         /* if both are of size == 2 */
3596         if(AOP_SIZE(left) == 2
3597                 && AOP_SIZE(right) == 2) {
3598                 genMultOneWord(left, right, result);
3599           goto release;
3600         }
3601
3602         /* if both are of size == 4 */
3603         if(AOP_SIZE(left) == 4
3604                 && AOP_SIZE(right) == 4) {
3605                 genMultOneLong(left, right, result);
3606           goto release;
3607         }
3608 #endif
3609
3610         fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
3611         assert( !"Multiplication should have been transformed into function call!" );
3612
3613         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3614
3615
3616         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3617         /* should have been converted to function call */
3618         assert(0) ;
3619
3620 release :
3621         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3622         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3623         pic16_freeAsmop(result,NULL,ic,TRUE);
3624 }
3625
3626 #if 0
3627 /*-----------------------------------------------------------------*/
3628 /* genDivbits :- division of bits                                  */
3629 /*-----------------------------------------------------------------*/
3630 static void genDivbits (operand *left,
3631                         operand *right,
3632                         operand *result)
3633 {
3634   char *l;
3635
3636     FENTRY;
3637     /* the result must be bit */
3638     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3639     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3640
3641     MOVA(l);
3642
3643     pic16_emitcode("div","ab");
3644     pic16_emitcode("rrc","a");
3645     pic16_aopPut(AOP(result),"c",0);
3646 }
3647
3648 /*-----------------------------------------------------------------*/
3649 /* genDivOneByte : 8 bit division                                  */
3650 /*-----------------------------------------------------------------*/
3651 static void genDivOneByte (operand *left,
3652                            operand *right,
3653                            operand *result)
3654 {
3655   sym_link *opetype = operandType(result);
3656   char *l ;
3657   symbol *lbl ;
3658   int size,offset;
3659
3660         /* result = divident / divisor
3661          * - divident may be a register or a literal,
3662          * - divisor may be a register or a literal,
3663          * so there are 3 cases (literal / literal is optimized
3664          * by the front-end) to handle.
3665          * In addition we must handle signed and unsigned, which
3666          * result in 6 final different cases -- VR */
3667
3668     FENTRY;
3669
3670     size = AOP_SIZE(result) - 1;
3671     offset = 1;
3672     /* signed or unsigned */
3673     if (SPEC_USIGN(opetype)) {
3674       pCodeOp *pct1,    /* count */
3675                 *pct2,  /* reste */
3676                 *pct3;  /* temp */
3677       symbol *label1, *label2, *label3;;
3678
3679
3680         /* unsigned is easy */
3681
3682         pct1 = pic16_popGetTempReg(1);
3683         pct2 = pic16_popGetTempReg(1);
3684         pct3 = pic16_popGetTempReg(1);
3685
3686         label1 = newiTempLabel(NULL);
3687         label2 = newiTempLabel(NULL);
3688         label3 = newiTempLabel(NULL);
3689
3690         /* the following algorithm is extracted from divuint.c */
3691
3692         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
3693         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
3694
3695         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
3696
3697         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
3698
3699         pic16_emitpLabel(label1->key);
3700
3701         emitCLRC;
3702         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
3703
3704
3705         emitCLRC;
3706         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
3707
3708
3709         emitSKPNC;
3710         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
3711
3712         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
3713         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
3714
3715         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
3716         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
3717         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
3718
3719         pic16_emitpLabel( label3->key );
3720         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
3721         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
3722
3723
3724
3725         pic16_emitpLabel(label2->key);
3726         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
3727         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
3728         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
3729
3730         /* result is in wreg */
3731         if(AOP_TYPE(result) != AOP_ACC)
3732                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3733
3734         pic16_popReleaseTempReg( pct3, 1);
3735         pic16_popReleaseTempReg( pct2, 1);
3736         pic16_popReleaseTempReg( pct1, 1);
3737
3738         return ;
3739     }
3740
3741     /* signed is a little bit more difficult */
3742
3743     /* save the signs of the operands */
3744     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3745     MOVA(l);
3746     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3747     pic16_emitcode("push","acc"); /* save it on the stack */
3748
3749     /* now sign adjust for both left & right */
3750     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);
3751     MOVA(l);
3752     lbl = newiTempLabel(NULL);
3753     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3754     pic16_emitcode("cpl","a");
3755     pic16_emitcode("inc","a");
3756     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3757     pic16_emitcode("mov","b,a");
3758
3759     /* sign adjust left side */
3760     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);
3761     MOVA(l);
3762
3763     lbl = newiTempLabel(NULL);
3764     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3765     pic16_emitcode("cpl","a");
3766     pic16_emitcode("inc","a");
3767     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3768
3769     /* now the division */
3770     pic16_emitcode("div","ab");
3771     /* we are interested in the lower order
3772     only */
3773     pic16_emitcode("mov","b,a");
3774     lbl = newiTempLabel(NULL);
3775     pic16_emitcode("pop","acc");
3776     /* if there was an over flow we don't
3777     adjust the sign of the result */
3778     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3779     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3780     CLRC;
3781     pic16_emitcode("clr","a");
3782     pic16_emitcode("subb","a,b");
3783     pic16_emitcode("mov","b,a");
3784     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3785
3786     /* now we are done */
3787     pic16_aopPut(AOP(result),"b",0);
3788     if(size > 0){
3789         pic16_emitcode("mov","c,b.7");
3790         pic16_emitcode("subb","a,acc");
3791     }
3792     while (size--)
3793         pic16_aopPut(AOP(result),"a",offset++);
3794
3795 }
3796 #endif
3797
3798 /*-----------------------------------------------------------------*/
3799 /* genDiv - generates code for division                            */
3800 /*-----------------------------------------------------------------*/
3801 static void genDiv (iCode *ic)
3802 {
3803     operand *left = IC_LEFT(ic);
3804     operand *right = IC_RIGHT(ic);
3805     operand *result= IC_RESULT(ic);
3806     int negated = 0;
3807     int leftVal = 0, rightVal = 0;
3808     int signedLits = 0;
3809     char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
3810     int op = 0;
3811
3812         /* Division is a very lengthy algorithm, so it is better
3813          * to call support routines than inlining algorithm.
3814          * Division functions written here just in case someone
3815          * wants to inline and not use the support libraries -- VR */
3816
3817     FENTRY;
3818
3819     /* assign the amsops */
3820     pic16_aopOp (left,ic,FALSE);
3821     pic16_aopOp (right,ic,FALSE);
3822     pic16_aopOp (result,ic,TRUE);
3823
3824     if (ic->op == '/')
3825       op = 0;
3826     else if (ic->op == '%')
3827       op = 1;
3828     else
3829       assert( !"invalid operation requested in genDivMod" );
3830
3831     /* get literal values */
3832     if (IS_VALOP(left)) {
3833       leftVal = (int) ulFromVal ( OP_VALUE(left) );
3834       assert( leftVal >= -128 && leftVal < 256 );
3835       if (leftVal < 0) { signedLits++; }
3836     }
3837     if (IS_VALOP(right)) {
3838       rightVal = (int) ulFromVal ( OP_VALUE(right) );
3839       assert( rightVal >= -128 && rightVal < 256 );
3840       if (rightVal < 0) { signedLits++; }
3841     }
3842
3843     /* We should only come here to convert all
3844      * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
3845      * with exactly one operand being s8_t into
3846      * u8_t x u8_t -> u8_t. All other cases should have been
3847      * turned into calls to support routines beforehand... */
3848     if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
3849         && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
3850     {
3851       if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
3852           && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
3853       {
3854         /* Both operands are signed or negative, use _divschar
3855          * instead of _divuchar */
3856         pushaop(AOP(right), 0);
3857         pushaop(AOP(left), 0);
3858
3859         /* call _divschar */
3860         pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
3861
3862         {
3863           symbol *sym;
3864           sym = newSymbol( functions[op][0], 0 );
3865           sym->used++;
3866           strcpy(sym->rname, functions[op][0]);
3867           checkAddSym(&externs, sym);
3868         }
3869
3870         /* assign result */
3871         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3872         if (AOP_SIZE(result) > 1)
3873         {
3874           pic16_emitpcode(POC_MOVFF,
3875               pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
3876                 pic16_popGet(AOP(result), 1)));
3877           /* sign extend */
3878           pic16_addSign(result, 2, 1);
3879         }
3880
3881         /* clean up stack */
3882         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3883         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3884
3885         goto release;
3886       }
3887
3888       /* push right operand */
3889       if (IS_VALOP(right)) {
3890         if (rightVal < 0) {
3891           pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
3892           negated++;
3893         } else {
3894           pushaop(AOP(right), 0);
3895         }
3896       } else if (!IS_UNSIGNED(operandType(right))) {
3897         pic16_mov2w(AOP(right), 0);
3898         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3899         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3900         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3901         negated++;
3902       } else {
3903         pushaop(AOP(right), 0);
3904       }
3905
3906       /* push left operand */
3907       if (IS_VALOP(left)) {
3908         if (leftVal < 0) {
3909           pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
3910           negated++;
3911         } else {
3912           pushaop(AOP(left), 0);
3913         }
3914       } else if (!IS_UNSIGNED(operandType(left))) {
3915         pic16_mov2w(AOP(left),0);
3916         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3917         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3918         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3919         negated++;
3920       } else {
3921         pushaop(AOP(left), 0);
3922       }
3923
3924       /* call _divuchar */
3925       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
3926
3927       {
3928         symbol *sym;
3929         sym = newSymbol( functions[op][1], 0 );
3930         sym->used++;
3931         strcpy(sym->rname, functions[op][1]);
3932         checkAddSym(&externs, sym);
3933       }
3934
3935       /* Revert negation(s) from above.
3936        * This is inefficient: if both operands are negative, this
3937        * should not touch WREG. However, determining that exactly
3938        * one operand was negated costs at least 3 instructions,
3939        * so there is nothing to be gained here, is there?
3940        *
3941        * I negate WREG because either operand might share registers with
3942        * result, so assigning first might destroy an operand. */
3943
3944       /* For the modulus operator, (a/b)*b == a shall hold.
3945        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
3946        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
3947        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
3948        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
3949        * Only invert the result if the left operand is negative (sigh).
3950        */
3951       if (AOP_SIZE(result) <= 1 || !negated)
3952       {
3953         if (ic->op == '/')
3954         {
3955           if (IS_VALOP(right)) {
3956             if (rightVal < 0) {
3957               /* we negated this operand above */
3958               pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3959             }
3960           } else if (!IS_UNSIGNED(operandType(right))) {
3961             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3962             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3963           }
3964         }
3965
3966         if (IS_VALOP(left)) {
3967           if (leftVal < 0) {
3968             /* we negated this operand above */
3969             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3970           }
3971         } else if (!IS_UNSIGNED(operandType(left))) {
3972           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3973           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3974         }
3975
3976         /* Move result to destination. */
3977         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3978
3979         /* Zero-extend:  no operand was signed (or result is just a byte). */
3980         pic16_addSign(result, 1, 0);
3981       } else {
3982         assert( AOP_SIZE(result) > 1 );
3983         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
3984         if (ic->op == '/')
3985         {
3986           if (IS_VALOP(right)) {
3987             if (rightVal < 0) {
3988               /* we negated this operand above */
3989               pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3990             }
3991           } else if (!IS_UNSIGNED(operandType(right))) {
3992             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3993             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3994           }
3995         }
3996
3997         if (IS_VALOP(left)) {
3998           if (leftVal < 0) {
3999             /* we negated this operand above */
4000             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4001           }
4002         } else if (!IS_UNSIGNED(operandType(left))) {
4003           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4004           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4005         }
4006
4007         /* Move result to destination. */
4008         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4009
4010         /* Negate result if required. */
4011         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4012         pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4013
4014         /* Sign-extend. */
4015         pic16_addSign(result, 2, 1);
4016       }
4017
4018       /* clean up stack */
4019       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4020       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4021       goto release;
4022     }
4023
4024 #if 0
4025     /* special cases first */
4026     /* both are bits */
4027     if (AOP_TYPE(left) == AOP_CRY &&
4028         AOP_TYPE(right)== AOP_CRY) {
4029         genDivbits(left,right,result);
4030         goto release ;
4031     }
4032
4033     /* if both are of size == 1 */
4034     if (AOP_SIZE(left) == 1 &&
4035         AOP_SIZE(right) == 1 ) {
4036         genDivOneByte(left,right,result);
4037         goto release ;
4038     }
4039 #endif
4040
4041     /* should have been converted to function call */
4042     assert(0);
4043 release :
4044     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4045     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4046     pic16_freeAsmop(result,NULL,ic,TRUE);
4047 }
4048
4049 #if 0
4050 /*-----------------------------------------------------------------*/
4051 /* genModbits :- modulus of bits                                   */
4052 /*-----------------------------------------------------------------*/
4053 static void genModbits (operand *left,
4054                         operand *right,
4055                         operand *result)
4056 {
4057   char *l;
4058
4059     FENTRY;
4060
4061     werror(W_POSSBUG2, __FILE__, __LINE__);
4062     /* the result must be bit */
4063     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4064     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4065
4066     MOVA(l);
4067
4068     pic16_emitcode("div","ab");
4069     pic16_emitcode("mov","a,b");
4070     pic16_emitcode("rrc","a");
4071     pic16_aopPut(AOP(result),"c",0);
4072 }
4073
4074 /*-----------------------------------------------------------------*/
4075 /* genModOneByte : 8 bit modulus                                   */
4076 /*-----------------------------------------------------------------*/
4077 static void genModOneByte (operand *left,
4078                            operand *right,
4079                            operand *result)
4080 {
4081   sym_link *opetype = operandType(result);
4082   char *l ;
4083   symbol *lbl ;
4084
4085     FENTRY;
4086     werror(W_POSSBUG2, __FILE__, __LINE__);
4087
4088     /* signed or unsigned */
4089     if (SPEC_USIGN(opetype)) {
4090         /* unsigned is easy */
4091         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4092         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4093         MOVA(l);
4094         pic16_emitcode("div","ab");
4095         pic16_aopPut(AOP(result),"b",0);
4096         return ;
4097     }
4098
4099     /* signed is a little bit more difficult */
4100
4101     /* save the signs of the operands */
4102     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4103     MOVA(l);
4104
4105     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4106     pic16_emitcode("push","acc"); /* save it on the stack */
4107
4108     /* now sign adjust for both left & right */
4109     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);
4110     MOVA(l);
4111
4112     lbl = newiTempLabel(NULL);
4113     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4114     pic16_emitcode("cpl","a");
4115     pic16_emitcode("inc","a");
4116     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4117     pic16_emitcode("mov","b,a");
4118
4119     /* sign adjust left side */
4120     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);
4121     MOVA(l);
4122
4123     lbl = newiTempLabel(NULL);
4124     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4125     pic16_emitcode("cpl","a");
4126     pic16_emitcode("inc","a");
4127     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4128
4129     /* now the multiplication */
4130     pic16_emitcode("div","ab");
4131     /* we are interested in the lower order
4132     only */
4133     lbl = newiTempLabel(NULL);
4134     pic16_emitcode("pop","acc");
4135     /* if there was an over flow we don't
4136     adjust the sign of the result */
4137     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4138     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4139     CLRC ;
4140     pic16_emitcode("clr","a");
4141     pic16_emitcode("subb","a,b");
4142     pic16_emitcode("mov","b,a");
4143     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4144
4145     /* now we are done */
4146     pic16_aopPut(AOP(result),"b",0);
4147
4148 }
4149 #endif
4150
4151 /*-----------------------------------------------------------------*/
4152 /* genMod - generates code for division                            */
4153 /*-----------------------------------------------------------------*/
4154 static void genMod (iCode *ic)
4155 {
4156   /* Task deferred to genDiv */
4157   genDiv(ic);
4158 #if 0
4159   operand *left = IC_LEFT(ic);
4160   operand *right = IC_RIGHT(ic);
4161   operand *result= IC_RESULT(ic);
4162
4163     FENTRY;
4164
4165     /* assign the amsops */
4166     pic16_aopOp (left,ic,FALSE);
4167     pic16_aopOp (right,ic,FALSE);
4168     pic16_aopOp (result,ic,TRUE);
4169
4170     /* special cases first */
4171     /* both are bits */
4172     if (AOP_TYPE(left) == AOP_CRY &&
4173         AOP_TYPE(right)== AOP_CRY) {
4174         genModbits(left,right,result);
4175         goto release ;
4176     }
4177
4178     /* if both are of size == 1 */
4179     if (AOP_SIZE(left) == 1 &&
4180         AOP_SIZE(right) == 1 ) {
4181         genModOneByte(left,right,result);
4182         goto release ;
4183     }
4184
4185     /* should have been converted to function call */
4186     assert(0);
4187
4188 release :
4189     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4190     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4191     pic16_freeAsmop(result,NULL,ic,TRUE);
4192 #endif
4193 }
4194
4195 /*-----------------------------------------------------------------*/
4196 /* genIfxJump :- will create a jump depending on the ifx           */
4197 /*-----------------------------------------------------------------*/
4198 /*
4199   note: May need to add parameter to indicate when a variable is in bit space.
4200 */
4201 static void genIfxJump (iCode *ic, char *jval)
4202 {
4203   FENTRY;
4204
4205     /* if true label then we jump if condition
4206     supplied is true */
4207     if ( IC_TRUE(ic) ) {
4208
4209         if(strcmp(jval,"a") == 0)
4210           emitSKPZ;
4211         else if (strcmp(jval,"c") == 0)
4212           emitSKPNC;
4213         else {
4214           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4215           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4216         }
4217
4218         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4219         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4220
4221     }
4222     else {
4223         /* false label is present */
4224         if(strcmp(jval,"a") == 0)
4225           emitSKPNZ;
4226         else if (strcmp(jval,"c") == 0)
4227           emitSKPC;
4228         else {
4229           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4230           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4231         }
4232
4233         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4234         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4235
4236     }
4237
4238
4239     /* mark the icode as generated */
4240     ic->generated = 1;
4241 }
4242
4243 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4244 {
4245   FENTRY;
4246
4247     /* if true label then we jump if condition
4248     supplied is true */
4249     if ( IC_TRUE(ic) ) {
4250       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4251       pic16_emitpcode(POC_BTFSC, jop);
4252
4253       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4254       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4255
4256     } else {
4257       /* false label is present */
4258       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4259       pic16_emitpcode(POC_BTFSS, jop);
4260
4261       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4262       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4263     }
4264
4265
4266     /* mark the icode as generated */
4267     ic->generated = 1;
4268 }
4269
4270 #if 0
4271 // not needed ATM
4272
4273 /*-----------------------------------------------------------------*/
4274 /* genSkip                                                         */
4275 /*-----------------------------------------------------------------*/
4276 static void genSkip(iCode *ifx,int status_bit)
4277 {
4278   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4279   if(!ifx)
4280     return;
4281
4282   if ( IC_TRUE(ifx) ) {
4283     switch(status_bit) {
4284     case 'z':
4285       emitSKPNZ;
4286       break;
4287
4288     case 'c':
4289       emitSKPNC;
4290       break;
4291
4292     case 'd':
4293       emitSKPDC;
4294       break;
4295
4296     }
4297
4298     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4299     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4300
4301   } else {
4302
4303     switch(status_bit) {
4304
4305     case 'z':
4306       emitSKPZ;
4307       break;
4308
4309     case 'c':
4310       emitSKPC;
4311       break;
4312
4313     case 'd':
4314       emitSKPDC;
4315       break;
4316     }
4317     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4318     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4319
4320   }
4321
4322 }
4323 #endif
4324
4325 /*-----------------------------------------------------------------*/
4326 /* genSkipc                                                        */
4327 /*-----------------------------------------------------------------*/
4328 static void genSkipc(resolvedIfx *rifx)
4329 {
4330   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4331
4332   if(!rifx)
4333     return;
4334
4335   if(rifx->condition)
4336     emitSKPNC;
4337   else
4338     emitSKPC;
4339
4340   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4341   rifx->generated = 1;
4342 }
4343
4344 /*-----------------------------------------------------------------*/
4345 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4346 /*                  aop (if it's NOT a literal) or from lit (if    */
4347 /*                  aop is a literal)                              */
4348 /*-----------------------------------------------------------------*/
4349 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4350   if (aop->type == AOP_LIT) {
4351     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4352   } else {
4353     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4354   }
4355 }
4356
4357 /*-----------------------------------------------------------------*/
4358 /* genCmp :- greater or less than comparison                       */
4359 /*-----------------------------------------------------------------*/
4360
4361 /* genCmp performs a left < right comparison, stores
4362  * the outcome in result (if != NULL) and generates
4363  * control flow code for the ifx (if != NULL).
4364  *
4365  * This version leaves in sequences like
4366  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4367  * which should be optmized by the peephole
4368  * optimizer - RN 2005-01-01 */
4369 static void genCmp (operand *left,operand *right,
4370                     operand *result, iCode *ifx, int sign)
4371 {
4372   resolvedIfx rIfx;
4373   int size;
4374   int offs;
4375   symbol *templbl;
4376   operand *dummy;
4377   unsigned long lit;
4378   unsigned long mask;
4379   int performedLt;
4380
4381   FENTRY;
4382
4383   assert (left && right);
4384   assert (AOP_SIZE(left) == AOP_SIZE(right));
4385
4386   size = AOP_SIZE(right) - 1;
4387   mask = (0x100UL << (size*8)) - 1;
4388   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4389   performedLt = 1;
4390   templbl = NULL;
4391   lit = 0;
4392
4393   resolveIfx (&rIfx, ifx);
4394
4395   /* handle for special cases */
4396   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4397       return;
4398
4399   /**********************************************************************
4400    * handle bits - bit compares are promoted to int compares seemingly! *
4401    **********************************************************************/
4402 #if 0
4403   // THIS IS COMPLETELY UNTESTED!
4404   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4405     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4406     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4407     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4408
4409     emitSETC;
4410     // 1 < {0,1} is false --> clear C by skipping the next instruction
4411     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4412     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4413     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4414     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4415     emitCLRC; // only skipped for left=0 && right=1
4416
4417     goto correct_result_in_carry;
4418   } // if
4419 #endif
4420
4421   /*************************************************
4422    * make sure that left is register (or the like) *
4423    *************************************************/
4424   if (!isAOP_REGlike(left)) {
4425     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4426     assert (isAOP_LIT(left));
4427     assert (isAOP_REGlike(right));
4428     // swap left and right
4429     // left < right <==> right > left <==> (right >= left + 1)
4430     lit = ulFromVal (AOP(left)->aopu.aop_lit);
4431
4432     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4433       // MAXVALUE < right? always false
4434       if (performedLt) emitCLRC; else emitSETC;
4435       goto correct_result_in_carry;
4436     } // if
4437
4438     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4439     // that's why we handled it above.
4440     lit++;
4441
4442     dummy = left;
4443     left = right;
4444     right = dummy;
4445
4446     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4447   } else if (isAOP_LIT(right)) {
4448     lit = ulFromVal (AOP(right)->aopu.aop_lit);
4449   } // if
4450
4451   assert (isAOP_REGlike(left)); // left must be register or the like
4452   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4453
4454   /*************************************************
4455    * special cases go here                         *
4456    *************************************************/
4457
4458   if (isAOP_LIT(right)) {
4459     if (!sign) {
4460       // unsigned comparison to a literal
4461       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4462       if (lit == 0) {
4463         // unsigned left < 0? always false
4464         if (performedLt) emitCLRC; else emitSETC;
4465         goto correct_result_in_carry;
4466       }
4467     } else {
4468       // signed comparison to a literal
4469       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4470       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4471         // signed left < 0x80000000? always false
4472         if (performedLt) emitCLRC; else emitSETC;
4473         goto correct_result_in_carry;
4474       } else if (lit == 0) {
4475         // compare left < 0; set CARRY if SIGNBIT(left) is set
4476         if (performedLt) emitSETC; else emitCLRC;
4477         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4478         if (performedLt) emitCLRC; else emitSETC;
4479         goto correct_result_in_carry;
4480       }
4481     } // if (!sign)
4482   } // right is literal
4483
4484   /*************************************************
4485    * perform a general case comparison             *
4486    * make sure we get CARRY==1 <==> left >= right  *
4487    *************************************************/
4488   // compare most significant bytes
4489   //DEBUGpc ("comparing bytes at offset %d", size);
4490   if (!sign) {
4491     // unsigned comparison
4492     mov2w_regOrLit (AOP(right), lit, size);
4493     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4494   } else {
4495     // signed comparison
4496     // (add 2^n to both operands then perform an unsigned comparison)
4497     if (isAOP_LIT(right)) {
4498       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4499       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4500
4501       if (litbyte == 0x80) {
4502         // left >= 0x80 -- always true, but more bytes to come
4503         pic16_mov2w (AOP(left), size);
4504         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4505         emitSETC;
4506       } else {
4507         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4508         pic16_mov2w (AOP(left), size);
4509         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4510         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4511       } // if
4512     } else {
4513       /* using PRODL as a temporary register here */
4514       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4515       //pCodeOp *pctemp = pic16_popGetTempReg(1);
4516       pic16_mov2w (AOP(left), size);
4517       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4518       pic16_emitpcode (POC_MOVWF, pctemp);
4519       pic16_mov2w (AOP(right), size);
4520       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4521       pic16_emitpcode (POC_SUBFW, pctemp);
4522       //pic16_popReleaseTempReg(pctemp, 1);
4523     }
4524   } // if (!sign)
4525
4526   // compare remaining bytes (treat as unsigned case from above)
4527   templbl = newiTempLabel ( NULL );
4528   offs = size;
4529   while (offs--) {
4530     //DEBUGpc ("comparing bytes at offset %d", offs);
4531     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4532     mov2w_regOrLit (AOP(right), lit, offs);
4533     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4534   } // while (offs)
4535   pic16_emitpLabel (templbl->key);
4536   goto result_in_carry;
4537
4538 result_in_carry:
4539
4540   /****************************************************
4541    * now CARRY contains the result of the comparison: *
4542    * SUBWF sets CARRY iff                             *
4543    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4544    * (F=left, W=right)                                *
4545    ****************************************************/
4546
4547   if (performedLt) {
4548     if (result && AOP_TYPE(result) != AOP_CRY) {
4549       // value will be stored
4550       emitTOGC;
4551     } else {
4552       // value wil only be used in the following genSkipc()
4553       rIfx.condition ^= 1;
4554     }
4555   } // if
4556
4557 correct_result_in_carry:
4558
4559   // assign result to variable (if neccessary)
4560   if (result && AOP_TYPE(result) != AOP_CRY) {
4561     //DEBUGpc ("assign result");
4562     size = AOP_SIZE(result);
4563     while (size--) {
4564       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4565     } // while
4566     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4567   } // if (result)
4568
4569   // perform conditional jump
4570   if (ifx) {
4571     //DEBUGpc ("generate control flow");
4572     genSkipc (&rIfx);
4573     ifx->generated = 1;
4574   } // if
4575 }
4576
4577 /*-----------------------------------------------------------------*/
4578 /* genCmpGt :- greater than comparison                             */
4579 /*-----------------------------------------------------------------*/
4580 static void genCmpGt (iCode *ic, iCode *ifx)
4581 {
4582   operand *left, *right, *result;
4583   sym_link *letype , *retype;
4584   int sign ;
4585
4586     FENTRY;
4587
4588     left = IC_LEFT(ic);
4589     right= IC_RIGHT(ic);
4590     result = IC_RESULT(ic);
4591
4592     letype = getSpec(operandType(left));
4593     retype =getSpec(operandType(right));
4594     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4595     /* assign the amsops */
4596     pic16_aopOp (left,ic,FALSE);
4597     pic16_aopOp (right,ic,FALSE);
4598     pic16_aopOp (result,ic,TRUE);
4599
4600     genCmp(right, left, result, ifx, sign);
4601
4602     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4603     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4604     pic16_freeAsmop(result,NULL,ic,TRUE);
4605 }
4606
4607 /*-----------------------------------------------------------------*/
4608 /* genCmpLt - less than comparisons                                */
4609 /*-----------------------------------------------------------------*/
4610 static void genCmpLt (iCode *ic, iCode *ifx)
4611 {
4612   operand *left, *right, *result;
4613   sym_link *letype , *retype;
4614   int sign ;
4615
4616     FENTRY;
4617
4618     left = IC_LEFT(ic);
4619     right= IC_RIGHT(ic);
4620     result = IC_RESULT(ic);
4621
4622     letype = getSpec(operandType(left));
4623     retype =getSpec(operandType(right));
4624     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4625
4626     /* assign the amsops */
4627     pic16_aopOp (left,ic,FALSE);
4628     pic16_aopOp (right,ic,FALSE);
4629     pic16_aopOp (result,ic,TRUE);
4630
4631     genCmp(left, right, result, ifx, sign);
4632
4633     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4634     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4635     pic16_freeAsmop(result,NULL,ic,TRUE);
4636 }
4637
4638 /*-----------------------------------------------------------------*/
4639 /* pic16_isLitOp - check if operand has to be treated as literal   */
4640 /*-----------------------------------------------------------------*/
4641 bool pic16_isLitOp(operand *op)
4642 {
4643   return ((AOP_TYPE(op) == AOP_LIT)
4644       || ( (AOP_TYPE(op) == AOP_PCODE)
4645           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
4646               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
4647 }
4648
4649 /*-----------------------------------------------------------------*/
4650 /* pic16_isLitAop - check if operand has to be treated as literal  */
4651 /*-----------------------------------------------------------------*/
4652 bool pic16_isLitAop(asmop *aop)
4653 {
4654   return ((aop->type == AOP_LIT)
4655       || ( (aop->type == AOP_PCODE)
4656           && ( (aop->aopu.pcop->type == PO_LITERAL)
4657               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
4658 }
4659
4660
4661
4662 /*-----------------------------------------------------------------*/
4663 /* genCmpEq - generates code for equal to                          */
4664 /*-----------------------------------------------------------------*/
4665 static void genCmpEq (iCode *ic, iCode *ifx)
4666 {
4667   operand *left, *right, *result;
4668   symbol *falselbl = newiTempLabel(NULL);
4669   symbol *donelbl = newiTempLabel(NULL);
4670
4671   int preserve_result = 0;
4672   int generate_result = 0;
4673   int i=0;
4674   unsigned long lit = -1;
4675
4676   FENTRY;
4677
4678   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4679   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4680   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4681
4682   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4683
4684   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
4685     {
4686       werror(W_POSSBUG2, __FILE__, __LINE__);
4687       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4688       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
4689       goto release;
4690     }
4691
4692   if (pic16_isLitOp(left) || (AOP_TYPE(right) == AOP_ACC))
4693     {
4694       operand *tmp = right ;
4695       right = left;
4696       left = tmp;
4697     }
4698
4699   if (AOP_TYPE(right) == AOP_LIT) {
4700     lit = ulFromVal (AOP(right)->aopu.aop_lit);
4701   }
4702
4703   if ( regsInCommon(left, result) || regsInCommon(right, result) )
4704     preserve_result = 1;
4705
4706   if(result && AOP_SIZE(result))
4707     generate_result = 1;
4708
4709   if(generate_result && !preserve_result)
4710     {
4711       for(i = 0; i < AOP_SIZE(result); i++)
4712         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4713     }
4714
4715   assert( AOP_SIZE(left) == AOP_SIZE(right) );
4716   for(i=0; i < AOP_SIZE(left); i++)
4717     {
4718       if(AOP_TYPE(left) != AOP_ACC)
4719         {
4720           if(pic16_isLitOp(left))
4721             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
4722           else
4723             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
4724         }
4725       if(pic16_isLitOp(right)) {
4726         if (pic16_isLitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
4727           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
4728         }
4729       } else
4730         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
4731
4732       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
4733     }
4734
4735   // result == true
4736
4737   if(generate_result && preserve_result)
4738     {
4739       for(i = 0; i < AOP_SIZE(result); i++)
4740         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4741     }
4742
4743   if(generate_result)
4744     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
4745
4746   if(generate_result && preserve_result)
4747     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4748
4749   if(ifx && IC_TRUE(ifx))
4750     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4751
4752   if(ifx && IC_FALSE(ifx))
4753     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4754
4755   pic16_emitpLabel(falselbl->key);
4756
4757   // result == false
4758
4759   if(ifx && IC_FALSE(ifx))
4760     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4761
4762   if(generate_result && preserve_result)
4763     {
4764       for(i = 0; i < AOP_SIZE(result); i++)
4765         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4766     }
4767
4768   pic16_emitpLabel(donelbl->key);
4769
4770   if(ifx)
4771     ifx->generated = 1;
4772
4773 release:
4774   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4775   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4776   pic16_freeAsmop(result,NULL,ic,TRUE);
4777
4778 }
4779
4780
4781 #if 0
4782 // old version kept for reference
4783
4784 /*-----------------------------------------------------------------*/
4785 /* genCmpEq - generates code for equal to                          */
4786 /*-----------------------------------------------------------------*/
4787 static void genCmpEq (iCode *ic, iCode *ifx)
4788 {
4789     operand *left, *right, *result;
4790     unsigned long lit = 0L;
4791     int size,offset=0;
4792     symbol *falselbl  = newiTempLabel(NULL);
4793
4794
4795     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4796
4797     if(ifx)
4798       DEBUGpic16_emitcode ("; ifx is non-null","");
4799     else
4800       DEBUGpic16_emitcode ("; ifx is null","");
4801
4802     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4803     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4804     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4805
4806     size = max(AOP_SIZE(left),AOP_SIZE(right));
4807
4808     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4809
4810     /* if literal, literal on the right or
4811     if the right is in a pointer register and left
4812     is not */
4813     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)) {
4814       operand *tmp = right ;
4815       right = left;
4816       left = tmp;
4817     }
4818
4819
4820     if(ifx && !AOP_SIZE(result)){
4821         symbol *tlbl;
4822         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
4823         /* if they are both bit variables */
4824         if (AOP_TYPE(left) == AOP_CRY &&
4825             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4826                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
4827             if(AOP_TYPE(right) == AOP_LIT){
4828                 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4829                 if(lit == 0L){
4830                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4831                     pic16_emitcode("cpl","c");
4832                 } else if(lit == 1L) {
4833                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4834                 } else {
4835                     pic16_emitcode("clr","c");
4836                 }
4837                 /* AOP_TYPE(right) == AOP_CRY */
4838             } else {
4839                 symbol *lbl = newiTempLabel(NULL);
4840                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4841                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4842                 pic16_emitcode("cpl","c");
4843                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4844             }
4845             /* if true label then we jump if condition
4846             supplied is true */
4847             tlbl = newiTempLabel(NULL);
4848             if ( IC_TRUE(ifx) ) {
4849                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4850                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4851             } else {
4852                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4853                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4854             }
4855             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
4856
4857                 {
4858                 /* left and right are both bit variables, result is carry */
4859                         resolvedIfx rIfx;
4860
4861                         resolveIfx(&rIfx,ifx);
4862
4863                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4864                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4865                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4866                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4867                         genSkipz2(&rIfx,0);
4868                 }
4869         } else {
4870
4871                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
4872
4873                         /* They're not both bit variables. Is the right a literal? */
4874                         if(AOP_TYPE(right) == AOP_LIT) {
4875                         lit = ulFromVal (AOP(right)->aopu.aop_lit);
4876
4877                         switch(size) {
4878
4879                                 case 1:
4880                                         switch(lit & 0xff) {
4881                                                 case 1:
4882                                                                 if ( IC_TRUE(ifx) ) {
4883                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4884                                                                         emitSKPNZ;
4885                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4886                                                                 } else {
4887                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4888                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4889                                                                 }
4890                                                                 break;
4891                                                 case 0xff:
4892                                                                 if ( IC_TRUE(ifx) ) {
4893                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4894                                                                         emitSKPNZ;
4895                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4896                                                                 } else {
4897                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4898                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4899                                                                 }
4900                                                                 break;
4901                                                 default:
4902                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4903                                                                 if(lit)
4904                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4905                                                                 genSkip(ifx,'z');
4906                                         } // switch lit
4907
4908
4909                                         /* end of size == 1 */
4910                                         break;
4911
4912                                 case 2:
4913                                         genc16bit2lit(left,lit,offset);
4914                                         genSkip(ifx,'z');
4915                                         break;
4916                                         /* end of size == 2 */
4917
4918                                 default:
4919                                         /* size is 4 */
4920                                         if(lit==0) {
4921                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4922                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4923                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4924                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4925                                                 genSkip(ifx,'z');
4926                                         } else {
4927                                                 /* search for patterns that can be optimized */
4928
4929                                                 genc16bit2lit(left,lit,0);
4930                                                 lit >>= 16;
4931                                                 if(lit) {
4932                                                                 if(IC_TRUE(ifx))
4933                                                                 emitSKPZ; // if hi word unequal
4934                                                                 else
4935                                                                 emitSKPNZ; // if hi word equal
4936                                                                 // fail early
4937                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
4938                                                         genc16bit2lit(left,lit,2);
4939                                                         genSkip(ifx,'z');
4940                                                 } else {
4941                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4942                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4943                                                         genSkip(ifx,'z');
4944                                                 }
4945                                         }
4946                                                 pic16_emitpLabel(falselbl->key);
4947                                                 break;
4948
4949                         } // switch size
4950
4951                         ifx->generated = 1;
4952                         goto release ;
4953
4954
4955           } else if(AOP_TYPE(right) == AOP_CRY ) {
4956             /* we know the left is not a bit, but that the right is */
4957             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4958             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4959                       pic16_popGet(AOP(right),offset));
4960             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4961
4962             /* if the two are equal, then W will be 0 and the Z bit is set
4963              * we could test Z now, or go ahead and check the high order bytes if
4964              * the variable we're comparing is larger than a byte. */
4965
4966             while(--size)
4967               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4968
4969             if ( IC_TRUE(ifx) ) {
4970               emitSKPNZ;
4971               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4972               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4973             } else {
4974               emitSKPZ;
4975               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4976               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4977             }
4978
4979           } else {
4980             /* They're both variables that are larger than bits */
4981             int s = size;
4982
4983             tlbl = newiTempLabel(NULL);
4984
4985             while(size--) {
4986               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4987               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4988
4989               if ( IC_TRUE(ifx) ) {
4990                 if(size) {
4991                   emitSKPZ;
4992
4993                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
4994
4995                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
4996                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
4997                 } else {
4998                   emitSKPNZ;
4999
5000                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5001
5002
5003                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5004                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5005                 }
5006               } else {
5007                 emitSKPZ;
5008
5009                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5010
5011                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5012                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5013               }
5014               offset++;
5015             }
5016             if(s>1 && IC_TRUE(ifx)) {
5017               pic16_emitpLabel(tlbl->key);
5018               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5019             }
5020           }
5021         }
5022         /* mark the icode as generated */
5023         ifx->generated = 1;
5024         goto release ;
5025     }
5026
5027     /* if they are both bit variables */
5028     if (AOP_TYPE(left) == AOP_CRY &&
5029         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5030         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5031         if(AOP_TYPE(right) == AOP_LIT){
5032             unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
5033             if(lit == 0L){
5034                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5035                 pic16_emitcode("cpl","c");
5036             } else if(lit == 1L) {
5037                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5038             } else {
5039                 pic16_emitcode("clr","c");
5040             }
5041             /* AOP_TYPE(right) == AOP_CRY */
5042         } else {
5043             symbol *lbl = newiTempLabel(NULL);
5044             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5045             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5046             pic16_emitcode("cpl","c");
5047             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5048         }
5049         /* c = 1 if egal */
5050         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5051             pic16_outBitC(result);
5052             goto release ;
5053         }
5054         if (ifx) {
5055             genIfxJump (ifx,"c");
5056             goto release ;
5057         }
5058         /* if the result is used in an arithmetic operation
5059         then put the result in place */
5060         pic16_outBitC(result);
5061     } else {
5062
5063       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5064       gencjne(left,right,result,ifx);
5065 /*
5066       if(ifx)
5067         gencjne(left,right,newiTempLabel(NULL));
5068       else {
5069         if(IC_TRUE(ifx)->key)
5070           gencjne(left,right,IC_TRUE(ifx)->key);
5071         else
5072           gencjne(left,right,IC_FALSE(ifx)->key);
5073         ifx->generated = 1;
5074         goto release ;
5075       }
5076       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5077         pic16_aopPut(AOP(result),"a",0);
5078         goto release ;
5079       }
5080
5081       if (ifx) {
5082         genIfxJump (ifx,"a");
5083         goto release ;
5084       }
5085 */
5086       /* if the result is used in an arithmetic operation
5087          then put the result in place */
5088 /*
5089       if (AOP_TYPE(result) != AOP_CRY)
5090         pic16_outAcc(result);
5091 */
5092       /* leave the result in acc */
5093     }
5094
5095 release:
5096     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5097     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5098     pic16_freeAsmop(result,NULL,ic,TRUE);
5099 }
5100 #endif
5101
5102 /*-----------------------------------------------------------------*/
5103 /* ifxForOp - returns the icode containing the ifx for operand     */
5104 /*-----------------------------------------------------------------*/
5105 static iCode *ifxForOp ( operand *op, iCode *ic )
5106 {
5107   FENTRY2;
5108
5109     /* if true symbol then needs to be assigned */
5110     if (IS_TRUE_SYMOP(op))
5111         return NULL ;
5112
5113     /* if this has register type condition and
5114     the next instruction is ifx with the same operand
5115     and live to of the operand is upto the ifx only then */
5116     if (ic->next
5117         && ic->next->op == IFX
5118         && IC_COND(ic->next)->key == op->key
5119         && OP_SYMBOL(op)->liveTo <= ic->next->seq
5120         ) {
5121                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
5122           return ic->next;
5123     }
5124
5125     /*
5126     if (ic->next &&
5127         ic->next->op == IFX &&
5128         IC_COND(ic->next)->key == op->key) {
5129       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5130       return ic->next;
5131     }
5132     */
5133
5134     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5135     if (ic->next &&
5136         ic->next->op == IFX)
5137       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5138
5139     if (ic->next &&
5140         ic->next->op == IFX &&
5141         IC_COND(ic->next)->key == op->key) {
5142       DEBUGpic16_emitcode ("; "," key is okay");
5143       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5144                            OP_SYMBOL(op)->liveTo,
5145                            ic->next->seq);
5146     }
5147
5148 #if 0
5149     /* the code below is completely untested
5150      * it just allows ulong2fs.c compile -- VR */
5151
5152     ic = ic->next;
5153     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
5154                                         __FILE__, __FUNCTION__, __LINE__);
5155
5156     /* if this has register type condition and
5157     the next instruction is ifx with the same operand
5158     and live to of the operand is upto the ifx only then */
5159     if (ic->next &&
5160         ic->next->op == IFX &&
5161         IC_COND(ic->next)->key == op->key &&
5162         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5163         return ic->next;
5164
5165     if (ic->next &&
5166         ic->next->op == IFX &&
5167         IC_COND(ic->next)->key == op->key) {
5168       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5169       return ic->next;
5170     }
5171
5172     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
5173                                         __FILE__, __FUNCTION__, __LINE__);
5174
5175 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
5176 #endif
5177
5178     return NULL;
5179 }
5180 /*-----------------------------------------------------------------*/
5181 /* genAndOp - for && operation                                     */
5182 /*-----------------------------------------------------------------*/
5183 static void genAndOp (iCode *ic)
5184 {
5185   operand *left,*right, *result;
5186 /*     symbol *tlbl; */
5187
5188     FENTRY;
5189
5190     /* note here that && operations that are in an
5191     if statement are taken away by backPatchLabels
5192     only those used in arthmetic operations remain */
5193     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5194     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5195     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5196
5197     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5198
5199     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5200     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5201     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5202
5203     /* if both are bit variables */
5204 /*     if (AOP_TYPE(left) == AOP_CRY && */
5205 /*         AOP_TYPE(right) == AOP_CRY ) { */
5206 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5207 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5208 /*         pic16_outBitC(result); */
5209 /*     } else { */
5210 /*         tlbl = newiTempLabel(NULL); */
5211 /*         pic16_toBoolean(left);     */
5212 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5213 /*         pic16_toBoolean(right); */
5214 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5215 /*         pic16_outBitAcc(result); */
5216 /*     } */
5217
5218     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5219     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5220     pic16_freeAsmop(result,NULL,ic,TRUE);
5221 }
5222
5223
5224 /*-----------------------------------------------------------------*/
5225 /* genOrOp - for || operation                                      */
5226 /*-----------------------------------------------------------------*/
5227 /*
5228   tsd pic port -
5229   modified this code, but it doesn't appear to ever get called
5230 */
5231
5232 static void genOrOp (iCode *ic)
5233 {
5234   operand *left,*right, *result;
5235   symbol *tlbl;
5236
5237     FENTRY;
5238
5239   /* note here that || operations that are in an
5240     if statement are taken away by backPatchLabels
5241     only those used in arthmetic operations remain */
5242     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5243     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5244     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5245
5246     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5247
5248     /* if both are bit variables */
5249     if (AOP_TYPE(left) == AOP_CRY &&
5250         AOP_TYPE(right) == AOP_CRY ) {
5251       pic16_emitcode("clrc","");
5252       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5253                AOP(left)->aopu.aop_dir,
5254                AOP(left)->aopu.aop_dir);
5255       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5256                AOP(right)->aopu.aop_dir,
5257                AOP(right)->aopu.aop_dir);
5258       pic16_emitcode("setc","");
5259
5260     } else {
5261         tlbl = newiTempLabel(NULL);
5262         pic16_toBoolean(left);
5263         emitSKPZ;
5264         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
5265         pic16_toBoolean(right);
5266         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5267
5268         pic16_outBitAcc(result);
5269     }
5270
5271     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5272     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5273     pic16_freeAsmop(result,NULL,ic,TRUE);
5274 }
5275
5276 /*-----------------------------------------------------------------*/
5277 /* isLiteralBit - test if lit == 2^n                               */
5278 /*-----------------------------------------------------------------*/
5279 static int isLiteralBit(unsigned long lit)
5280 {
5281     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5282     0x100L,0x200L,0x400L,0x800L,
5283     0x1000L,0x2000L,0x4000L,0x8000L,
5284     0x10000L,0x20000L,0x40000L,0x80000L,
5285     0x100000L,0x200000L,0x400000L,0x800000L,
5286     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5287     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5288     int idx;
5289
5290     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5291     for(idx = 0; idx < 32; idx++)
5292         if(lit == pw[idx])
5293             return idx+1;
5294     return 0;
5295 }
5296
5297 /*-----------------------------------------------------------------*/
5298 /* continueIfTrue -                                                */
5299 /*-----------------------------------------------------------------*/
5300 static void continueIfTrue (iCode *ic)
5301 {
5302   FENTRY;
5303   if(IC_TRUE(ic))
5304     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5305   ic->generated = 1;
5306 }
5307
5308 /*-----------------------------------------------------------------*/
5309 /* jmpIfTrue -                                                     */
5310 /*-----------------------------------------------------------------*/
5311 static void jumpIfTrue (iCode *ic)
5312 {
5313   FENTRY;
5314   if(!IC_TRUE(ic))
5315     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5316   ic->generated = 1;
5317 }
5318
5319 /*-----------------------------------------------------------------*/
5320 /* jmpTrueOrFalse -                                                */
5321 /*-----------------------------------------------------------------*/
5322 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5323 {
5324   // ugly but optimized by peephole
5325   FENTRY;
5326   if(IC_TRUE(ic)){
5327     symbol *nlbl = newiTempLabel(NULL);
5328       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5329       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5330       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5331       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5332   } else {
5333     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5334     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5335   }
5336   ic->generated = 1;
5337 }
5338
5339 /*-----------------------------------------------------------------*/
5340 /* genAnd  - code for and                                          */
5341 /*-----------------------------------------------------------------*/
5342 static void genAnd (iCode *ic, iCode *ifx)
5343 {
5344   operand *left, *right, *result;
5345   int size, offset = 0;
5346   unsigned long lit = 0L;
5347   resolvedIfx rIfx;
5348
5349   FENTRY;
5350
5351   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5352   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5353   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5354
5355   resolveIfx (&rIfx, ifx);
5356
5357   /* if left is a literal & right is not then exchange them */
5358   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5359       AOP_NEEDSACC (left))
5360     {
5361       operand *tmp = right;
5362       right = left;
5363       left = tmp;
5364     }
5365
5366   /* if result = right then exchange them */
5367   if (pic16_sameRegs (AOP (result), AOP (right)))
5368     {
5369       operand *tmp = right;
5370       right = left;
5371       left = tmp;
5372     }
5373
5374   /* if right is bit then exchange them */
5375   if (AOP_TYPE (right) == AOP_CRY &&
5376       AOP_TYPE (left) != AOP_CRY)
5377     {
5378       operand *tmp = right;
5379       right = left;
5380       left = tmp;
5381     }
5382
5383   if (AOP_TYPE (right) == AOP_LIT)
5384     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5385
5386   size = AOP_SIZE (result);
5387
5388   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5389
5390   // if(bit & yy)
5391   // result = bit & yy;
5392   if (AOP_TYPE(left) == AOP_CRY){
5393     // c = bit & literal;
5394     if(AOP_TYPE(right) == AOP_LIT){
5395       if(lit & 1) {
5396         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5397           // no change
5398           goto release;
5399         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5400       } else {
5401         // bit(result) = 0;
5402         if(size && (AOP_TYPE(result) == AOP_CRY)){
5403           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5404           goto release;
5405         }
5406         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5407           jumpIfTrue(ifx);
5408           goto release;
5409         }
5410         pic16_emitcode("clr","c");
5411       }
5412     } else {
5413       if (AOP_TYPE(right) == AOP_CRY){
5414         // c = bit & bit;
5415         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5416         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5417       } else {
5418         // c = bit & val;
5419         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5420         // c = lsb
5421         pic16_emitcode("rrc","a");
5422         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5423       }
5424     }
5425     // bit = c
5426     // val = c
5427     if(size)
5428       pic16_outBitC(result);
5429     // if(bit & ...)
5430     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5431       genIfxJump(ifx, "c");
5432     goto release ;
5433   }
5434
5435   // if (val & 0xZZ)      - size = 0, ifx != FALSE -
5436   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5437   if ((AOP_TYPE (right) == AOP_LIT) &&
5438      (AOP_TYPE (result) == AOP_CRY) &&
5439      (AOP_TYPE (left) != AOP_CRY))
5440     {
5441       symbol *tlbl = newiTempLabel (NULL);
5442       int sizel = AOP_SIZE (left);
5443       int nonnull = 0;
5444       char emitBra;
5445
5446       if (size)
5447         emitSETC;
5448
5449       /* get number of non null bytes in literal */
5450       while (sizel--)
5451         {
5452           if (lit & (0xff << (sizel * 8)))
5453             ++nonnull;
5454         }
5455
5456       emitBra = nonnull || rIfx.condition;
5457
5458       for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
5459         {
5460           unsigned char bytelit = lit;
5461
5462           if (bytelit != 0)
5463             {
5464               int posbit;
5465
5466               --nonnull;
5467
5468               /* patch provided by Aaron Colwell */
5469               if ((posbit = isLiteralBit (bytelit)) != 0)
5470                 {
5471                   if (nonnull)
5472                     {
5473                       pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5474                       pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
5475                     }
5476                   else
5477                     {
5478                       pic16_emitpcode (rIfx.condition ? POC_BTFSC :POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5479                     }
5480                 }
5481               else
5482                 {
5483                   if (bytelit == 0xff)
5484                     {
5485                       /* Aaron had a MOVF instruction here, changed to MOVFW cause
5486                        * a peephole could optimize it out -- VR */
5487                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5488                     }
5489                   else
5490                     {
5491                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5492                       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit));
5493                     }
5494                   if (nonnull)
5495                     {
5496                       if (rIfx.condition)
5497                         {
5498                           emitSKPZ;
5499                           pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5500                         }
5501                       else
5502                         {
5503                           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
5504                         }
5505                     }
5506                   else
5507                     {
5508                       /* last non null byte */
5509                       if (rIfx.condition)
5510                         emitSKPZ;
5511                       else
5512                         emitSKPNZ;
5513                     }
5514                 }
5515             }
5516         }
5517
5518       // bit = left & literal
5519       if (size)
5520         {
5521           emitCLRC;
5522           pic16_emitpLabel (tlbl->key);
5523         }
5524
5525       // if(left & literal)
5526       else
5527         {
5528           if (ifx)
5529             {
5530               if (emitBra)
5531                 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));
5532               ifx->generated = 1;
5533             }
5534           pic16_emitpLabel (tlbl->key);
5535           goto release;
5536         }
5537       pic16_outBitC (result);
5538       goto release;
5539     }
5540
5541   /* if left is same as result */
5542   if(pic16_sameRegs(AOP(result),AOP(left))){
5543     int know_W = -1;
5544     for(;size--; offset++,lit>>=8) {
5545       if(AOP_TYPE(right) == AOP_LIT){
5546         switch(lit & 0xff) {
5547         case 0x00:
5548           /*  and'ing with 0 has clears the result */
5549 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5550           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5551           break;
5552         case 0xff:
5553           /* and'ing with 0xff is a nop when the result and left are the same */
5554           break;
5555
5556         default:
5557           {
5558             int p = pic16_my_powof2( (~lit) & 0xff );
5559             if(p>=0) {
5560               /* only one bit is set in the literal, so use a bcf instruction */
5561 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5562               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5563
5564             } else {
5565               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5566               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5567               if(know_W != (lit&0xff))
5568                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5569               know_W = lit &0xff;
5570               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5571             }
5572           }
5573         }
5574       } else {
5575         if (AOP_TYPE(left) == AOP_ACC) {
5576           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5577         } else {
5578           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5579           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5580
5581         }
5582       }
5583     }
5584
5585   } else {
5586     // left & result in different registers
5587     if(AOP_TYPE(result) == AOP_CRY){
5588       // result = bit
5589       // if(size), result in bit
5590       // if(!size && ifx), conditional oper: if(left & right)
5591       symbol *tlbl = newiTempLabel(NULL);
5592       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5593       if(size)
5594         pic16_emitcode("setb","c");
5595       while(sizer--){
5596         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5597         pic16_emitcode("anl","a,%s",
5598                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5599         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5600         offset++;
5601       }
5602       if(size){
5603         CLRC;
5604         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5605         pic16_outBitC(result);
5606       } else if(ifx)
5607         jmpTrueOrFalse(ifx, tlbl);
5608     } else {
5609       for(;(size--);offset++) {
5610         // normal case
5611         // result = left & right
5612         if(AOP_TYPE(right) == AOP_LIT){
5613           int t = (lit >> (offset*8)) & 0x0FFL;
5614           switch(t) {
5615           case 0x00:
5616             pic16_emitcode("clrf","%s",
5617                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5618             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5619             break;
5620           case 0xff:
5621             pic16_emitcode("movf","%s,w",
5622                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5623             pic16_emitcode("movwf","%s",
5624                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5625             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5626             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5627             break;
5628           default:
5629             pic16_emitcode("movlw","0x%x",t);
5630             pic16_emitcode("andwf","%s,w",
5631                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5632             pic16_emitcode("movwf","%s",
5633                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5634
5635             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5636             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5637             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5638           }
5639           continue;
5640         }
5641
5642         if (AOP_TYPE(left) == AOP_ACC) {
5643           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5644           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5645         } else {
5646           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5647           pic16_emitcode("andwf","%s,w",
5648                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5649           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5650           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5651         }
5652         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5653         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5654       }
5655     }
5656   }
5657
5658 release :
5659   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5660   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5661   pic16_freeAsmop(result,NULL,ic,TRUE);
5662 }
5663
5664 /*-----------------------------------------------------------------*/
5665 /* genOr  - code for or                                            */
5666 /*-----------------------------------------------------------------*/
5667 static void genOr (iCode *ic, iCode *ifx)
5668 {
5669   operand *left, *right, *result;
5670   int size, offset = 0;
5671   unsigned long lit = 0L;
5672   resolvedIfx rIfx;
5673
5674   FENTRY;
5675
5676   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5677   pic16_aopOp ((right= IC_RIGHT (ic)), ic, FALSE);
5678   pic16_aopOp ((result=IC_RESULT (ic)), ic, TRUE);
5679
5680   resolveIfx (&rIfx, ifx);
5681
5682   /* if left is a literal & right is not then exchange them */
5683   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5684       AOP_NEEDSACC (left))
5685     {
5686       operand *tmp = right;
5687       right = left;
5688       left = tmp;
5689     }
5690
5691   /* if result = right then exchange them */
5692   if (pic16_sameRegs (AOP (result), AOP (right)))
5693     {
5694       operand *tmp = right;
5695       right = left;
5696       left = tmp;
5697     }
5698
5699   /* if right is bit then exchange them */
5700   if (AOP_TYPE (right) == AOP_CRY &&
5701       AOP_TYPE (left) != AOP_CRY)
5702     {
5703       operand *tmp = right;
5704       right = left;
5705       left = tmp;
5706     }
5707
5708   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5709
5710   if (AOP_TYPE (right) == AOP_LIT)
5711       lit = ulFromVal (AOP (right)->aopu.aop_lit);
5712
5713   size = AOP_SIZE (result);
5714
5715   // if(bit | yy)
5716   // xx = bit | yy;
5717   if (AOP_TYPE(left) == AOP_CRY){
5718       if(AOP_TYPE(right) == AOP_LIT){
5719           // c = bit & literal;
5720           if(lit){
5721               // lit != 0 => result = 1
5722               if(AOP_TYPE(result) == AOP_CRY){
5723                 if(size)
5724                   pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5725                 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5726                 //     AOP(result)->aopu.aop_dir,
5727                 //     AOP(result)->aopu.aop_dir);
5728                   else if(ifx)
5729                       continueIfTrue(ifx);
5730                   goto release;
5731               }
5732           } else {
5733               // lit == 0 => result = left
5734               if(size && pic16_sameRegs(AOP(result),AOP(left)))
5735                   goto release;
5736               pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5737           }
5738       } else {
5739           if (AOP_TYPE(right) == AOP_CRY){
5740             if(pic16_sameRegs(AOP(result),AOP(left))){
5741               // c = bit | bit;
5742               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5743               pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5744               pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5745
5746             } else {
5747               if( AOP_TYPE(result) == AOP_ACC) {
5748                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5749                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5750                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5751                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5752
5753               } else {
5754
5755                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5756                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5757                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5758                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5759
5760               }
5761             }
5762           } else {
5763               // c = bit | val;
5764               symbol *tlbl = newiTempLabel(NULL);
5765               pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5766
5767
5768               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5769               if( AOP_TYPE(right) == AOP_ACC) {
5770                 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5771                 emitSKPNZ;
5772                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5773                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5774               }
5775
5776
5777
5778               if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5779                   pic16_emitcode(";XXX setb","c");
5780               pic16_emitcode(";XXX jb","%s,%05d_DS_",
5781                        AOP(left)->aopu.aop_dir,tlbl->key+100);
5782               pic16_toBoolean(right);
5783               pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5784               if((AOP_TYPE(result) == AOP_CRY) && ifx){
5785                   jmpTrueOrFalse(ifx, tlbl);
5786                   goto release;
5787               } else {
5788                   CLRC;
5789                   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5790               }
5791           }
5792       }
5793       // bit = c
5794       // val = c
5795       if(size)
5796           pic16_outBitC(result);
5797       // if(bit | ...)
5798       else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5799           genIfxJump(ifx, "c");
5800       goto release ;
5801   }
5802
5803   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5804   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5805   if ((AOP_TYPE (right) == AOP_LIT) &&
5806      (AOP_TYPE (result) == AOP_CRY) &&
5807      (AOP_TYPE (left) != AOP_CRY))
5808     {
5809       if (IS_OP_VOLATILE(left)) {
5810           pic16_mov2w_volatile(AOP(left));
5811       } // if
5812       if (lit)
5813         {
5814           if (rIfx.condition)
5815             pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5816           ifx->generated = 1;
5817         }
5818       else
5819         wassert (0);
5820
5821       goto release;
5822   }
5823
5824   /* if left is same as result */
5825   if(pic16_sameRegs(AOP(result),AOP(left))){
5826     int know_W = -1;
5827     for(;size--; offset++,lit>>=8) {
5828       if(AOP_TYPE(right) == AOP_LIT){
5829         if(((lit & 0xff) == 0) && !IS_OP_VOLATILE(left)) {
5830           /*  or'ing with 0 has no effect */
5831           continue;
5832         } else {
5833           int p = pic16_my_powof2(lit & 0xff);
5834           if(p>=0) {
5835             /* only one bit is set in the literal, so use a bsf instruction */
5836             pic16_emitpcode(POC_BSF,
5837                       pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5838           } else {
5839             if(know_W != (lit & 0xff))
5840               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5841             know_W = lit & 0xff;
5842             pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5843           }
5844
5845         }
5846       } else {
5847         if (AOP_TYPE(left) == AOP_ACC) {
5848           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5849         } else {
5850           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5851           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5852         }
5853       }
5854     }
5855   } else {
5856       // left & result in different registers
5857       if(AOP_TYPE(result) == AOP_CRY){
5858           // result = bit
5859           // if(size), result in bit
5860           // if(!size && ifx), conditional oper: if(left | right)
5861           symbol *tlbl = newiTempLabel(NULL);
5862           int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5863           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5864
5865
5866           if(size)
5867               pic16_emitcode(";XXX setb","c");
5868           while(sizer--){
5869               MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5870               pic16_emitcode(";XXX orl","a,%s",
5871                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5872               pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5873               offset++;
5874           }
5875           if(size){
5876               CLRC;
5877               pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5878               pic16_outBitC(result);
5879           } else if(ifx)
5880               jmpTrueOrFalse(ifx, tlbl);
5881       } else for(;(size--);offset++){
5882         // normal case
5883         // result = left & right
5884         if(AOP_TYPE(right) == AOP_LIT){
5885           int t = (lit >> (offset*8)) & 0x0FFL;
5886           switch(t) {
5887           case 0x00:
5888             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
5889             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5890             break;
5891           default:
5892             pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
5893             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5894             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5895           }
5896           continue;
5897         }
5898
5899         // faster than result <- left, anl result,right
5900         // and better if result is SFR
5901         if (AOP_TYPE(left) == AOP_ACC) {
5902           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
5903         } else {
5904           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5905           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5906         }
5907         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5908       }
5909   }
5910
5911 release :
5912   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5913   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5914   pic16_freeAsmop(result,NULL,ic,TRUE);
5915 }
5916
5917 /*-----------------------------------------------------------------*/
5918 /* genXor - code for xclusive or                                   */
5919 /*-----------------------------------------------------------------*/
5920 static void genXor (iCode *ic, iCode *ifx)
5921 {
5922   operand *left, *right, *result;
5923   int size, offset = 0;
5924   unsigned long lit = 0L;
5925   resolvedIfx rIfx;
5926
5927   FENTRY;
5928
5929   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5930   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5931   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5932
5933   resolveIfx (&rIfx,ifx);
5934
5935   /* if left is a literal & right is not ||
5936      if left needs acc & right does not */
5937   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5938       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5939     {
5940       operand *tmp = right;
5941       right = left;
5942       left = tmp;
5943     }
5944
5945   /* if result = right then exchange them */
5946   if (pic16_sameRegs (AOP (result), AOP (right)))
5947     {
5948       operand *tmp = right ;
5949       right = left;
5950       left = tmp;
5951     }
5952
5953   /* if right is bit then exchange them */
5954   if (AOP_TYPE (right) == AOP_CRY &&
5955       AOP_TYPE (left) != AOP_CRY)
5956     {
5957       operand *tmp = right ;
5958       right = left;
5959       left = tmp;
5960     }
5961
5962   if (AOP_TYPE (right) == AOP_LIT)
5963     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5964
5965   size = AOP_SIZE (result);
5966
5967   // if(bit ^ yy)
5968   // xx = bit ^ yy;
5969   if (AOP_TYPE(left) == AOP_CRY)
5970     {
5971       if (AOP_TYPE(right) == AOP_LIT)
5972         {
5973           // c = bit & literal;
5974           if (lit >> 1)
5975             {
5976               // lit>>1  != 0 => result = 1
5977               if (AOP_TYPE(result) == AOP_CRY)
5978                 {
5979                   if (size)
5980                     {
5981                       pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result), offset));
5982                     }
5983                   else if (ifx)
5984                     continueIfTrue(ifx);
5985                   goto release;
5986                 }
5987               pic16_emitcode("setb", "c");
5988             }
5989           else
5990             {
5991               // lit == (0 or 1)
5992               if (lit == 0)
5993                 {
5994                   // lit == 0, result = left
5995                   if (size && pic16_sameRegs(AOP(result), AOP(left)))
5996                     goto release;
5997                   pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
5998                 }
5999               else
6000                 {
6001                   // lit == 1, result = not(left)
6002                   if (size && pic16_sameRegs(AOP(result), AOP(left)))
6003                     {
6004                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result), offset));
6005                       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result), offset));
6006                       pic16_emitcode("cpl", "%s", AOP(result)->aopu.aop_dir);
6007                       goto release;
6008                     }
6009                   else
6010                     {
6011                       pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6012                       pic16_emitcode("cpl", "c");
6013                     }
6014                 }
6015             }
6016         }
6017       else
6018         {
6019           // right != literal
6020           symbol *tlbl = newiTempLabel(NULL);
6021           if (AOP_TYPE(right) == AOP_CRY)
6022             {
6023               // c = bit ^ bit;
6024               pic16_emitcode("mov", "c,%s", AOP(right)->aopu.aop_dir);
6025             }
6026           else
6027             {
6028               int sizer = AOP_SIZE(right);
6029               // c = bit ^ val
6030               // if val>>1 != 0, result = 1
6031               pic16_emitcode("setb", "c");
6032               while (sizer)
6033                 {
6034                   MOVA(pic16_aopGet(AOP(right), sizer - 1, FALSE, FALSE));
6035                   if (sizer == 1)
6036                     // test the msb of the lsb
6037                     pic16_emitcode("anl", "a,#0xfe");
6038                   pic16_emitcode("jnz", "%05d_DS_", tlbl->key+100);
6039                   sizer--;
6040                 }
6041               // val = (0,1)
6042               pic16_emitcode("rrc", "a");
6043             }
6044           pic16_emitcode("jnb", "%s,%05d_DS_", AOP(left)->aopu.aop_dir, (tlbl->key + 100));
6045           pic16_emitcode("cpl", "c");
6046           pic16_emitcode("", "%05d_DS_:", (tlbl->key + 100));
6047         }
6048       // bit = c
6049       // val = c
6050       if (size)
6051         pic16_outBitC(result);
6052       // if(bit | ...)
6053       else if ((AOP_TYPE(result) == AOP_CRY) && ifx)
6054         genIfxJump(ifx, "c");
6055       goto release;
6056     }
6057
6058   // if(val ^ 0xZZ)       - size = 0, ifx != FALSE  -
6059   // bit = val ^ 0xZZ     - size = 1, ifx = FALSE -
6060   if ((AOP_TYPE (right) == AOP_LIT) &&
6061      (AOP_TYPE (result) == AOP_CRY) &&
6062      (AOP_TYPE (left) != AOP_CRY))
6063     {
6064       symbol *tlbl = newiTempLabel (NULL);
6065       int sizel;
6066
6067       if (size)
6068         emitSETC;
6069
6070       for (sizel = AOP_SIZE(left); sizel--; ++offset, lit >>= 8)
6071         {
6072           unsigned char bytelit = lit;
6073
6074           switch (bytelit)
6075             {
6076             case 0xff:
6077               pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
6078               break;
6079
6080             case 0x00:
6081               pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6082               break;
6083
6084             default:
6085               pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit));
6086               pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
6087               break;
6088             }
6089           if (sizel)
6090             {
6091               if (rIfx.condition)
6092                 {
6093                   /* rIfx.lbl might be far away... */
6094                   emitSKPZ;
6095                   pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
6096                 }
6097               else
6098                 {
6099                   pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
6100                 }
6101             }
6102           else
6103             {
6104               /* last non null byte */
6105               if (rIfx.condition)
6106                 emitSKPZ;
6107               else
6108                 emitSKPNZ;
6109             }
6110         }
6111
6112       // bit = left ^ literal
6113       if (size)
6114         {
6115           emitCLRC;
6116           pic16_emitpLabel (tlbl->key);
6117         }
6118       // if (left ^ literal)
6119       else
6120         {
6121           if (ifx)
6122             {
6123               pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));
6124               ifx->generated = 1;
6125             }
6126           pic16_emitpLabel (tlbl->key);
6127           goto release;
6128         }
6129
6130       pic16_outBitC (result);
6131       goto release;
6132   }
6133
6134   if (pic16_sameRegs(AOP(result), AOP(left)))
6135     {
6136       /* if left is same as result */
6137       for (; size--; offset++)
6138         {
6139           if (AOP_TYPE(right) == AOP_LIT)
6140             {
6141               int t  = (lit >> (offset * 8)) & 0x0FFL;
6142               if  (t == 0x00L)
6143                 continue;
6144               else
6145                 {
6146                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6147                   pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6148                 }
6149             }
6150           else
6151             {
6152               if (AOP_TYPE(left) == AOP_ACC)
6153                 pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6154               else
6155                 {
6156                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6157                   pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6158                 }
6159             }
6160         }
6161     }
6162   else
6163     {
6164     // left ^ result in different registers
6165     if (AOP_TYPE(result) == AOP_CRY)
6166       {
6167         // result = bit
6168         // if(size), result in bit
6169         // if(!size && ifx), conditional oper: if(left ^ right)
6170         symbol *tlbl = newiTempLabel(NULL);
6171         int sizer = max(AOP_SIZE(left), AOP_SIZE(right));
6172         if (size)
6173           pic16_emitcode("setb", "c");
6174         while (sizer--)
6175           {
6176             if ((AOP_TYPE(right) == AOP_LIT) &&
6177               (((lit >> (offset*8)) & 0x0FFL) == 0x00L))
6178               {
6179                 MOVA(pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6180               }
6181             else
6182               {
6183                 MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6184                 pic16_emitcode("xrl", "a,%s",
6185                                pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6186               }
6187             pic16_emitcode("jnz", "%05d_DS_", tlbl->key + 100);
6188             offset++;
6189           }
6190         if (size)
6191           {
6192             CLRC;
6193             pic16_emitcode("", "%05d_DS_:", tlbl->key + 100);
6194             pic16_outBitC(result);
6195           }
6196         else if (ifx)
6197           jmpTrueOrFalse(ifx, tlbl);
6198       }
6199     else
6200       {
6201         for (; (size--); offset++)
6202           {
6203             // normal case
6204             // result = left ^ right
6205             if (AOP_TYPE(right) == AOP_LIT)
6206               {
6207                 int t = (lit >> (offset * 8)) & 0x0FFL;
6208                 switch(t)
6209                   {
6210                   case 0x00:
6211                     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6212                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6213                     break;
6214
6215                   case 0xff:
6216                     pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(left), offset));
6217                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6218                     break;
6219
6220                   default:
6221                     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6222                     pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6223                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6224                   }
6225                 continue;
6226               }
6227
6228             // faster than result <- left, anl result,right
6229             // and better if result is SFR
6230             if (AOP_TYPE(left) == AOP_ACC)
6231               {
6232                 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), offset));
6233               }
6234             else
6235               {
6236                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6237                 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6238               }
6239             if ( AOP_TYPE(result) != AOP_ACC)
6240               {
6241                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6242               }
6243           }
6244       }
6245   }
6246
6247 release :
6248   pic16_freeAsmop(left, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6249   pic16_freeAsmop(right, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6250   pic16_freeAsmop(result, NULL, ic, TRUE);
6251 }
6252
6253 /*-----------------------------------------------------------------*/
6254 /* genInline - write the inline code out                           */
6255 /*-----------------------------------------------------------------*/
6256 static void genInline (iCode *ic)
6257 {
6258   char *buffer, *bp, *bp1;
6259   bool inComment = FALSE;
6260
6261   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6262
6263   _G.inLine += (!options.asmpeep);
6264
6265   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
6266
6267   while((bp1=strstr(bp, "\\n"))) {
6268     *bp1++ = '\n';
6269     *bp1++ = ' ';
6270     bp = bp1;
6271   }
6272   bp = bp1 = buffer;
6273
6274 #if 0
6275   /* This is an experimental code for #pragma inline
6276      and is temporarily disabled for 2.5.0 release */
6277   if(asmInlineMap)
6278   {
6279     symbol *sym;
6280     char *s;
6281     char *cbuf;
6282     int cblen;
6283
6284       cbuf = Safe_strdup(buffer);
6285       cblen = strlen(buffer)+1;
6286       memset(cbuf, 0, cblen);
6287
6288       bp = buffer;
6289       bp1 = cbuf;
6290       while(*bp) {
6291         if(*bp != '%')*bp1++ = *bp++;
6292         else {
6293           int i;
6294
6295             bp++;
6296             i = *bp - '0';
6297             if(i>elementsInSet(asmInlineMap))break;
6298
6299             bp++;
6300             s = indexSet(asmInlineMap, i);
6301             DEBUGpc("searching symbol s = `%s'", s);
6302             sym = findSym(SymbolTab, NULL, s);
6303
6304             if(sym->reqv) {
6305               strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
6306             } else {
6307               strcat(bp1, sym->rname);
6308             }
6309
6310             while(*bp1)bp1++;
6311         }
6312
6313         if(strlen(bp1) > cblen - 16) {
6314           int i = strlen(cbuf);
6315           cblen += 50;
6316           cbuf = realloc(cbuf, cblen);
6317           memset(cbuf+i, 0, 50);
6318           bp1 = cbuf + i;
6319         }
6320       }
6321
6322       free(buffer);
6323       buffer = Safe_strdup( cbuf );
6324       free(cbuf);
6325
6326       bp = bp1 = buffer;
6327   }
6328 #endif  /* 0 */
6329
6330   /* emit each line as a code */
6331   while (*bp)
6332     {
6333       switch (*bp)
6334         {
6335         case ';':
6336           inComment = TRUE;
6337           ++bp;
6338           break;
6339
6340         case '\n':
6341           inComment = FALSE;
6342           *bp++ = '\0';
6343           if (*bp1)
6344             pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6345           bp1 = bp;
6346           break;
6347
6348         default:
6349           /* Add \n for labels, not dirs such as c:\mydir */
6350           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
6351             {
6352               ++bp;
6353               *bp = '\0';
6354               ++bp;
6355               /* print label, use this special format with NULL directive
6356                * to denote that the argument should not be indented with tab */
6357               pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6358               bp1 = bp;
6359             }
6360           else
6361             ++bp;
6362           break;
6363         }
6364     }
6365
6366   if ((bp1 != bp) && *bp1)
6367     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6368
6369   Safe_free (buffer);
6370
6371   _G.inLine -= (!options.asmpeep);
6372 }
6373
6374 /*-----------------------------------------------------------------*/
6375 /* genRRC - rotate right with carry                                */
6376 /*-----------------------------------------------------------------*/
6377 static void genRRC (iCode *ic)
6378 {
6379   operand *left , *result ;
6380   int size, same;
6381
6382   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6383
6384   /* rotate right with carry */
6385   left = IC_LEFT(ic);
6386   result=IC_RESULT(ic);
6387   pic16_aopOp (left,ic,FALSE);
6388   pic16_aopOp (result,ic,TRUE);
6389
6390   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6391
6392   same = pic16_sameRegs(AOP(result),AOP(left));
6393
6394   size = AOP_SIZE(result);
6395
6396   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6397
6398   /* get the lsb and put it into the carry */
6399   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0));
6400
6401   while(size--) {
6402
6403     if(same) {
6404       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),size));
6405     } else {
6406       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size));
6407       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),size));
6408     }
6409   }
6410
6411   pic16_freeAsmop(left,NULL,ic,TRUE);
6412   pic16_freeAsmop(result,NULL,ic,TRUE);
6413 }
6414
6415 /*-----------------------------------------------------------------*/
6416 /* genRLC - generate code for rotate left with carry               */
6417 /*-----------------------------------------------------------------*/
6418 static void genRLC (iCode *ic)
6419 {
6420   operand *left , *result ;
6421   int size, offset = 0;
6422   int same;
6423
6424   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6425   /* rotate right with carry */
6426   left = IC_LEFT(ic);
6427   result=IC_RESULT(ic);
6428   pic16_aopOp (left,ic,FALSE);
6429   pic16_aopOp (result,ic,TRUE);
6430
6431   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6432
6433   same = pic16_sameRegs(AOP(result),AOP(left));
6434
6435   /* move it to the result */
6436   size = AOP_SIZE(result);
6437
6438   /* get the msb and put it into the carry */
6439   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6440
6441   offset = 0 ;
6442
6443   while(size--) {
6444
6445     if(same) {
6446       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6447     } else {
6448       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6449       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6450     }
6451
6452     offset++;
6453   }
6454
6455
6456   pic16_freeAsmop(left,NULL,ic,TRUE);
6457   pic16_freeAsmop(result,NULL,ic,TRUE);
6458 }
6459
6460
6461 /* gpasm can get the highest order bit with HIGH/UPPER
6462  * so the following probably is not needed -- VR */
6463
6464 /*-----------------------------------------------------------------*/
6465 /* genGetHbit - generates code get highest order bit               */
6466 /*-----------------------------------------------------------------*/
6467 static void genGetHbit (iCode *ic)
6468 {
6469     operand *left, *result;
6470     left = IC_LEFT(ic);
6471     result=IC_RESULT(ic);
6472     pic16_aopOp (left,ic,FALSE);
6473     pic16_aopOp (result,ic,FALSE);
6474
6475     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6476     /* get the highest order byte into a */
6477     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6478     if(AOP_TYPE(result) == AOP_CRY){
6479         pic16_emitcode("rlc","a");
6480         pic16_outBitC(result);
6481     }
6482     else{
6483         pic16_emitcode("rl","a");
6484         pic16_emitcode("anl","a,#0x01");
6485         pic16_outAcc(result);
6486     }
6487
6488
6489     pic16_freeAsmop(left,NULL,ic,TRUE);
6490     pic16_freeAsmop(result,NULL,ic,TRUE);
6491 }
6492
6493 #if 0
6494 /*-----------------------------------------------------------------*/
6495 /* AccRol - rotate left accumulator by known count                 */
6496 /*-----------------------------------------------------------------*/
6497 static void AccRol (int shCount)
6498 {
6499     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6500     shCount &= 0x0007;              // shCount : 0..7
6501     switch(shCount){
6502         case 0 :
6503             break;
6504         case 1 :
6505             pic16_emitcode("rl","a");
6506             break;
6507         case 2 :
6508             pic16_emitcode("rl","a");
6509             pic16_emitcode("rl","a");
6510             break;
6511         case 3 :
6512             pic16_emitcode("swap","a");
6513             pic16_emitcode("rr","a");
6514             break;
6515         case 4 :
6516             pic16_emitcode("swap","a");
6517             break;
6518         case 5 :
6519             pic16_emitcode("swap","a");
6520             pic16_emitcode("rl","a");
6521             break;
6522         case 6 :
6523             pic16_emitcode("rr","a");
6524             pic16_emitcode("rr","a");
6525             break;
6526         case 7 :
6527             pic16_emitcode("rr","a");
6528             break;
6529     }
6530 }
6531 #endif
6532
6533 /*-----------------------------------------------------------------*/
6534 /* AccLsh - left shift accumulator by known count                  */
6535 /*-----------------------------------------------------------------*/
6536 static void AccLsh (int shCount, int doMask)
6537 {
6538         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6539         switch(shCount){
6540                 case 0 :
6541                         return;
6542                         break;
6543                 case 1 :
6544                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6545                         break;
6546                 case 2 :
6547                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6548                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6549                         break;
6550                 case 3 :
6551                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6552                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6553                         break;
6554                 case 4 :
6555                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6556                         break;
6557                 case 5 :
6558                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6559                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6560                         break;
6561                 case 6 :
6562                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6563                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6564                         break;
6565                 case 7 :
6566                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6567                         break;
6568         }
6569         if (doMask) {
6570                 /* no masking is required in genPackBits */
6571                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6572         }
6573 }
6574
6575 /*-----------------------------------------------------------------*/
6576 /* AccRsh - right shift accumulator by known count                 */
6577 /*-----------------------------------------------------------------*/
6578 static void AccRsh (int shCount, int andmask)
6579 {
6580         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6581         assert ((shCount >= 0) && (shCount <= 8));
6582         switch (shCount) {
6583                 case 0 :
6584                         return; break;
6585                 case 1 :
6586                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6587                         break;
6588                 case 2 :
6589                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6590                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6591                         break;
6592                 case 3 :
6593                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6594                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6595                         break;
6596                 case 4 :
6597                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6598                         break;
6599                 case 5 :
6600                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6601                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6602                         break;
6603                 case 6 :
6604                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6605                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6606                         break;
6607                 case 7 :
6608                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6609                         break;
6610                 default:
6611                         // Rotating by 8 is a NOP.
6612                         break;
6613         }
6614
6615         if (andmask)
6616                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6617         else
6618                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
6619 }
6620
6621 /*-----------------------------------------------------------------*/
6622 /* shiftR1Left2Result - shift right one byte from left to result   */
6623 /*-----------------------------------------------------------------*/
6624 static void shiftR1Left2ResultSigned (operand *left, int offl,
6625                                 operand *result, int offr,
6626                                 int shCount)
6627 {
6628   int same;
6629
6630   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6631   assert ((shCount >= 0) && (shCount <= 8));
6632
6633   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6634
6635   /* Do NOT use result for intermediate results, it might be an SFR!. */
6636   switch (shCount) {
6637   case 0:
6638     if (!same) {
6639       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6640       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6641     }
6642     break;
6643
6644   case 1:
6645     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), offl));
6646     if (same)
6647       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6648     else {
6649       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left), offl));
6650       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6651     }
6652     break;
6653
6654   case 2:
6655     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6656     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6657     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); // keep sign bit in W<5>
6658     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 5));
6659     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xc0)); // sign-extend
6660     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6661     break;
6662
6663   case 3:
6664     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6665     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6666     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); // keep sign in W<4>
6667     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 4));
6668     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); // sign-extend
6669     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6670     break;
6671
6672   case 4:
6673     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6674     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); // keep sign in W<3>
6675     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 3));
6676     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); // sign-extend
6677     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6678     break;
6679
6680   case 5:
6681     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6682     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6683     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); // keep sign in W<2>
6684     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 2));
6685     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); // sign-extend
6686     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6687     break;
6688
6689   case 6:
6690     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6691     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6692     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); // keep sign bit in W<1>
6693     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 1));
6694     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xfc)); // sign-extend
6695     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6696     break;
6697
6698   case 7:
6699     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6700     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), offl), 7));
6701     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6702     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6703     break;
6704
6705   default:
6706     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6707     break;
6708   }
6709 }
6710
6711 /*-----------------------------------------------------------------*/
6712 /* shiftR1Left2Result - shift right one byte from left to result   */
6713 /*-----------------------------------------------------------------*/
6714 static void shiftR1Left2Result (operand *left, int offl,
6715                                 operand *result, int offr,
6716                                 int shCount, int sign)
6717 {
6718   int same;
6719
6720   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6721   assert ((shCount >= 0) && (shCount <= 8));
6722
6723   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6724
6725   /* Copy the msb into the carry if signed. */
6726   if (sign) {
6727     shiftR1Left2ResultSigned(left, offl, result, offr, shCount);
6728     return;
6729   }
6730
6731   /* Do NOT use result for intermediate results, it might be an SFR!. */
6732   switch (shCount) {
6733   case 0:
6734     if (!same) {
6735       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6736       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6737     }
6738     break;
6739
6740   case 1:
6741     if (same) {
6742       emitCLRC;
6743       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6744     } else {
6745       pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6746       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x7f));
6747       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6748     }
6749     break;
6750
6751   case 2:
6752     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6753     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6754     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f));
6755     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6756     break;
6757
6758   case 3:
6759     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6760     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6761     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6762     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6763     break;
6764
6765   case 4:
6766     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6767     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6768     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6769     break;
6770
6771   case 5:
6772     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6773     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6774     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
6775     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6776     break;
6777
6778   case 6:
6779     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6780     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6781     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03));
6782     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6783     break;
6784
6785   case 7:
6786     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6787     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x01));
6788     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6789     break;
6790
6791   default:
6792     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6793     break;
6794   }
6795 }
6796
6797 /*-----------------------------------------------------------------*/
6798 /* shiftL1Left2Result - shift left one byte from left to result    */
6799 /*-----------------------------------------------------------------*/
6800 static void shiftL1Left2Result (operand *left, int offl,
6801                                 operand *result, int offr, int shCount)
6802 {
6803   int same;
6804
6805   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6806   assert ((shCount >= 0) && (shCount <= 8));
6807
6808   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6809
6810   /* Do NOT use result for intermediate results, it might be an SFR!. */
6811   switch (shCount) {
6812   case 0:
6813     if (!same) {
6814       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6815       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6816     }
6817     break;
6818
6819   case 1:
6820     if (same) {
6821       emitCLRC;
6822       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left), offl));
6823     } else {
6824       pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6825       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
6826       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6827     }
6828     break;
6829
6830   case 2:
6831     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6832     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6833     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfc));
6834     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6835     break;
6836
6837   case 3:
6838     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6839     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6840     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf8));
6841     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6842     break;
6843
6844   case 4:
6845     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6846     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6847     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6848     break;
6849
6850   case 5:
6851     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6852     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6853     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0));
6854     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6855     break;
6856
6857   case 6:
6858     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6859     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6860     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0));
6861     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6862     break;
6863
6864   case 7:
6865     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6866     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6867     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6868     break;
6869
6870   default:
6871     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6872     break;
6873   }
6874 }
6875
6876 /*-----------------------------------------------------------------*/
6877 /* movLeft2Result - move byte from left to result                  */
6878 /*-----------------------------------------------------------------*/
6879 static void movLeft2Result (operand *left, int offl,
6880                             operand *result, int offr)
6881 {
6882   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6883   if (!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)) {
6884     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6885     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6886   }
6887 }
6888
6889 /*-----------------------------------------------------------------*/
6890 /* shiftL2Left2Result - shift left two bytes from left to result   */
6891 /*-----------------------------------------------------------------*/
6892 static void shiftL2Left2Result (operand *left, int offl,
6893                                 operand *result, int offr, int shCount)
6894 {
6895   int same = pic16_sameRegs(AOP(result), AOP(left));
6896   int i;
6897
6898   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6899
6900   if (same && (offl != offr)) { // shift bytes
6901     if (offr > offl) {
6902        for(i=1;i>-1;i--) {
6903          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6904          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6905        }
6906     } else { // just treat as different later on
6907                 same = 0;
6908     }
6909   }
6910
6911   if(same) {
6912     switch(shCount) {
6913     case 0:
6914       break;
6915     case 1:
6916     case 2:
6917     case 3:
6918
6919       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6920       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6921       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6922
6923       while(--shCount) {
6924                 emitCLRC;
6925                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6926                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6927       }
6928
6929       break;
6930     case 4:
6931     case 5:
6932       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6933       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6934       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6935       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6936       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6937       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6938       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6939       if(shCount >=5) {
6940                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6941                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6942       }
6943       break;
6944     case 6:
6945       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6946       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6947       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6948       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6949       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6950       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6951       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6952       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6953       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6954       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6955       break;
6956     case 7:
6957       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6958       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6959       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6960       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6961       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6962     }
6963
6964   } else {
6965     switch(shCount) {
6966     case 0:
6967       break;
6968     case 1:
6969     case 2:
6970     case 3:
6971       /* note, use a mov/add for the shift since the mov has a
6972          chance of getting optimized out */
6973       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6974       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6975       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6976       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
6977       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6978
6979       while(--shCount) {
6980                 emitCLRC;
6981                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6982                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6983       }
6984       break;
6985
6986     case 4:
6987     case 5:
6988       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6989       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6990       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6991       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6992       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6993       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
6994       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6995       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6996
6997
6998       if(shCount == 5) {
6999                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7000                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7001       }
7002       break;
7003     case 6:
7004       pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left),offl));
7005       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7006       pic16_emitpcode(POC_RRNCF,  pic16_popGet(AOP(result),offr));
7007       pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left),offl+MSB16));
7008       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr+MSB16));
7009       pic16_emitpcode(POC_RRNCF,  pic16_popGet(AOP(result),offr+MSB16));
7010       pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(0xc0));
7011       pic16_emitpcode(POC_ANDWF,  pic16_popGet(AOP(result),offr+MSB16));
7012       pic16_emitpcode(POC_ANDFW,  pic16_popGet(AOP(result),offr));
7013       pic16_emitpcode(POC_XORFW,  pic16_popGet(AOP(result),offr));
7014       pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(result),offr+MSB16));
7015       pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offr));
7016       break;
7017     case 7:
7018       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7019       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7020       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7021       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7022       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7023     }
7024   }
7025
7026 }
7027 /*-----------------------------------------------------------------*/
7028 /* shiftR2Left2Result - shift right two bytes from left to result  */
7029 /*-----------------------------------------------------------------*/
7030 static void shiftR2Left2Result (operand *left, int offl,
7031                                 operand *result, int offr,
7032                                 int shCount, int sign)
7033 {
7034   int same = pic16_sameRegs(AOP(result), AOP(left));
7035   int i;
7036   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7037
7038   if (same && (offl != offr)) { // shift right bytes
7039     if (offr < offl) {
7040        for(i=0;i<2;i++) {
7041          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7042          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7043        }
7044     } else { // just treat as different later on
7045                 same = 0;
7046     }
7047   }
7048
7049   switch(shCount) {
7050   case 0:
7051     break;
7052   case 1:
7053   case 2:
7054   case 3:
7055     /* obtain sign from left operand */
7056     if(sign)
7057       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
7058     else
7059       emitCLRC;
7060
7061     if(same) {
7062       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7063       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7064     } else {
7065       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7066       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7067       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7068       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7069     }
7070
7071     while(--shCount) {
7072       if(sign)
7073         /* now get sign from already assigned result (avoid BANKSEL) */
7074         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7075       else
7076         emitCLRC;
7077       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7078       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7079     }
7080     break;
7081   case 4:
7082   case 5:
7083     if(same) {
7084
7085       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7086       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7087       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7088
7089       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7090       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7091       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7092       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7093     } else {
7094       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7095       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7096       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7097
7098       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7099       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7100       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7101       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7102       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7103     }
7104
7105     if(shCount >=5) {
7106       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7107       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7108     }
7109
7110     if(sign) {
7111       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7112       pic16_emitpcode(POC_BTFSC,
7113                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7114       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7115     }
7116
7117     break;
7118
7119   case 6:
7120     if(same) {
7121
7122       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7123       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7124
7125       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7126       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7127       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7128       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7129       if(sign) {
7130         pic16_emitpcode(POC_BTFSC,
7131                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7132         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7133       }
7134       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7135       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7136       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7137       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7138     } else {
7139       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7140       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7141       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7142       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7143       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7144       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7145       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7146       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7147       if(sign) {
7148         pic16_emitpcode(POC_BTFSC,
7149                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7150         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7151       }
7152       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7153       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7154
7155
7156     }
7157
7158     break;
7159   case 7:
7160     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7161     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7162     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7163     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7164     if(sign) {
7165       emitSKPNC;
7166       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7167     } else
7168       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7169   }
7170 }
7171
7172
7173 /*-----------------------------------------------------------------*/
7174 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7175 /*-----------------------------------------------------------------*/
7176 static void shiftLLeftOrResult (operand *left, int offl,
7177                                 operand *result, int offr, int shCount)
7178 {
7179     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7180
7181     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7182     /* shift left accumulator */
7183     AccLsh(shCount, 1);
7184     /* or with result */
7185     /* back to result */
7186     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7187 }
7188
7189 /*-----------------------------------------------------------------*/
7190 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7191 /*-----------------------------------------------------------------*/
7192 static void shiftRLeftOrResult (operand *left, int offl,
7193                                 operand *result, int offr, int shCount)
7194 {
7195     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7196
7197     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7198     /* shift right accumulator */
7199     AccRsh(shCount, 1);
7200     /* or with result */
7201     /* back to result */
7202     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7203 }
7204
7205 /*-----------------------------------------------------------------*/
7206 /* genlshOne - left shift a one byte quantity by known count       */
7207 /*-----------------------------------------------------------------*/
7208 static void genlshOne (operand *result, operand *left, int shCount)
7209 {
7210     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7211     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7212 }
7213
7214 /*-----------------------------------------------------------------*/
7215 /* genlshTwo - left shift two bytes by known amount != 0           */
7216 /*-----------------------------------------------------------------*/
7217 static void genlshTwo (operand *result,operand *left, int shCount)
7218 {
7219     int size;
7220
7221     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7222     size = pic16_getDataSize(result);
7223
7224     /* if shCount >= 8 */
7225     if (shCount >= 8) {
7226         shCount -= 8 ;
7227
7228         if (size > 1){
7229             if (shCount)
7230                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7231             else
7232                 movLeft2Result(left, LSB, result, MSB16);
7233         }
7234         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7235     }
7236
7237     /*  1 <= shCount <= 7 */
7238     else {
7239         if(size == 1)
7240             shiftL1Left2Result(left, LSB, result, LSB, shCount);
7241         else
7242             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7243     }
7244 }
7245
7246 /*-----------------------------------------------------------------*/
7247 /* shiftLLong - shift left one long from left to result            */
7248 /* offr = LSB or MSB16                                             */
7249 /*-----------------------------------------------------------------*/
7250 static void shiftLLong (operand *left, operand *result, int offr )
7251 {
7252     int size = AOP_SIZE(result);
7253     int same = pic16_sameRegs(AOP(left),AOP(result));
7254         int i;
7255
7256     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7257
7258         if (same && (offr == MSB16)) { //shift one byte
7259                 for(i=size-1;i>=MSB16;i--) {
7260                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7261                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7262                 }
7263         } else {
7264                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB));
7265         }
7266
7267     if (size > LSB+offr ){
7268                 if (same) {
7269                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7270                 } else {
7271                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7272                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7273                 }
7274          }
7275
7276     if(size > MSB16+offr){
7277                 if (same) {
7278                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7279                 } else {
7280                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7281                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7282                 }
7283     }
7284
7285     if(size > MSB24+offr){
7286                 if (same) {
7287                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7288                 } else {
7289                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7290                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7291                 }
7292     }
7293
7294     if(size > MSB32+offr){
7295                 if (same) {
7296                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7297                 } else {
7298                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7299                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7300                 }
7301     }
7302     if(offr != LSB)
7303                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7304
7305 }
7306
7307 /*-----------------------------------------------------------------*/
7308 /* genlshFour - shift four byte by a known amount != 0             */
7309 /*-----------------------------------------------------------------*/
7310 static void genlshFour (operand *result, operand *left, int shCount)
7311 {
7312     int size;
7313
7314     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7315     size = AOP_SIZE(result);
7316
7317     /* if shifting more that 3 bytes */
7318     if (shCount >= 24 ) {
7319         shCount -= 24;
7320         if (shCount)
7321             /* lowest order of left goes to the highest
7322             order of the destination */
7323             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7324         else
7325             movLeft2Result(left, LSB, result, MSB32);
7326
7327                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7328                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7329                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7330
7331         return;
7332     }
7333
7334     /* more than two bytes */
7335     else if ( shCount >= 16 ) {
7336         /* lower order two bytes goes to higher order two bytes */
7337         shCount -= 16;
7338         /* if some more remaining */
7339         if (shCount)
7340             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7341         else {
7342             movLeft2Result(left, MSB16, result, MSB32);
7343             movLeft2Result(left, LSB, result, MSB24);
7344         }
7345                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7346                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7347         return;
7348     }
7349
7350     /* if more than 1 byte */
7351     else if ( shCount >= 8 ) {
7352         /* lower order three bytes goes to higher order  three bytes */
7353         shCount -= 8;
7354         if(size == 2){
7355             if(shCount)
7356                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7357             else
7358                 movLeft2Result(left, LSB, result, MSB16);
7359         }
7360         else{   /* size = 4 */
7361             if(shCount == 0){
7362                 movLeft2Result(left, MSB24, result, MSB32);
7363                 movLeft2Result(left, MSB16, result, MSB24);
7364                 movLeft2Result(left, LSB, result, MSB16);
7365                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7366             }
7367             else if(shCount == 1)
7368                 shiftLLong(left, result, MSB16);
7369             else{
7370                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7371                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7372                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7373                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7374             }
7375         }
7376     }
7377
7378     /* 1 <= shCount <= 7 */
7379     else if(shCount <= 3)
7380     {
7381         shiftLLong(left, result, LSB);
7382         while(--shCount >= 1)
7383             shiftLLong(result, result, LSB);
7384     }
7385     /* 3 <= shCount <= 7, optimize */
7386     else{
7387         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7388         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7389         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7390     }
7391 }
7392
7393 /*-----------------------------------------------------------------*/
7394 /* genLeftShiftLiteral - left shifting by known count              */
7395 /*-----------------------------------------------------------------*/
7396 void pic16_genLeftShiftLiteral (operand *left,
7397                                  operand *right,
7398                                  operand *result,
7399                                  iCode *ic)
7400 {
7401     int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7402     int size;
7403
7404     FENTRY;
7405     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
7406     pic16_freeAsmop(right,NULL,ic,TRUE);
7407
7408     pic16_aopOp(left,ic,FALSE);
7409     pic16_aopOp(result,ic,TRUE);
7410
7411     size = getSize(operandType(result));
7412
7413 #if VIEW_SIZE
7414     pic16_emitcode("; shift left ","result %d, left %d",size,
7415              AOP_SIZE(left));
7416 #endif
7417
7418     /* I suppose that the left size >= result size */
7419     if(shCount == 0){
7420         while(size--){
7421             movLeft2Result(left, size, result, size);
7422         }
7423     }
7424
7425     else if(shCount >= (size * 8))
7426         while(size--)
7427             pic16_aopPut(AOP(result),zero,size);
7428     else{
7429         switch (size) {
7430             case 1:
7431                 genlshOne (result,left,shCount);
7432                 break;
7433
7434             case 2:
7435             case 3:
7436                 genlshTwo (result,left,shCount);
7437                 break;
7438
7439             case 4:
7440                 genlshFour (result,left,shCount);
7441                 break;
7442         }
7443     }
7444     pic16_freeAsmop(left,NULL,ic,TRUE);
7445     pic16_freeAsmop(result,NULL,ic,TRUE);
7446 }
7447
7448 /*-----------------------------------------------------------------*
7449  * genMultiAsm - repeat assembly instruction for size of register.
7450  * if endian == 1, then the high byte (i.e base address + size of
7451  * register) is used first else the low byte is used first;
7452  *-----------------------------------------------------------------*/
7453 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7454 {
7455
7456   int offset = 0;
7457
7458   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7459
7460   if(!reg)
7461     return;
7462
7463   if(!endian) {
7464     endian = 1;
7465   } else {
7466     endian = -1;
7467     offset = size-1;
7468   }
7469
7470   while(size--) {
7471     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7472     offset += endian;
7473   }
7474
7475 }
7476
7477 /*-----------------------------------------------------------------*/
7478 /* genrshOne - right shift a one byte quantity by known count      */
7479 /*-----------------------------------------------------------------*/
7480 static void genrshOne (operand *result, operand *left,
7481                        int shCount, int sign)
7482 {
7483     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7484     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7485 }
7486
7487 /*-----------------------------------------------------------------*/
7488 /* genrshTwo - right shift two bytes by known amount != 0          */
7489 /*-----------------------------------------------------------------*/
7490 static void genrshTwo (operand *result,operand *left,
7491                        int shCount, int sign)
7492 {
7493   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7494   /* if shCount >= 8 */
7495   if (shCount >= 8) {
7496     shCount -= 8 ;
7497     if (shCount)
7498       shiftR1Left2Result(left, MSB16, result, LSB,
7499                          shCount, sign);
7500     else
7501       movLeft2Result(left, MSB16, result, LSB);
7502
7503     pic16_addSign (result, 1, sign);
7504   }
7505
7506   /*  1 <= shCount <= 7 */
7507   else
7508     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7509 }
7510
7511 /*-----------------------------------------------------------------*/
7512 /* shiftRLong - shift right one long from left to result           */
7513 /* offl = LSB or MSB16                                             */
7514 /*-----------------------------------------------------------------*/
7515 static void shiftRLong (operand *left, int offl,
7516                         operand *result, int sign)
7517 {
7518     int size = AOP_SIZE(result);
7519     int same = pic16_sameRegs(AOP(left),AOP(result));
7520     int i;
7521     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7522
7523         if (same && (offl == MSB16)) { //shift one byte right
7524                 for(i=MSB16;i<size;i++) {
7525                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7526                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7527                 }
7528         }
7529
7530     if(sign)
7531                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7532         else
7533                 emitCLRC;
7534
7535         if (same) {
7536                 if (offl == LSB)
7537                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7538         } else {
7539         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7540         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7541         }
7542
7543     if(offl == MSB16) {
7544         /* add sign of "a" */
7545         pic16_addSign(result, MSB32, sign);
7546         }
7547
7548         if (same) {
7549         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7550         } else {
7551         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7552         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7553         }
7554
7555         if (same) {
7556         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7557         } else {
7558         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7559         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7560         }
7561
7562         if (same) {
7563         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7564         } else {
7565         if(offl == LSB){
7566                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7567                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7568         }
7569         }
7570 }
7571
7572 /*-----------------------------------------------------------------*/
7573 /* genrshFour - shift four byte by a known amount != 0             */
7574 /*-----------------------------------------------------------------*/
7575 static void genrshFour (operand *result, operand *left,
7576                         int shCount, int sign)
7577 {
7578   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7579   /* if shifting more that 3 bytes */
7580   if(shCount >= 24 ) {
7581     shCount -= 24;
7582     if(shCount)
7583       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7584     else
7585       movLeft2Result(left, MSB32, result, LSB);
7586
7587     pic16_addSign(result, MSB16, sign);
7588   }
7589   else if(shCount >= 16){
7590     shCount -= 16;
7591     if(shCount)
7592       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7593     else{
7594       movLeft2Result(left, MSB24, result, LSB);
7595       movLeft2Result(left, MSB32, result, MSB16);
7596     }
7597     pic16_addSign(result, MSB24, sign);
7598   }
7599   else if(shCount >= 8){
7600     shCount -= 8;
7601     if(shCount == 1)
7602       shiftRLong(left, MSB16, result, sign);
7603     else if(shCount == 0){
7604       movLeft2Result(left, MSB16, result, LSB);
7605       movLeft2Result(left, MSB24, result, MSB16);
7606       movLeft2Result(left, MSB32, result, MSB24);
7607       pic16_addSign(result, MSB32, sign);
7608     }
7609     else{ //shcount >= 2
7610       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7611       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7612       /* the last shift is signed */
7613       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7614       pic16_addSign(result, MSB32, sign);
7615     }
7616   }
7617   else{   /* 1 <= shCount <= 7 */
7618     if(shCount <= 2){
7619       shiftRLong(left, LSB, result, sign);
7620       if(shCount == 2)
7621         shiftRLong(result, LSB, result, sign);
7622     }
7623     else{
7624       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7625       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7626       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7627     }
7628   }
7629 }
7630
7631 /*-----------------------------------------------------------------*/
7632 /* genRightShiftLiteral - right shifting by known count            */
7633 /*-----------------------------------------------------------------*/
7634 static void genRightShiftLiteral (operand *left,
7635                                   operand *right,
7636                                   operand *result,
7637                                   iCode *ic,
7638                                   int sign)
7639 {
7640   int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7641   int lsize,res_size;
7642
7643   pic16_freeAsmop(right,NULL,ic,TRUE);
7644
7645   pic16_aopOp(left,ic,FALSE);
7646   pic16_aopOp(result,ic,TRUE);
7647
7648   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7649
7650 #if VIEW_SIZE
7651   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7652                  AOP_SIZE(left));
7653 #endif
7654
7655   lsize = pic16_getDataSize(left);
7656   res_size = pic16_getDataSize(result);
7657   /* test the LEFT size !!! */
7658
7659   /* I suppose that the left size >= result size */
7660   if (shCount == 0) {
7661     assert (res_size <= lsize);
7662     while (res_size--) {
7663       pic16_mov2f (AOP(result), AOP(left), res_size);
7664     } // for
7665   } else if (shCount >= (lsize * 8)) {
7666     if (sign) {
7667       /* 
7668        * Do NOT use
7669        *    CLRF    result
7670        *    BTFSC   left, 7
7671        *    SETF    result
7672        * even for 8-bit operands; result might be an SFR.
7673        */
7674       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7675       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), lsize-1), 7));
7676       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7677       while (res_size--) {
7678         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), res_size));
7679       }
7680     } else { // unsigned
7681       while (res_size--) {
7682         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), res_size));
7683       }
7684     }
7685   } else { // 0 < shCount < 8*lsize
7686     switch (res_size) {
7687     case 1:
7688       genrshOne (result,left,shCount,sign);
7689       break;
7690
7691     case 2:
7692       genrshTwo (result,left,shCount,sign);
7693       break;
7694
7695     case 4:
7696       genrshFour (result,left,shCount,sign);
7697       break;
7698     default :
7699       break;
7700     }
7701   }
7702
7703   pic16_freeAsmop(left,NULL,ic,TRUE);
7704   pic16_freeAsmop(result,NULL,ic,TRUE);
7705 }
7706
7707 /*-----------------------------------------------------------------*/
7708 /* genGenericShift - generates code for left or right shifting     */
7709 /*-----------------------------------------------------------------*/
7710 static void genGenericShift (iCode *ic, int isShiftLeft)
7711 {
7712   operand *left,*right, *result;
7713   int offset;
7714   int sign, signedCount;
7715   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
7716   PIC_OPCODE pos_shift, neg_shift;
7717
7718   FENTRY;
7719
7720   right = IC_RIGHT(ic);
7721   left  = IC_LEFT(ic);
7722   result = IC_RESULT(ic);
7723
7724   pic16_aopOp(right,ic,FALSE);
7725   pic16_aopOp(left,ic,FALSE);
7726   pic16_aopOp(result,ic,TRUE);
7727
7728   sign = !SPEC_USIGN(operandType (left));
7729   signedCount = !SPEC_USIGN(operandType (right));
7730
7731   /* if the shift count is known then do it
7732      as efficiently as possible */
7733   if (AOP_TYPE(right) == AOP_LIT) {
7734     long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
7735     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
7736     // we should modify right->aopu.aop_lit here!
7737     // Instead we use abs(shCount) in genXXXShiftLiteral()...
7738     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
7739     if (isShiftLeft)
7740       pic16_genLeftShiftLiteral (left,right,result,ic);
7741     else
7742       genRightShiftLiteral (left,right,result,ic, sign);
7743
7744     goto release;
7745   } // if (right is literal)
7746
7747   /* shift count is unknown then we have to form a loop.
7748    * Note: we take only the lower order byte since shifting
7749    * more than 32 bits make no sense anyway, ( the
7750    * largest size of an object can be only 32 bits )
7751    * Note: we perform arithmetic shifts if the left operand is
7752    * signed and we do an (effective) right shift, i. e. we
7753    * shift in the sign bit from the left. */
7754
7755   label_complete = newiTempLabel ( NULL );
7756   label_loop_pos = newiTempLabel ( NULL );
7757   label_loop_neg = NULL;
7758   label_negative = NULL;
7759   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
7760   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
7761
7762   if (signedCount) {
7763     // additional labels needed
7764     label_loop_neg = newiTempLabel ( NULL );
7765     label_negative = newiTempLabel ( NULL );
7766   } // if
7767
7768   // copy source to result -- this will effectively truncate the left operand to the size of result!
7769   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
7770   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
7771   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
7772     pic16_mov2f (AOP(result),AOP(left), offset);
7773   } // for
7774
7775   // if result is longer than left, fill with zeros (or sign)
7776   if (AOP_SIZE(left) < AOP_SIZE(result)) {
7777     if (sign && AOP_SIZE(left) > 0) {
7778       // shift signed operand -- fill with sign
7779       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
7780       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
7781       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
7782       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7783         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
7784       } // for
7785     } else {
7786       // shift unsigned operand -- fill result with zeros
7787       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7788         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
7789       } // for
7790     }
7791   } // if (size mismatch)
7792
7793   pic16_mov2w (AOP(right), 0);
7794   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
7795   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
7796
7797 #if 0
7798   // perform a shift by one (shift count is positive)
7799   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7800   // 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])
7801   pic16_emitpLabel (label_loop_pos->key);
7802   emitCLRC;
7803   if (sign && (pos_shift == POC_RRCF)) {
7804     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7805     emitSETC;
7806   } // if
7807   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7808   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
7809   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
7810 #else
7811   // perform a shift by one (shift count is positive)
7812   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7813   // 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])
7814   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
7815   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
7816   emitCLRC;
7817   pic16_emitpLabel (label_loop_pos->key);
7818   if (sign && (pos_shift == POC_RRCF)) {
7819     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7820     emitSETC;
7821   } // if
7822   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7823   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7824   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7825   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
7826 #endif
7827
7828   if (signedCount) {
7829     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
7830
7831     pic16_emitpLabel (label_negative->key);
7832     // perform a shift by -1 (shift count is negative)
7833     // 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)
7834     emitCLRC;
7835     pic16_emitpLabel (label_loop_neg->key);
7836     if (sign && (neg_shift == POC_RRCF)) {
7837       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7838       emitSETC;
7839     } // if
7840     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
7841     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7842     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7843     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
7844   } // if (signedCount)
7845
7846   pic16_emitpLabel (label_complete->key);
7847
7848 release:
7849   pic16_freeAsmop (right,NULL,ic,TRUE);
7850   pic16_freeAsmop(left,NULL,ic,TRUE);
7851   pic16_freeAsmop(result,NULL,ic,TRUE);
7852 }
7853
7854 static void genLeftShift (iCode *ic) {
7855   genGenericShift (ic, 1);
7856 }
7857
7858 static void genRightShift (iCode *ic) {
7859   genGenericShift (ic, 0);
7860 }
7861
7862
7863 /* load FSR0 with address of/from op according to pic16_isLitOp() or if lit is 1 */
7864 void pic16_loadFSR0(operand *op, int lit)
7865 {
7866   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || pic16_isLitOp( op )) {
7867     if (AOP_TYPE(op) == AOP_LIT) {
7868       /* handle 12 bit integers correctly */
7869       unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
7870       if ((val & 0x0fff) != val) {
7871         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
7872                 val, (val & 0x0fff) );
7873         val &= 0x0fff;
7874       }
7875       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
7876     } else {
7877       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
7878     }
7879   } else {
7880     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
7881     // set up FSR0 with address of result
7882     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
7883     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
7884   }
7885 }
7886
7887 /*----------------------------------------------------------------*/
7888 /* pic16_derefPtr - move one byte from the location ptr points to */
7889 /*                  to WREG (doWrite == 0) or one byte from WREG   */
7890 /*                  to the location ptr points to (doWrite != 0)   */
7891 /*----------------------------------------------------------------*/
7892 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
7893 {
7894   if (!IS_PTR(operandType(ptr)))
7895   {
7896     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
7897     else pic16_mov2w (AOP(ptr), 0);
7898     return;
7899   }
7900
7901   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
7902   /* We might determine pointer type right here: */
7903   p_type = DCL_TYPE(operandType(ptr));
7904
7905   switch (p_type) {
7906     case FPOINTER:
7907     case POINTER:
7908       if (!fsr0_setup || !*fsr0_setup)
7909       {
7910         pic16_loadFSR0( ptr, 0 );
7911         if (fsr0_setup) *fsr0_setup = 1;
7912       }
7913       if (doWrite)
7914         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7915       else
7916         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7917       break;
7918
7919     case GPOINTER:
7920       if (AOP(ptr)->aopu.aop_reg[2]) {
7921         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
7922         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
7923         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
7924         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
7925         pic16_mov2w(AOP(ptr), 2);
7926         pic16_callGenericPointerRW(doWrite, 1);
7927       } else {
7928         // data pointer (just 2 byte given)
7929         if (!fsr0_setup || !*fsr0_setup)
7930         {
7931           pic16_loadFSR0( ptr, 0 );
7932           if (fsr0_setup) *fsr0_setup = 1;
7933         }
7934         if (doWrite)
7935           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7936         else
7937           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7938       }
7939       break;
7940
7941     default:
7942       assert (0 && "invalid pointer type specified");
7943       break;
7944   }
7945 }
7946
7947 /*-----------------------------------------------------------------*/
7948 /* genUnpackBits - generates code for unpacking bits               */
7949 /*-----------------------------------------------------------------*/
7950 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
7951 {
7952   int shCnt ;
7953   sym_link *etype, *letype;
7954   int blen=0, bstr=0;
7955   int lbstr;
7956   int same;
7957   pCodeOp *op;
7958
7959   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7960   etype = getSpec(operandType(result));
7961   letype = getSpec(operandType(left));
7962
7963   //    if(IS_BITFIELD(etype)) {
7964   blen = SPEC_BLEN(etype);
7965   bstr = SPEC_BSTR(etype);
7966   //    }
7967
7968   lbstr = SPEC_BSTR( letype );
7969
7970   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
7971       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
7972
7973 #if 1
7974   if((blen == 1) && (bstr < 8)
7975       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
7976     /* it is a single bit, so use the appropriate bit instructions */
7977     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
7978
7979     same = pic16_sameRegs(AOP(left),AOP(result));
7980     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
7981     pic16_emitpcode(POC_CLRF, op);
7982
7983     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
7984       /* workaround to reduce the extra lfsr instruction */
7985       pic16_emitpcode(POC_BTFSC,
7986           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
7987     } else {
7988       assert (PIC_IS_DATA_PTR (operandType(left)));
7989       pic16_loadFSR0 (left, 0);
7990       pic16_emitpcode(POC_BTFSC,
7991           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
7992     }
7993
7994     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
7995       /* unsigned bitfields result in either 0 or 1 */
7996       pic16_emitpcode(POC_INCF, op);
7997     } else {
7998       /* signed bitfields result in either 0 or -1 */
7999       pic16_emitpcode(POC_DECF, op);
8000     }
8001     if (same) {
8002       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
8003     }
8004
8005     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8006     return;
8007   }
8008
8009 #endif
8010
8011   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8012     // access symbol directly
8013     pic16_mov2w (AOP(left), 0);
8014   } else {
8015     pic16_derefPtr (left, ptype, 0, NULL);
8016   }
8017
8018   /* if we have bitdisplacement then it fits   */
8019   /* into this byte completely or if length is */
8020   /* less than a byte                          */
8021   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
8022
8023     /* shift right acc */
8024     AccRsh(shCnt, 0);
8025
8026     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8027           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8028
8029     /* VR -- normally I would use the following, but since we use the hack,
8030      * to avoid the masking from AccRsh, why not mask it right now? */
8031
8032     /*
8033        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8034      */
8035
8036     /* extend signed bitfields to 8 bits */
8037     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
8038     {
8039       assert (blen + bstr > 0);
8040       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
8041       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
8042     }
8043
8044     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8045
8046     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8047     return ;
8048   }
8049
8050   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
8051   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8052   exit(EXIT_FAILURE);
8053
8054   return ;
8055 }
8056
8057
8058 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
8059 {
8060   int size, offset = 0, leoffset=0 ;
8061
8062         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8063         pic16_aopOp(result, ic, TRUE);
8064
8065         FENTRY;
8066
8067         size = AOP_SIZE(result);
8068 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8069
8070
8071 #if 1
8072         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
8073                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
8074                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
8075                 goto release;
8076         }
8077 #endif
8078
8079         if(AOP(left)->aopu.pcop->type == PO_DIR)
8080                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8081
8082         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8083
8084         while (size--) {
8085                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8086
8087 //              pic16_DumpOp("(result)",result);
8088                 if(pic16_isLitAop(AOP(result))) {
8089                         pic16_mov2w(AOP(left), offset); // patch 8
8090                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8091                 } else {
8092                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8093                                 pic16_popGet(AOP(left), offset), //patch 8
8094                                 pic16_popGet(AOP(result), offset)));
8095                 }
8096
8097                 offset++;
8098                 leoffset++;
8099         }
8100
8101 release:
8102     pic16_freeAsmop(result,NULL,ic,TRUE);
8103 }
8104
8105
8106
8107 /*-----------------------------------------------------------------*/
8108 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8109 /*-----------------------------------------------------------------*/
8110 static void genNearPointerGet (operand *left,
8111                                operand *result,
8112                                iCode *ic)
8113 {
8114 //  asmop *aop = NULL;
8115   //regs *preg = NULL ;
8116   sym_link *rtype, *retype;
8117   sym_link *ltype, *letype;
8118
8119     FENTRY;
8120
8121     rtype = operandType(result);
8122     retype= getSpec(rtype);
8123     ltype = operandType(left);
8124     letype= getSpec(ltype);
8125
8126     pic16_aopOp(left,ic,FALSE);
8127
8128 //    pic16_DumpOp("(left)",left);
8129 //    pic16_DumpOp("(result)",result);
8130
8131     /* if left is rematerialisable and
8132      * result is not bit variable type and
8133      * the left is pointer to data space i.e
8134      * lower 128 bytes of space */
8135
8136     if (AOP_TYPE(left) == AOP_PCODE
8137       && !IS_BITFIELD(retype)
8138       && DCL_TYPE(ltype) == POINTER) {
8139
8140         genDataPointerGet (left,result,ic);
8141         pic16_freeAsmop(left, NULL, ic, TRUE);
8142         return ;
8143     }
8144
8145     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8146     pic16_aopOp (result,ic,TRUE);
8147
8148     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
8149
8150 #if 1
8151     if(IS_BITFIELD( retype )
8152       && (SPEC_BLEN(operandType(result))==1)
8153     ) {
8154       iCode *nextic;
8155       pCodeOp *jop;
8156       int bitstrt, bytestrt;
8157
8158         /* if this is bitfield of size 1, see if we are checking the value
8159          * of a single bit in an if-statement,
8160          * if yes, then don't generate usual code, but execute the
8161          * genIfx directly -- VR */
8162
8163         nextic = ic->next;
8164
8165         /* CHECK: if next iCode is IFX
8166          * and current result operand is nextic's conditional operand
8167          * and current result operand live ranges ends at nextic's key number
8168          */
8169         if((nextic->op == IFX)
8170           && (result == IC_COND(nextic))
8171           && (OP_LIVETO(result) == nextic->seq)
8172           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
8173           ) {
8174             /* everything is ok then */
8175             /* find a way to optimize the genIfx iCode */
8176
8177             bytestrt = SPEC_BSTR(operandType(result))/8;
8178             bitstrt = SPEC_BSTR(operandType(result))%8;
8179
8180             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
8181
8182             genIfxpCOpJump(nextic, jop);
8183
8184             pic16_freeAsmop(left, NULL, ic, TRUE);
8185             pic16_freeAsmop(result, NULL, ic, TRUE);
8186             return;
8187         }
8188     }
8189 #endif
8190
8191     /* if bitfield then unpack the bits */
8192     if (IS_BITFIELD(letype))
8193       genUnpackBits (result, left, NULL, POINTER);
8194     else {
8195       /* we have can just get the values */
8196       int size = AOP_SIZE(result);
8197       int offset = 0;
8198
8199       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8200
8201       pic16_loadFSR0( left, 0 );
8202
8203       while(size--) {
8204         if(size) {
8205           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8206                 pic16_popGet(AOP(result), offset++)));
8207         } else {
8208           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8209                 pic16_popGet(AOP(result), offset++)));
8210         }
8211       }
8212     }
8213
8214 #if 0
8215     /* now some housekeeping stuff */
8216     if (aop) {
8217       /* we had to allocate for this iCode */
8218       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8219       pic16_freeAsmop(NULL,aop,ic,TRUE);
8220     } else {
8221       /* we did not allocate which means left
8222        * already in a pointer register, then
8223        * if size > 0 && this could be used again
8224        * we have to point it back to where it
8225        * belongs */
8226       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8227       if (AOP_SIZE(result) > 1
8228         && !OP_SYMBOL(left)->remat
8229         && ( OP_SYMBOL(left)->liveTo > ic->seq
8230             || ic->depth )) {
8231 //        int size = AOP_SIZE(result) - 1;
8232 //        while (size--)
8233 //          pic16_emitcode("dec","%s",rname);
8234         }
8235     }
8236 #endif
8237
8238     /* done */
8239     pic16_freeAsmop(left,NULL,ic,TRUE);
8240     pic16_freeAsmop(result,NULL,ic,TRUE);
8241 }
8242
8243 /*-----------------------------------------------------------------*/
8244 /* genGenPointerGet - gget value from generic pointer space        */
8245 /*-----------------------------------------------------------------*/
8246 static void genGenPointerGet (operand *left,
8247                               operand *result, iCode *ic)
8248 {
8249   int size;
8250   sym_link *letype = getSpec(operandType(left));
8251
8252   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8253   pic16_aopOp(left,ic,FALSE);
8254   pic16_aopOp(result,ic,TRUE);
8255   size = AOP_SIZE(result);
8256
8257   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8258
8259   /* if bit then unpack */
8260   if (IS_BITFIELD(letype)) {
8261     genUnpackBits(result,left,"BAD",GPOINTER);
8262     goto release;
8263   }
8264
8265   /* set up WREG:PRODL:FSR0L with address from left */
8266   mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
8267   mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
8268   pic16_mov2w(AOP(left), 2);
8269   pic16_callGenericPointerRW(0, size);
8270
8271   assignResultValue(result, size, 1);
8272
8273 release:
8274   pic16_freeAsmop(left,NULL,ic,TRUE);
8275   pic16_freeAsmop(result,NULL,ic,TRUE);
8276 }
8277
8278 /*-----------------------------------------------------------------*/
8279 /* genConstPointerGet - get value from const generic pointer space */
8280 /*-----------------------------------------------------------------*/
8281 static void genConstPointerGet (operand *left,
8282                                 operand *result, iCode *ic)
8283 {
8284   //sym_link *retype = getSpec(operandType(result));
8285   // symbol *albl = newiTempLabel(NULL);        // patch 15
8286   // symbol *blbl = newiTempLabel(NULL);        //
8287   // PIC_OPCODE poc;                            // patch 15
8288   int size;
8289   int offset = 0;
8290
8291   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8292   pic16_aopOp(left,ic,FALSE);
8293   pic16_aopOp(result,ic,TRUE);
8294   size = AOP_SIZE(result);
8295
8296   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8297
8298   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8299
8300   // set up table pointer
8301   if( (AOP_TYPE(left) == AOP_PCODE)
8302       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8303           || (AOP(left)->aopu.pcop->type == PO_DIR)))
8304     {
8305       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
8306       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
8307       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
8308       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
8309       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
8310       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
8311   } else {
8312     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
8313     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
8314     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
8315   }
8316
8317   while(size--) {
8318     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
8319     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
8320     offset++;
8321   }
8322
8323   pic16_freeAsmop(left,NULL,ic,TRUE);
8324   pic16_freeAsmop(result,NULL,ic,TRUE);
8325 }
8326
8327
8328 /*-----------------------------------------------------------------*/
8329 /* genPointerGet - generate code for pointer get                   */
8330 /*-----------------------------------------------------------------*/
8331 static void genPointerGet (iCode *ic)
8332 {
8333   operand *left, *result ;
8334   sym_link *type, *etype;
8335   int p_type;
8336
8337     FENTRY;
8338
8339     left = IC_LEFT(ic);
8340     result = IC_RESULT(ic) ;
8341
8342     /* depending on the type of pointer we need to
8343     move it to the correct pointer register */
8344     type = operandType(left);
8345     etype = getSpec(type);
8346
8347 #if 0
8348     if (IS_PTR_CONST(type))
8349 #else
8350     if (IS_CODEPTR(type))
8351 #endif
8352       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8353
8354     /* if left is of type of pointer then it is simple */
8355     if (IS_PTR(type) && !IS_FUNC(type->next))
8356       p_type = DCL_TYPE(type);
8357     else {
8358       /* we have to go by the storage class */
8359       p_type = PTR_TYPE(SPEC_OCLS(etype));
8360
8361       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8362
8363       if (SPEC_OCLS(etype)->codesp ) {
8364         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8365         //p_type = CPOINTER ;
8366       } else
8367       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
8368         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8369         /*p_type = FPOINTER ;*/
8370       } else
8371       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
8372         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8373         /* p_type = PPOINTER; */
8374       } else
8375       if (SPEC_OCLS(etype) == idata ) {
8376         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8377         /* p_type = IPOINTER; */
8378       } else {
8379         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8380         /* p_type = POINTER ; */
8381       }
8382     }
8383
8384     /* now that we have the pointer type we assign
8385     the pointer values */
8386     switch (p_type) {
8387       case POINTER:
8388       case FPOINTER:
8389       case IPOINTER:
8390         genNearPointerGet (left,result,ic);
8391         break;
8392
8393 #if 0
8394       /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8395       case PPOINTER:
8396         genPagedPointerGet(left,result,ic);
8397         break;
8398
8399       case FPOINTER:
8400         genFarPointerGet (left,result,ic);
8401         break;
8402 #endif
8403
8404       case CPOINTER:
8405         genConstPointerGet (left,result,ic);
8406         //pic16_emitcodePointerGet (left,result,ic);
8407         break;
8408
8409       case GPOINTER:
8410 #if 0
8411       if (IS_PTR_CONST(type))
8412         genConstPointerGet (left,result,ic);
8413       else
8414 #endif
8415         genGenPointerGet (left,result,ic);
8416       break;
8417
8418     default:
8419       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8420               "genPointerGet: illegal pointer type");
8421
8422     }
8423 }
8424
8425 /*-----------------------------------------------------------------*/
8426 /* genPackBits - generates code for packed bit storage             */
8427 /*-----------------------------------------------------------------*/
8428 static void genPackBits (sym_link    *etype , operand *result,
8429                          operand *right ,
8430                          char *rname, int p_type)
8431 {
8432   int shCnt = 0 ;
8433   int offset = 0  ;
8434   int rLen = 0 ;
8435   int blen, bstr ;
8436   int shifted_and_masked = 0;
8437   unsigned long lit = (unsigned long)-1;
8438   sym_link *retype;
8439
8440   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8441   blen = SPEC_BLEN(etype);
8442   bstr = SPEC_BSTR(etype);
8443
8444   retype = getSpec(operandType(right));
8445
8446   if(AOP_TYPE(right) == AOP_LIT) {
8447     lit = ulFromVal (AOP(right)->aopu.aop_lit);
8448
8449     if((blen == 1) && (bstr < 8)) {
8450       /* it is a single bit, so use the appropriate bit instructions */
8451
8452       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
8453
8454       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
8455         /* workaround to reduce the extra lfsr instruction */
8456         if(lit) {
8457           pic16_emitpcode(POC_BSF,
8458               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8459         } else {
8460           pic16_emitpcode(POC_BCF,
8461               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8462         }
8463       } else {
8464         if (PIC_IS_DATA_PTR(operandType(result))) {
8465           pic16_loadFSR0(result, 0);
8466           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8467               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8468         } else {
8469           /* get old value */
8470           pic16_derefPtr (result, p_type, 0, NULL);
8471           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8472               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8473           /* write back new value */
8474           pic16_derefPtr (result, p_type, 1, NULL);
8475         }
8476       }
8477
8478       return;
8479     }
8480     /* IORLW below is more efficient */
8481     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
8482     lit = (lit & ((1UL << blen) - 1)) << bstr;
8483     shifted_and_masked = 1;
8484     offset++;
8485   } else
8486     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
8487         && IS_BITFIELD(retype)
8488         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
8489         && (blen == 1)) {
8490       int rblen, rbstr;
8491
8492       rblen = SPEC_BLEN( retype );
8493       rbstr = SPEC_BSTR( retype );
8494
8495       if(IS_BITFIELD(etype)) {
8496         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
8497         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8498       } else {
8499         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
8500       }
8501
8502       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
8503
8504       if(IS_BITFIELD(etype)) {
8505         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8506       } else {
8507         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
8508       }
8509
8510       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
8511
8512       return;
8513     } else {
8514       /* move right to W */
8515       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
8516     }
8517
8518   /* if the bit length is less than or   */
8519   /* it exactly fits a byte then         */
8520   if((shCnt=SPEC_BSTR(etype))
8521       || SPEC_BLEN(etype) <= 8 )  {
8522     int fsr0_setup = 0;
8523
8524     if (blen != 8 || (bstr % 8) != 0) {
8525       // we need to combine the value with the old value
8526       if(!shifted_and_masked)
8527       {
8528         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
8529
8530         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
8531             SPEC_BSTR(etype), SPEC_BLEN(etype));
8532
8533         /* shift left acc, do NOT mask the result again */
8534         AccLsh(shCnt, 0);
8535
8536         /* using PRODH as a temporary register here */
8537         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
8538       }
8539
8540       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
8541         || IS_DIRECT(result)) {
8542         /* access symbol directly */
8543         pic16_mov2w (AOP(result), 0);
8544       } else {
8545         /* get old value */
8546         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
8547       }
8548 #if 1
8549       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8550             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
8551                             (unsigned char)(0xff >> (8-bstr))) ));
8552       if (!shifted_and_masked) {
8553         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8554       } else {
8555         /* We have the shifted and masked (literal) right value in `lit' */
8556         if (lit != 0)
8557           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
8558       }
8559     } else { // if (blen == 8 && (bstr % 8) == 0)
8560         if (shifted_and_masked) {
8561             // move right (literal) to WREG (only case where right is not yet in WREG)
8562             pic16_mov2w(AOP(right), (bstr / 8));
8563         }
8564     }
8565
8566     /* write new value back */
8567     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
8568         || IS_DIRECT(result)) {
8569       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
8570     } else {
8571       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
8572     }
8573 #endif
8574
8575     return;
8576   }
8577
8578
8579 #if 0
8580   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8581   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8582   exit(EXIT_FAILURE);
8583 #endif
8584
8585
8586   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
8587   rLen = SPEC_BLEN(etype)-8;
8588
8589   /* now generate for lengths greater than one byte */
8590   while (1) {
8591     rLen -= 8 ;
8592     if (rLen <= 0 ) {
8593       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
8594       break ;
8595     }
8596
8597     switch (p_type) {
8598       case POINTER:
8599         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
8600         break;
8601
8602         /*
8603            case FPOINTER:
8604            MOVA(l);
8605            pic16_emitcode("movx","@dptr,a");
8606            break;
8607
8608            case GPOINTER:
8609            MOVA(l);
8610            DEBUGpic16_emitcode(";lcall","__gptrput");
8611            break;
8612          */
8613       default:
8614         assert(0);
8615     }
8616
8617
8618     pic16_mov2w(AOP(right), offset++);
8619   }
8620
8621   /* last last was not complete */
8622   if (rLen)   {
8623     /* save the byte & read byte */
8624     switch (p_type) {
8625       case POINTER:
8626         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
8627         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8628         break;
8629
8630         /*
8631            case FPOINTER:
8632            pic16_emitcode ("mov","b,a");
8633            pic16_emitcode("movx","a,@dptr");
8634            break;
8635
8636            case GPOINTER:
8637            pic16_emitcode ("push","b");
8638            pic16_emitcode ("push","acc");
8639            pic16_emitcode ("lcall","__gptrget");
8640            pic16_emitcode ("pop","b");
8641            break;
8642          */
8643       default:
8644         assert(0);
8645     }
8646     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
8647     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
8648     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8649     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8650     //        pic16_emitcode ("orl","a,b");
8651   }
8652
8653   //    if (p_type == GPOINTER)
8654   //        pic16_emitcode("pop","b");
8655
8656   switch (p_type) {
8657
8658     case POINTER:
8659       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8660       //        pic16_emitcode("mov","@%s,a",rname);
8661       break;
8662       /*
8663          case FPOINTER:
8664          pic16_emitcode("movx","@dptr,a");
8665          break;
8666
8667          case GPOINTER:
8668          DEBUGpic16_emitcode(";lcall","__gptrput");
8669          break;
8670        */
8671     default:
8672       assert(0);
8673   }
8674
8675   //    pic16_freeAsmop(right, NULL, ic, TRUE);
8676 }
8677
8678 /*-----------------------------------------------------------------*/
8679 /* genDataPointerSet - remat pointer to data space                 */
8680 /*-----------------------------------------------------------------*/
8681 static void genDataPointerSet(operand *right,
8682                               operand *result,
8683                               iCode *ic)
8684 {
8685   int size, offset = 0, resoffset=0 ;
8686
8687     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8688     pic16_aopOp(right,ic,FALSE);
8689
8690     size = AOP_SIZE(right);
8691
8692 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8693
8694 #if 0
8695     if ( AOP_TYPE(result) == AOP_PCODE) {
8696       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8697               AOP(result)->aopu.pcop->name,
8698                 (AOP(result)->aopu.pcop->type == PO_DIR)?
8699               PCOR(AOP(result)->aopu.pcop)->instance:
8700               PCOI(AOP(result)->aopu.pcop)->offset);
8701     }
8702 #endif
8703
8704     if(AOP(result)->aopu.pcop->type == PO_DIR)
8705       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
8706
8707     while (size--) {
8708       if (AOP_TYPE(right) == AOP_LIT) {
8709         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
8710         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
8711       } else {
8712         pic16_mov2w(AOP(right), offset);
8713         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
8714       }
8715       offset++;
8716       resoffset++;
8717     }
8718
8719     pic16_freeAsmop(right,NULL,ic,TRUE);
8720 }
8721
8722
8723
8724 /*-----------------------------------------------------------------*/
8725 /* genNearPointerSet - pic16_emitcode for near pointer put         */
8726 /*-----------------------------------------------------------------*/
8727 static void genNearPointerSet (operand *right,
8728                                operand *result,
8729                                iCode *ic)
8730 {
8731   asmop *aop = NULL;
8732   sym_link *retype;
8733   sym_link *ptype = operandType(result);
8734   sym_link *resetype;
8735
8736     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8737     retype= getSpec(operandType(right));
8738     resetype = getSpec(operandType(result));
8739
8740     pic16_aopOp(result,ic,FALSE);
8741
8742     /* if the result is rematerializable &
8743      * in data space & not a bit variable */
8744
8745     /* and result is not a bit variable */
8746     if (AOP_TYPE(result) == AOP_PCODE
8747       && DCL_TYPE(ptype) == POINTER
8748       && !IS_BITFIELD(retype)
8749       && !IS_BITFIELD(resetype)) {
8750
8751         genDataPointerSet (right,result,ic);
8752         pic16_freeAsmop(result,NULL,ic,TRUE);
8753       return;
8754     }
8755
8756     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8757     pic16_aopOp(right,ic,FALSE);
8758     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8759
8760     /* if bitfield then unpack the bits */
8761     if (IS_BITFIELD(resetype)) {
8762       genPackBits (resetype, result, right, NULL, POINTER);
8763     } else {
8764       /* we have can just get the values */
8765       int size = AOP_SIZE(right);
8766       int offset = 0 ;
8767
8768         pic16_loadFSR0(result, 0);
8769
8770         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8771         while (size--) {
8772           if (pic16_isLitOp(right)) {
8773             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
8774             if (size) {
8775               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
8776             } else {
8777               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
8778             }
8779           } else { // no literal
8780             if(size) {
8781               pic16_emitpcode(POC_MOVFF,
8782                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
8783                   pic16_popCopyReg(&pic16_pc_postinc0)));
8784             } else {
8785               pic16_emitpcode(POC_MOVFF,
8786                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
8787                   pic16_popCopyReg(&pic16_pc_indf0)));
8788             }
8789           }
8790
8791           offset++;
8792         }
8793     }
8794
8795     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8796     /* now some housekeeping stuff */
8797     if (aop) {
8798       /* we had to allocate for this iCode */
8799       pic16_freeAsmop(NULL,aop,ic,TRUE);
8800     } else {
8801       /* we did not allocate which means left
8802        * already in a pointer register, then
8803        * if size > 0 && this could be used again
8804        * we have to point it back to where it
8805        * belongs */
8806       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8807       if (AOP_SIZE(right) > 1
8808         && !OP_SYMBOL(result)->remat
8809         && ( OP_SYMBOL(result)->liveTo > ic->seq
8810         || ic->depth )) {
8811
8812           int size = AOP_SIZE(right) - 1;
8813
8814             while (size--)
8815               pic16_emitcode("decf","fsr0,f");
8816               //pic16_emitcode("dec","%s",rname);
8817       }
8818     }
8819
8820     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8821     /* done */
8822 //release:
8823     pic16_freeAsmop(right,NULL,ic,TRUE);
8824     pic16_freeAsmop(result,NULL,ic,TRUE);
8825 }
8826
8827 /*-----------------------------------------------------------------*/
8828 /* genGenPointerSet - set value from generic pointer space         */
8829 /*-----------------------------------------------------------------*/
8830 static void genGenPointerSet (operand *right,
8831                               operand *result, iCode *ic)
8832 {
8833   int size;
8834   sym_link *retype = getSpec(operandType(result));
8835
8836     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8837
8838     pic16_aopOp(result,ic,FALSE);
8839     pic16_aopOp(right,ic,FALSE);
8840     size = AOP_SIZE(right);
8841
8842     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8843
8844
8845     /* if bit then unpack */
8846     if (IS_BITFIELD(retype)) {
8847 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8848       genPackBits(retype,result,right,"dptr",GPOINTER);
8849       goto release;
8850     }
8851
8852     size = AOP_SIZE(right);
8853
8854     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
8855
8856
8857     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
8858
8859     /* value of right+0 is placed on stack, which will be retrieved
8860      * by the support function thus restoring the stack. The important
8861      * thing is that there is no need to manually restore stack pointer
8862      * here */
8863     pushaop(AOP(right), 0);
8864 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
8865     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
8866     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
8867     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
8868
8869     /* load address to write to in WREG:FSR0H:FSR0L */
8870     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
8871                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
8872     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
8873                                 pic16_popCopyReg(&pic16_pc_prodl)));
8874     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
8875
8876     pic16_callGenericPointerRW(1, size);
8877
8878 release:
8879     pic16_freeAsmop(right,NULL,ic,TRUE);
8880     pic16_freeAsmop(result,NULL,ic,TRUE);
8881 }
8882
8883 /*-----------------------------------------------------------------*/
8884 /* genPointerSet - stores the value into a pointer location        */
8885 /*-----------------------------------------------------------------*/
8886 static void genPointerSet (iCode *ic)
8887 {
8888   operand *right, *result ;
8889   sym_link *type, *etype;
8890   int p_type;
8891
8892     FENTRY;
8893
8894     right = IC_RIGHT(ic);
8895     result = IC_RESULT(ic) ;
8896
8897     /* depending on the type of pointer we need to
8898     move it to the correct pointer register */
8899     type = operandType(result);
8900     etype = getSpec(type);
8901
8902     /* if left is of type of pointer then it is simple */
8903     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8904         p_type = DCL_TYPE(type);
8905     }
8906     else {
8907         /* we have to go by the storage class */
8908         p_type = PTR_TYPE(SPEC_OCLS(etype));
8909
8910 /*      if (SPEC_OCLS(etype)->codesp ) { */
8911 /*          p_type = CPOINTER ;  */
8912 /*      } */
8913 /*      else */
8914 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8915 /*              p_type = FPOINTER ; */
8916 /*          else */
8917 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8918 /*                  p_type = PPOINTER ; */
8919 /*              else */
8920 /*                  if (SPEC_OCLS(etype) == idata ) */
8921 /*                      p_type = IPOINTER ; */
8922 /*                  else */
8923 /*                      p_type = POINTER ; */
8924     }
8925
8926     /* now that we have the pointer type we assign
8927     the pointer values */
8928     switch (p_type) {
8929       case POINTER:
8930       case FPOINTER:
8931       case IPOINTER:
8932         genNearPointerSet (right,result,ic);
8933         break;
8934
8935 #if 0
8936       /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8937       case PPOINTER:
8938         genPagedPointerSet (right,result,ic);
8939         break;
8940
8941       case FPOINTER:
8942         genFarPointerSet (right,result,ic);
8943         break;
8944 #endif
8945
8946       case GPOINTER:
8947         genGenPointerSet (right,result,ic);
8948         break;
8949
8950       default:
8951         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8952           "genPointerSet: illegal pointer type");
8953     }
8954 }
8955
8956 /*-----------------------------------------------------------------*/
8957 /* genIfx - generate code for Ifx statement                        */
8958 /*-----------------------------------------------------------------*/
8959 static void genIfx (iCode *ic, iCode *popIc)
8960 {
8961   operand *cond = IC_COND(ic);
8962   int isbit =0;
8963
8964     FENTRY;
8965
8966     pic16_aopOp(cond,ic,FALSE);
8967
8968     /* get the value into acc */
8969     if (AOP_TYPE(cond) != AOP_CRY)
8970       pic16_toBoolean(cond);
8971     else
8972       isbit = 1;
8973     /* the result is now in the accumulator */
8974     pic16_freeAsmop(cond,NULL,ic,TRUE);
8975
8976     /* if there was something to be popped then do it */
8977     if (popIc)
8978       genIpop(popIc);
8979
8980     /* if the condition is  a bit variable */
8981     if (isbit && IS_ITEMP(cond) &&
8982         SPIL_LOC(cond)) {
8983       genIfxJump(ic,"c");
8984       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8985     } else {
8986       if (isbit && !IS_ITEMP(cond))
8987         genIfxJump(ic,OP_SYMBOL(cond)->rname);
8988         else
8989         genIfxJump(ic,"a");
8990     }
8991     ic->generated = 1;
8992 }
8993
8994 /*-----------------------------------------------------------------*/
8995 /* genAddrOf - generates code for address of                       */
8996 /*-----------------------------------------------------------------*/
8997 static void genAddrOf (iCode *ic)
8998 {
8999   operand *result, *left;
9000   int size;
9001   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9002   pCodeOp *pcop0, *pcop1, *pcop2;
9003
9004     FENTRY;
9005
9006     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9007
9008     sym = OP_SYMBOL( IC_LEFT(ic) );
9009
9010     if(sym->onStack) {
9011       /* get address of symbol on stack */
9012       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
9013 #if 0
9014       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
9015                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
9016 #endif
9017
9018       // operands on stack are accessible via "FSR2 + index" with index
9019       // starting at 2 for arguments and growing from 0 downwards for
9020       // local variables (index == 0 is not assigned so we add one here)
9021       {
9022         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
9023
9024           if (soffs <= 0) {
9025             assert (soffs < 0);
9026             soffs++;
9027           } // if
9028
9029           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
9030           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
9031           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
9032           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
9033           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
9034           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
9035           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
9036       }
9037
9038       goto release;
9039     }
9040
9041 //      if(pic16_debug_verbose) {
9042 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9043 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9044 //      }
9045
9046     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9047     size = AOP_SIZE(IC_RESULT(ic));
9048
9049     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9050     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9051     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9052
9053     if (size == 3) {
9054       pic16_emitpcode(POC_MOVLW, pcop0);
9055       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9056       pic16_emitpcode(POC_MOVLW, pcop1);
9057       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9058       pic16_emitpcode(POC_MOVLW, pcop2);
9059       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9060     } else
9061     if (size == 2) {
9062       pic16_emitpcode(POC_MOVLW, pcop0);
9063       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9064       pic16_emitpcode(POC_MOVLW, pcop1);
9065     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9066     } else {
9067       pic16_emitpcode(POC_MOVLW, pcop0);
9068       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9069     }
9070
9071     pic16_freeAsmop(left, NULL, ic, FALSE);
9072 release:
9073     pic16_freeAsmop(result,NULL,ic,TRUE);
9074 }
9075
9076
9077 /*-----------------------------------------------------------------*/
9078 /* genAssign - generate code for assignment                        */
9079 /*-----------------------------------------------------------------*/
9080 static void genAssign (iCode *ic)
9081 {
9082   operand *result, *right;
9083   sym_link *restype, *rtype;
9084   int size, offset,know_W;
9085   unsigned long lit = 0L;
9086
9087     result = IC_RESULT(ic);
9088     right  = IC_RIGHT(ic) ;
9089
9090     FENTRY;
9091
9092     /* if they are the same */
9093     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9094       return ;
9095
9096     /* reversed order operands are aopOp'ed so that result operand
9097      * is effective in case right is a stack symbol. This maneauver
9098      * allows to use the _G.resDirect flag later */
9099      pic16_aopOp(result,ic,TRUE);
9100     pic16_aopOp(right,ic,FALSE);
9101
9102     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9103
9104     /* if they are the same registers */
9105     if (pic16_sameRegs(AOP(right),AOP(result)))
9106       goto release;
9107
9108     /* if the result is a bit */
9109     if (AOP_TYPE(result) == AOP_CRY) {
9110       /* if the right size is a literal then
9111          we know what the value is */
9112       if (AOP_TYPE(right) == AOP_LIT) {
9113
9114         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9115             pic16_popGet(AOP(result),0));
9116
9117         if (((int) operandLitValue(right)))
9118           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9119               AOP(result)->aopu.aop_dir,
9120               AOP(result)->aopu.aop_dir);
9121         else
9122           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9123               AOP(result)->aopu.aop_dir,
9124               AOP(result)->aopu.aop_dir);
9125
9126         goto release;
9127       }
9128
9129       /* the right is also a bit variable */
9130       if (AOP_TYPE(right) == AOP_CRY) {
9131         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9132         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9133         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9134
9135         goto release ;
9136       }
9137
9138       /* we need to or */
9139       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9140       pic16_toBoolean(right);
9141       emitSKPZ;
9142       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9143       //pic16_aopPut(AOP(result),"a",0);
9144       goto release ;
9145     }
9146
9147     /* bit variables done */
9148     /* general case */
9149     size = AOP_SIZE(result);
9150     offset = 0 ;
9151
9152   /* bit variables done */
9153   /* general case */
9154   size = AOP_SIZE(result);
9155   restype = operandType(result);
9156   rtype = operandType(right);
9157   offset = 0 ;
9158
9159   if(AOP_TYPE(right) == AOP_LIT) {
9160     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
9161     {
9162       lit = ulFromVal (AOP(right)->aopu.aop_lit);
9163
9164       /* patch tag for literals that are cast to pointers */
9165       if (IS_CODEPTR(restype)) {
9166         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
9167         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9168       } else {
9169         if (IS_GENPTR(restype))
9170         {
9171           if (IS_CODEPTR(rtype)) {
9172             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
9173             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9174           } else if (PIC_IS_DATA_PTR(rtype)) {
9175             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
9176             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9177           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
9178             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
9179           } else if (IS_PTR(rtype)) {
9180             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
9181             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9182           }
9183         }
9184       }
9185     } else {
9186       union {
9187         unsigned long lit_int;
9188         float lit_float;
9189       } info;
9190
9191
9192       if(IS_FIXED16X16(operandType(right))) {
9193         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
9194       } else {
9195         /* take care if literal is a float */
9196         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
9197         lit = info.lit_int;
9198       }
9199     }
9200   }
9201
9202 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
9203 //                      sizeof(unsigned long int), sizeof(float));
9204
9205
9206     if (AOP_TYPE(right) == AOP_REG) {
9207       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
9208       while (size--) {
9209         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
9210       } // while
9211       goto release;
9212     }
9213
9214     /* when do we have to read the program memory?
9215      * - if right itself is a symbol in code space
9216      *   (we don't care what it points to if it's a pointer)
9217      * - AND right is not a function (we would want its address)
9218      */
9219     if(AOP_TYPE(right) != AOP_LIT
9220       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
9221       && !IS_FUNC(OP_SYM_TYPE(right))
9222       && !IS_ITEMP(right)) {
9223
9224       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
9225       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
9226
9227       // set up table pointer
9228       if(pic16_isLitOp(right)) {
9229 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
9230         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
9231         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9232         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
9233         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9234         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
9235         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9236       } else {
9237 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
9238         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
9239             pic16_popCopyReg(&pic16_pc_tblptrl)));
9240         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
9241             pic16_popCopyReg(&pic16_pc_tblptrh)));
9242         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
9243             pic16_popCopyReg(&pic16_pc_tblptru)));
9244       }
9245
9246       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
9247       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
9248       while(size--) {
9249         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9250         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
9251             pic16_popGet(AOP(result),offset)));
9252         offset++;
9253       }
9254
9255       /* FIXME: for pointers we need to extend differently (according
9256        * to pointer type DATA/CODE/EEPROM/... :*/
9257       size = getSize(OP_SYM_TYPE(right));
9258       if(AOP_SIZE(result) > size) {
9259         size = AOP_SIZE(result) - size;
9260         while(size--) {
9261           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
9262           offset++;
9263         }
9264       }
9265       goto release;
9266     }
9267
9268 #if 0
9269     /* VR - What is this?! */
9270     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9271       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9272
9273       if(aopIdx(AOP(result),0) == 4) {
9274         /* this is a workaround to save value of right into wreg too,
9275          * value of wreg is going to be used later */
9276         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9277         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9278         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9279         goto release;
9280       } else
9281 //      assert(0);
9282       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9283     }
9284 #endif
9285
9286     size = AOP_SIZE(right);
9287     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
9288     know_W=-1;
9289     while (size--) {
9290       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
9291       if(AOP_TYPE(right) == AOP_LIT) {
9292         if(lit&0xff) {
9293           if(know_W != (lit&0xff))
9294             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9295           know_W = lit&0xff;
9296           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9297         } else
9298           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9299
9300         lit >>= 8;
9301
9302       } else if (AOP_TYPE(right) == AOP_CRY) {
9303         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9304         if(offset == 0) {
9305           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
9306           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9307           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9308         }
9309       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
9310         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9311         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9312       } else {
9313         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9314
9315         if(!_G.resDirect) {                                             /* use this aopForSym feature */
9316           if(AOP_TYPE(result) == AOP_ACC) {
9317             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
9318           } else
9319             if(AOP_TYPE(right) == AOP_ACC) {
9320               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9321             } else {
9322               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9323             }
9324         }
9325       }
9326
9327       offset++;
9328     }
9329     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
9330
9331 release:
9332   pic16_freeAsmop (right,NULL,ic,FALSE);
9333   pic16_freeAsmop (result,NULL,ic,TRUE);
9334 }
9335
9336 /*-----------------------------------------------------------------*/
9337 /* genJumpTab - generates code for jump table                       */
9338 /*-----------------------------------------------------------------*/
9339 static void genJumpTab (iCode *ic)
9340 {
9341   symbol *jtab;
9342   char *l;
9343   pCodeOp *jt_offs;
9344   pCodeOp *jt_offs_hi;
9345   pCodeOp *jt_label;
9346
9347     FENTRY;
9348
9349     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9350     /* get the condition into accumulator */
9351     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9352     MOVA(l);
9353     /* multiply by three */
9354     pic16_emitcode("add","a,acc");
9355     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9356
9357     jtab = newiTempLabel(NULL);
9358     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9359     pic16_emitcode("jmp","@a+dptr");
9360     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9361
9362 #if 0
9363     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9364     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9365     emitSKPNC;
9366     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9367     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9368     pic16_emitpLabel(jtab->key);
9369
9370 #else
9371
9372     jt_offs = pic16_popGetTempReg(0);
9373     jt_offs_hi = pic16_popGetTempReg(1);
9374     jt_label = pic16_popGetLabel (jtab->key);
9375     //fprintf (stderr, "Creating jump table...\n");
9376
9377     // calculate offset into jump table (idx * sizeof (GOTO))
9378     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
9379     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
9380     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
9381     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
9382     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
9383     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
9384     pic16_emitpcode(POC_MOVWF , jt_offs);
9385
9386     // prepare PCLATx (set to first entry in jump table)
9387     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
9388     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
9389     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
9390     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
9391     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
9392
9393     // set PCLATx to selected entry (new PCL is stored in jt_offs)
9394     pic16_emitpcode(POC_ADDWF , jt_offs);
9395     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
9396     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
9397     emitSKPNC;
9398     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
9399
9400     // release temporaries and prepare jump into table (new PCL --> WREG)
9401     pic16_emitpcode(POC_MOVFW , jt_offs);
9402     pic16_popReleaseTempReg (jt_offs_hi, 1);
9403     pic16_popReleaseTempReg (jt_offs, 0);
9404
9405     // jump into the table
9406     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
9407
9408     pic16_emitpLabelFORCE(jtab->key);
9409 #endif
9410
9411     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9412 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
9413
9414     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
9415     /* now generate the jump labels */
9416     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9417          jtab = setNextItem(IC_JTLABELS(ic))) {
9418 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9419         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9420
9421     }
9422     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
9423
9424 }
9425
9426 /*-----------------------------------------------------------------*/
9427 /* genMixedOperation - gen code for operators between mixed types  */
9428 /*-----------------------------------------------------------------*/
9429 /*
9430   TSD - Written for the PIC port - but this unfortunately is buggy.
9431   This routine is good in that it is able to efficiently promote
9432   types to different (larger) sizes. Unfortunately, the temporary
9433   variables that are optimized out by this routine are sometimes
9434   used in other places. So until I know how to really parse the
9435   iCode tree, I'm going to not be using this routine :(.
9436 */
9437 static int genMixedOperation (iCode *ic)
9438 {
9439 #if 0
9440   operand *result = IC_RESULT(ic);
9441   sym_link *ctype = operandType(IC_LEFT(ic));
9442   operand *right = IC_RIGHT(ic);
9443   int ret = 0;
9444   int big,small;
9445   int offset;
9446
9447   iCode *nextic;
9448   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9449
9450   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9451
9452   nextic = ic->next;
9453   if(!nextic)
9454     return 0;
9455
9456   nextright = IC_RIGHT(nextic);
9457   nextleft  = IC_LEFT(nextic);
9458   nextresult = IC_RESULT(nextic);
9459
9460   pic16_aopOp(right,ic,FALSE);
9461   pic16_aopOp(result,ic,FALSE);
9462   pic16_aopOp(nextright,  nextic, FALSE);
9463   pic16_aopOp(nextleft,   nextic, FALSE);
9464   pic16_aopOp(nextresult, nextic, FALSE);
9465
9466   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9467
9468     operand *t = right;
9469     right = nextright;
9470     nextright = t;
9471
9472     pic16_emitcode(";remove right +","");
9473
9474   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9475 /*
9476     operand *t = right;
9477     right = nextleft;
9478     nextleft = t;
9479 */
9480     pic16_emitcode(";remove left +","");
9481   } else
9482     return 0;
9483
9484   big = AOP_SIZE(nextleft);
9485   small = AOP_SIZE(nextright);
9486
9487   switch(nextic->op) {
9488
9489   case '+':
9490     pic16_emitcode(";optimize a +","");
9491     /* if unsigned or not an integral type */
9492     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9493       pic16_emitcode(";add a bit to something","");
9494     } else {
9495
9496       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9497
9498       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9499         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9500         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9501       } else
9502         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9503
9504       offset = 0;
9505       while(--big) {
9506
9507         offset++;
9508
9509         if(--small) {
9510           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9511             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9512             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9513           }
9514
9515           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9516           emitSKPNC;
9517           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9518                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9519                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9520           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9521           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9522
9523         } else {
9524           pic16_emitcode("rlf","known_zero,w");
9525
9526           /*
9527             if right is signed
9528               btfsc  right,7
9529                addlw ff
9530           */
9531           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9532             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9533             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9534           } else {
9535             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9536           }
9537         }
9538       }
9539       ret = 1;
9540     }
9541   }
9542   ret = 1;
9543
9544 release:
9545   pic16_freeAsmop(right,NULL,ic,TRUE);
9546   pic16_freeAsmop(result,NULL,ic,TRUE);
9547   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9548   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9549   if(ret)
9550     nextic->generated = 1;
9551
9552   return ret;
9553 #else
9554   return 0;
9555 #endif
9556 }
9557 /*-----------------------------------------------------------------*/
9558 /* genCast - gen code for casting                                  */
9559 /*-----------------------------------------------------------------*/
9560 static void genCast (iCode *ic)
9561 {
9562   operand *result = IC_RESULT(ic);
9563   sym_link *ctype = operandType(IC_LEFT(ic));
9564   sym_link *rtype = operandType(IC_RIGHT(ic));
9565   sym_link *restype = operandType(IC_RESULT(ic));
9566   operand *right = IC_RIGHT(ic);
9567   int size, offset ;
9568
9569
9570     FENTRY;
9571
9572         /* if they are equivalent then do nothing */
9573 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9574 //              return ;
9575
9576         pic16_aopOp(result,ic,FALSE);
9577         pic16_aopOp(right,ic,FALSE) ;
9578
9579         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9580
9581
9582         /* if the result is a bit */
9583         if (AOP_TYPE(result) == AOP_CRY) {
9584
9585                 /* if the right size is a literal then
9586                  * we know what the value is */
9587                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9588
9589                 if (AOP_TYPE(right) == AOP_LIT) {
9590                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9591                                 pic16_popGet(AOP(result),0));
9592
9593                         if (((int) operandLitValue(right)))
9594                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9595                                         AOP(result)->aopu.aop_dir,
9596                                         AOP(result)->aopu.aop_dir);
9597                         else
9598                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9599                                         AOP(result)->aopu.aop_dir,
9600                                         AOP(result)->aopu.aop_dir);
9601                         goto release;
9602                 }
9603
9604                 /* the right is also a bit variable */
9605                 if (AOP_TYPE(right) == AOP_CRY) {
9606                         emitCLRC;
9607                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9608
9609                         pic16_emitcode("clrc","");
9610                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9611                                 AOP(right)->aopu.aop_dir,
9612                                 AOP(right)->aopu.aop_dir);
9613                         pic16_aopPut(AOP(result),"c",0);
9614                         goto release ;
9615                 }
9616
9617                 /* we need to or */
9618                 if (AOP_TYPE(right) == AOP_REG) {
9619                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9620                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9621                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9622                 }
9623                 pic16_toBoolean(right);
9624                 pic16_aopPut(AOP(result),"a",0);
9625                 goto release ;
9626         }
9627
9628         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9629           int offset = 1;
9630
9631                 size = AOP_SIZE(result);
9632
9633                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9634
9635                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
9636                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9637                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
9638
9639                 while (size--)
9640                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9641
9642                 goto release;
9643         }
9644
9645         if(IS_BITFIELD(getSpec(restype))
9646           && IS_BITFIELD(getSpec(rtype))) {
9647           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
9648         }
9649
9650         /* port from pic14 to cope with generic pointers */
9651         if (PIC_IS_TAGGED(restype))
9652         {
9653           operand *result = IC_RESULT(ic);
9654           //operand *left = IC_LEFT(ic);
9655           operand *right = IC_RIGHT(ic);
9656           int tag = 0xff;
9657
9658           /* copy common part */
9659           int max, size = AOP_SIZE(result);
9660           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
9661           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9662
9663           max = size;
9664           while (size--)
9665           {
9666             pic16_mov2w (AOP(right), size);
9667             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
9668           } // while
9669
9670           /* upcast into generic pointer type? */
9671           if (IS_GENPTR(restype)
9672               && !PIC_IS_TAGGED(rtype)
9673               && (AOP_SIZE(result) > max))
9674           {
9675             /* determine appropriate tag for right */
9676             if (PIC_IS_DATA_PTR(rtype))
9677               tag = GPTR_TAG_DATA;
9678             else if (IS_CODEPTR(rtype))
9679               tag = GPTR_TAG_CODE;
9680             else if (PIC_IS_DATA_PTR(ctype)) {
9681               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
9682               tag = GPTR_TAG_DATA;
9683             } else if (IS_CODEPTR(ctype)) {
9684               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
9685               tag = GPTR_TAG_CODE;
9686             } else if (IS_PTR(rtype)) {
9687               PERFORM_ONCE(weirdcast,
9688               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
9689               );
9690               tag = GPTR_TAG_DATA;
9691             } else {
9692               PERFORM_ONCE(weirdcast,
9693               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
9694               );
9695               tag = GPTR_TAG_DATA;
9696             }
9697
9698             assert (AOP_SIZE(result) == 3);
9699             /* zero-extend address... */
9700             for (size = max; size < AOP_SIZE(result)-1; size++)
9701               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
9702             /* ...and add tag */
9703             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
9704           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
9705             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
9706             for (size = max; size < AOP_SIZE(result)-1; size++)
9707               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
9708             /* add __code tag */
9709             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
9710           } else if (AOP_SIZE(result) > max) {
9711             /* extend non-pointers */
9712             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
9713             pic16_addSign(result, max, 0);
9714           } // if
9715           goto release;
9716         }
9717
9718         /* if they are the same size : or less */
9719         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9720
9721                 /* if they are in the same place */
9722                 if (pic16_sameRegs(AOP(right),AOP(result)))
9723                         goto release;
9724
9725                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9726 #if 0
9727                 if (IS_PTR_CONST(rtype))
9728 #else
9729                 if (IS_CODEPTR(rtype))
9730 #endif
9731                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9732
9733 #if 0
9734                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9735 #else
9736                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9737 #endif
9738                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9739
9740                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9741                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9742                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9743
9744                         if(AOP_SIZE(result) < 2) {
9745                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
9746                         } else {
9747                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9748                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9749                         }
9750                 } else {
9751                         /* if they in different places then copy */
9752                         size = AOP_SIZE(result);
9753                         offset = 0 ;
9754                         while (size--) {
9755                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9756                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9757                                 offset++;
9758                         }
9759                 }
9760                 goto release;
9761         }
9762
9763         /* if the result is of type pointer */
9764         if (IS_PTR(ctype)) {
9765           int p_type;
9766           sym_link *type = operandType(right);
9767           sym_link *etype = getSpec(type);
9768
9769                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9770
9771                 /* pointer to generic pointer */
9772                 if (IS_GENPTR(ctype)) {
9773                   char *l = zero;
9774
9775                         if (IS_PTR(type))
9776                                 p_type = DCL_TYPE(type);
9777                         else {
9778                 /* we have to go by the storage class */
9779                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9780
9781 /*              if (SPEC_OCLS(etype)->codesp )  */
9782 /*                  p_type = CPOINTER ;  */
9783 /*              else */
9784 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9785 /*                      p_type = FPOINTER ; */
9786 /*                  else */
9787 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9788 /*                          p_type = PPOINTER; */
9789 /*                      else */
9790 /*                          if (SPEC_OCLS(etype) == idata ) */
9791 /*                              p_type = IPOINTER ; */
9792 /*                          else */
9793 /*                              p_type = POINTER ; */
9794             }
9795
9796             /* the first two bytes are known */
9797       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9798             size = GPTRSIZE - 1;
9799             offset = 0 ;
9800             while (size--) {
9801               if(offset < AOP_SIZE(right)) {
9802                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
9803                 pic16_mov2f(AOP(result), AOP(right), offset);
9804 /*
9805                 if ((AOP_TYPE(right) == AOP_PCODE) &&
9806                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9807                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9808                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9809                 } else {
9810
9811                   pic16_aopPut(AOP(result),
9812                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9813                          offset);
9814                 }
9815 */
9816               } else
9817                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9818               offset++;
9819             }
9820             /* the last byte depending on type */
9821             switch (p_type) {
9822             case IPOINTER:
9823             case POINTER:
9824             case FPOINTER:
9825                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9826                 break;
9827
9828             case CPOINTER:
9829                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9830                 break;
9831
9832             case PPOINTER:
9833               pic16_emitcode(";BUG!? ","%d",__LINE__);
9834                 l = "#0x03";
9835                 break;
9836
9837             case GPOINTER:
9838                 if (GPTRSIZE > AOP_SIZE(right)) {
9839                   // assume __data pointer... THIS MIGHT BE WRONG!
9840                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9841                 } else {
9842                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9843                 }
9844               break;
9845
9846             default:
9847                 /* this should never happen */
9848                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9849                        "got unknown pointer type");
9850                 exit(1);
9851             }
9852             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
9853             goto release ;
9854         }
9855
9856
9857         assert( 0 );
9858         /* just copy the pointers */
9859         size = AOP_SIZE(result);
9860         offset = 0 ;
9861         while (size--) {
9862             pic16_aopPut(AOP(result),
9863                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9864                    offset);
9865             offset++;
9866         }
9867         goto release ;
9868     }
9869
9870
9871
9872     /* so we now know that the size of destination is greater
9873     than the size of the source.
9874     Now, if the next iCode is an operator then we might be
9875     able to optimize the operation without performing a cast.
9876     */
9877     if(genMixedOperation(ic))
9878       goto release;
9879
9880     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9881
9882     /* we move to result for the size of source */
9883     size = AOP_SIZE(right);
9884     offset = 0 ;
9885
9886     while (size--) {
9887       if(!_G.resDirect)
9888         pic16_mov2f(AOP(result), AOP(right), offset);
9889       offset++;
9890     }
9891
9892     /* now depending on the sign of the destination */
9893     size = AOP_SIZE(result) - AOP_SIZE(right);
9894     /* if unsigned or not an integral type */
9895     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
9896       while (size--)
9897         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9898     } else {
9899       /* we need to extend the sign :( */
9900
9901       if(size == 1) {
9902         /* Save one instruction of casting char to int */
9903         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
9904         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9905         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
9906       } else {
9907         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9908
9909         if(offset)
9910           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9911         else
9912           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9913
9914         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
9915
9916         while (size--)
9917           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
9918       }
9919     }
9920
9921 release:
9922     pic16_freeAsmop(right,NULL,ic,TRUE);
9923     pic16_freeAsmop(result,NULL,ic,TRUE);
9924
9925 }
9926
9927 /*-----------------------------------------------------------------*/
9928 /* genDjnz - generate decrement & jump if not zero instrucion      */
9929 /*-----------------------------------------------------------------*/
9930 static int genDjnz (iCode *ic, iCode *ifx)
9931 {
9932     symbol *lbl, *lbl1;
9933     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9934
9935     if (!ifx)
9936         return 0;
9937
9938     /* if the if condition has a false label
9939        then we cannot save */
9940     if (IC_FALSE(ifx))
9941         return 0;
9942
9943     /* if the minus is not of the form
9944        a = a - 1 */
9945     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9946         !IS_OP_LITERAL(IC_RIGHT(ic)))
9947         return 0;
9948
9949     if (operandLitValue(IC_RIGHT(ic)) != 1)
9950         return 0;
9951
9952     /* if the size of this greater than one then no
9953        saving */
9954     if (getSize(operandType(IC_RESULT(ic))) > 1)
9955         return 0;
9956
9957     /* otherwise we can save BIG */
9958     lbl = newiTempLabel(NULL);
9959     lbl1= newiTempLabel(NULL);
9960
9961     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9962
9963     pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
9964     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
9965
9966     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9967     ifx->generated = 1;
9968     return 1;
9969 }
9970
9971 /*-----------------------------------------------------------------*/
9972 /* genReceive - generate code for a receive iCode                  */
9973 /*-----------------------------------------------------------------*/
9974 static void genReceive (iCode *ic)
9975 {
9976
9977   FENTRY;
9978
9979 #if 0
9980   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
9981         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
9982 #endif
9983 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
9984
9985   if (isOperandInFarSpace(IC_RESULT(ic))
9986       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
9987           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9988
9989     int size = getSize(operandType(IC_RESULT(ic)));
9990     int offset =  pic16_fReturnSizePic - size;
9991
9992       assert( 0 );
9993       while (size--) {
9994         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
9995                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
9996                       offset++;
9997         }
9998
9999       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10000
10001       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10002       size = AOP_SIZE(IC_RESULT(ic));
10003       offset = 0;
10004       while (size--) {
10005         pic16_emitcode ("pop","acc");
10006         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10007       }
10008   } else {
10009     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
10010     _G.accInUse++;
10011     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10012     _G.accInUse--;
10013
10014     /* set pseudo stack pointer to where it should be - dw*/
10015     GpsuedoStkPtr = ic->parmBytes;
10016
10017     /* setting GpsuedoStkPtr has side effects here: */
10018     /* FIXME: What's the correct size of the return(ed) value?
10019      *        For now, assuming '4' as before... */
10020     assignResultValue(IC_RESULT(ic), 4, 0);
10021   }
10022
10023   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10024 }
10025
10026 /*-----------------------------------------------------------------*/
10027 /* genDummyRead - generate code for dummy read of volatiles        */
10028 /*-----------------------------------------------------------------*/
10029 static void
10030 genDummyRead (iCode * ic)
10031 {
10032   operand *op;
10033
10034   op = IC_RIGHT(ic);
10035   if (op && IS_SYMOP(op)) {
10036     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
10037       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
10038       return;
10039     }
10040     pic16_aopOp (op, ic, FALSE);
10041     pic16_mov2w_volatile(AOP(op));
10042     pic16_freeAsmop (op, NULL, ic, TRUE);
10043   } else if (op) {
10044     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
10045   } // if
10046 }
10047
10048 /*-----------------------------------------------------------------*/
10049 /* genpic16Code - generate code for pic16 based controllers        */
10050 /*-----------------------------------------------------------------*/
10051 /*
10052  * At this point, ralloc.c has gone through the iCode and attempted
10053  * to optimize in a way suitable for a PIC. Now we've got to generate
10054  * PIC instructions that correspond to the iCode.
10055  *
10056  * Once the instructions are generated, we'll pass through both the
10057  * peep hole optimizer and the pCode optimizer.
10058  *-----------------------------------------------------------------*/
10059
10060 void genpic16Code (iCode *lic)
10061 {
10062   iCode *ic;
10063   int cln = 0;
10064
10065     lineHead = lineCurr = NULL;
10066
10067     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10068     pic16_addpBlock(pb);
10069
10070 #if 0
10071     /* if debug information required */
10072     if (options.debug && currFunc) {
10073       if (currFunc) {
10074         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10075       }
10076     }
10077 #endif
10078
10079     for (ic = lic ; ic ; ic = ic->next ) {
10080
10081       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
10082       if ( cln != ic->lineno ) {
10083         if ( options.debug ) {
10084           debugFile->writeCLine (ic);
10085         }
10086
10087         if(!options.noCcodeInAsm) {
10088           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
10089               printCLine(ic->filename, ic->lineno)));
10090         }
10091
10092         cln = ic->lineno ;
10093       }
10094
10095       if(options.iCodeInAsm) {
10096         const char *iLine;
10097
10098         /* insert here code to print iCode as comment */
10099         iLine = printILine(ic);
10100         pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
10101         dbuf_free(iLine);
10102       }
10103
10104       /* if the result is marked as
10105        * spilt and rematerializable or code for
10106        * this has already been generated then
10107        * do nothing */
10108       if (resultRemat(ic) || ic->generated )
10109         continue ;
10110
10111       /* depending on the operation */
10112       switch (ic->op) {
10113         case '!' :
10114           pic16_genNot(ic);
10115           break;
10116
10117         case '~' :
10118           pic16_genCpl(ic);
10119           break;
10120
10121         case UNARYMINUS:
10122           genUminus (ic);
10123           break;
10124
10125         case IPUSH:
10126           genIpush (ic);
10127           break;
10128
10129         case IPOP:
10130           /* IPOP happens only when trying to restore a
10131            * spilt live range, if there is an ifx statement
10132            * following this pop then the if statement might
10133            * be using some of the registers being popped which
10134            * would destroy the contents of the register so
10135            * we need to check for this condition and handle it */
10136            if (ic->next
10137              && ic->next->op == IFX
10138              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10139                genIfx (ic->next,ic);
10140           else
10141             genIpop (ic);
10142           break;
10143
10144         case CALL:
10145           genCall (ic);
10146           break;
10147
10148         case PCALL:
10149           genPcall (ic);
10150           break;
10151
10152         case FUNCTION:
10153           genFunction (ic);
10154           break;
10155
10156         case ENDFUNCTION:
10157           genEndFunction (ic);
10158           break;
10159
10160         case RETURN:
10161           genRet (ic);
10162           break;
10163
10164         case LABEL:
10165           genLabel (ic);
10166           break;
10167
10168         case GOTO:
10169           genGoto (ic);
10170           break;
10171
10172         case '+' :
10173           pic16_genPlus (ic) ;
10174           break;
10175
10176         case '-' :
10177           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10178             pic16_genMinus (ic);
10179           break;
10180
10181         case '*' :
10182           genMult (ic);
10183           break;
10184
10185         case '/' :
10186           genDiv (ic) ;
10187           break;
10188
10189         case '%' :
10190           genMod (ic);
10191           break;
10192
10193         case '>' :
10194           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10195           break;
10196
10197         case '<' :
10198           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10199           break;
10200
10201         case LE_OP:
10202         case GE_OP:
10203         case NE_OP:
10204           /* note these two are xlated by algebraic equivalence
10205            * during parsing SDCC.y */
10206           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10207             "got '>=' or '<=' shouldn't have come here");
10208           break;
10209
10210         case EQ_OP:
10211           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10212           break;
10213
10214         case AND_OP:
10215           genAndOp (ic);
10216           break;
10217
10218         case OR_OP:
10219           genOrOp (ic);
10220           break;
10221
10222         case '^' :
10223           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10224           break;
10225
10226         case '|' :
10227           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10228           break;
10229
10230         case BITWISEAND:
10231           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10232           break;
10233
10234         case INLINEASM:
10235           genInline (ic);
10236           break;
10237
10238         case RRC:
10239           genRRC (ic);
10240           break;
10241
10242         case RLC:
10243           genRLC (ic);
10244           break;
10245
10246         case GETHBIT:
10247           genGetHbit (ic);
10248           break;
10249
10250         case LEFT_OP:
10251           genLeftShift (ic);
10252           break;
10253
10254         case RIGHT_OP:
10255           genRightShift (ic);
10256           break;
10257
10258         case GET_VALUE_AT_ADDRESS:
10259           genPointerGet(ic);
10260           break;
10261
10262         case '=' :
10263           if (POINTER_SET(ic))
10264             genPointerSet(ic);
10265           else
10266             genAssign(ic);
10267           break;
10268
10269         case IFX:
10270           genIfx (ic,NULL);
10271           break;
10272
10273         case ADDRESS_OF:
10274           genAddrOf (ic);
10275           break;
10276
10277         case JUMPTABLE:
10278           genJumpTab (ic);
10279           break;
10280
10281         case CAST:
10282           genCast (ic);
10283           break;
10284
10285         case RECEIVE:
10286           genReceive(ic);
10287           break;
10288
10289         case SEND:
10290           addSet(&_G.sendSet,ic);
10291           break;
10292
10293         case DUMMY_READ_VOLATILE:
10294           genDummyRead (ic);
10295           break;
10296
10297         default :
10298           ic = ic;
10299       }
10300     }
10301
10302
10303     /* now we are ready to call the
10304        peep hole optimizer */
10305     if (!options.nopeep)
10306       peepHole (&lineHead);
10307
10308     /* now do the actual printing */
10309     printLine (lineHead, codeOutBuf);
10310
10311 #ifdef PCODE_DEBUG
10312     DFPRINTF((stderr,"printing pBlock\n\n"));
10313     pic16_printpBlock(stdout,pb);
10314 #endif
10315
10316     return;
10317 }