1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for pic16
3 
4   Copyright (C) 1998, Sandeep Dutta . sandeep.dutta@usa.net
5   Copyright (C) 1999, Jean-Louis VERN.jlvern@writeme.com
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port:
8   Copyright (C) 2000, Scott Dattalo scott@dattalo.com
9   PIC16 port:
10   Copyright (C) 2002, Martin Dubuc m.dubuc@rogers.com
11   Copyright (C) 2003-2006,Vangelis Rokas <vrokas AT users.sourceforge.net>
12   Bug Fixes  -  Raphael Neider <rneider AT web.de> (2004,2005)
13   Bug Fixes  -  Borut Razem <borut.razem AT siol.net> (2007)
14   Bug Fixes  -  Mauro Giachero <maurogiachero AT users.sourceforge.net> (2008)
15 
16   This program is free software; you can redistribute it and/or modify it
17   under the terms of the GNU General Public License as published by the
18   Free Software Foundation; either version 2, or (at your option) any
19   later version.
20 
21   This program is distributed in the hope that it will be useful,
22   but WITHOUT ANY WARRANTY; without even the implied warranty of
23   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24   GNU General Public License for more details.
25 
26   You should have received a copy of the GNU General Public License
27   along with this program; if not, write to the Free Software
28   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 -------------------------------------------------------------------------*/
30 /*
31   Notes:
32   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
33                 Made everything static
34 */
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 
41 #include "common.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45 #include "genutils.h"
46 #include "device.h"
47 #include "main.h"
48 #include "glue.h"
49 #include "dbuf_string.h"
50 
51 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
52 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
53 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
54 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
55 #define IS_DIRECT(op)           ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
56 
57 /* Wrapper to execute `code' at most once. */
58 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
59 
60 void pic16_genMult8X8_n (operand *, operand *, operand *);
61 extern void pic16_printpBlock (FILE * of, pBlock * pb);
62 static asmop *newAsmop (short type);
63 static pCodeOp *pic16_popRegFromString (char *str, int size, int offset, operand * op);
64 extern pCode *pic16_newpCodeAsmDir (const char *asdir, const char *argfmt, ...);
65 static void mov2fp (pCodeOp * dst, asmop * src, int offset);
66 static pCodeOp *pic16_popRegFromIdx (int rIdx);
67 static void genCritical (iCode * ic);
68 static void genEndCritical (iCode * ic);
69 
70 int pic16_labelOffset = 0;
71 extern int pic16_debug_verbose;
72 
73 extern set *externs;
74 
75 /* max_key keeps track of the largest label number used in
76    a function. This is then used to adjust the label offset
77    for the next function.
78 */
79 static int max_key = 0;
80 static int GpseudoStkPtr = 0;
81 
82 pCodeOp *pic16_popGetImmd (char *name, unsigned int offset, int index);
83 
84 const char *pic16_AopType (short type);
85 
86 void pic16_pushpCodeOp (pCodeOp * pcop);
87 void pic16_poppCodeOp (pCodeOp * pcop);
88 
89 
90 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
91 
92 /* set the following macro to 1 to enable passing the
93  * first byte of functions parameters via WREG */
94 #define USE_WREG_IN_FUNC_PARAMS 0
95 
96 
97 /* this is the down and dirty file with all kinds of
98    kludgy & hacky stuff. This is what it is all about
99    CODE GENERATION for a specific MCU . some of the
100    routines may be reusable, will have to see */
101 static char *zero = "#0x00";
102 static char *one = "#0x01";
103 
104 
105 /*
106  * Function return value policy (MSB-->LSB):
107  *  8 bits      -> WREG
108  * 16 bits      -> PRODL:WREG
109  * 24 bits      -> PRODH:PRODL:WREG
110  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
111  * >32 bits     -> on stack, and FSR0 points to the beginning
112  */
113 char *fReturnpic16[] = { "WREG", "PRODL", "PRODH", "FSR0L" };
114 int fReturnIdx[] = { IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
115 
116 unsigned pic16_fReturnSizePic = 4;      /* shared with ralloc.c */
117 static char **fReturn = fReturnpic16;
118 
119 static char *accUse[] = { "WREG" };
120 
121 static struct
122 {
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 unsigned char SLMask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
141                                   0xE0, 0xC0, 0x80, 0x00
142                                 };
143 
144 static unsigned char SRMask[] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
145                                   0x07, 0x03, 0x01, 0x00
146                                 };
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 pic16_my_powof2 (unsigned long num)
161 {
162   if (num)
163     {
164       if ((num & (num - 1)) == 0)
165         {
166           int nshifts = -1;
167           while (num)
168             {
169               num >>= 1;
170               nshifts++;
171             }
172           return nshifts;
173         }
174     }
175 
176   return -1;
177 }
178 
179 void
DEBUGpic16_pic16_AopType(int line_no,operand * left,operand * right,operand * result)180 DEBUGpic16_pic16_AopType (int line_no, operand * left, operand * right, operand * result)
181 {
182   DEBUGpic16_emitcode ("; ", "line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
183                        line_no,
184                        ((result) ? pic16_AopType (AOP_TYPE (result)) : "-"),
185                        ((result) ? pic16_aopGet (AOP (result), 0, TRUE, FALSE) : "-"),
186                        ((left) ? pic16_AopType (AOP_TYPE (left)) : "-"),
187                        ((left) ? pic16_aopGet (AOP (left), 0, TRUE, FALSE) : "-"),
188                        ((right) ? pic16_AopType (AOP_TYPE (right)) : "-"),
189                        ((right) ? pic16_aopGet (AOP (right), 0, FALSE, FALSE) : "-"), ((result) ? AOP_SIZE (result) : 0));
190 }
191 
192 void
DEBUGpic16_pic16_AopTypeSign(int line_no,operand * left,operand * right,operand * result)193 DEBUGpic16_pic16_AopTypeSign (int line_no, operand * left, operand * right, operand * result)
194 {
195 
196   DEBUGpic16_emitcode ("; ", "line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
197                        line_no,
198                        ((result) ? pic16_AopType (AOP_TYPE (result)) : "-"),
199                        ((result) ? (SPEC_USIGN (operandType (result)) ? 'u' : 's') : '-'),
200                          ((left) ? pic16_AopType (AOP_TYPE (left)) : "-"),
201                          ((left) ? (SPEC_USIGN (operandType (left)) ? 'u' : 's') : '-'),
202                          ((right) ? pic16_AopType (AOP_TYPE (right)) : "-"),
203                          ((right) ? (SPEC_USIGN (operandType (right)) ? 'u' : 's') : '-'));
204 
205 }
206 
207 void
pic16_emitpcomment(char * fmt,...)208 pic16_emitpcomment (char *fmt, ...)
209 {
210   va_list ap;
211   struct dbuf_s dbuf;
212   const char *line;
213 
214   dbuf_init (&dbuf, INITIAL_INLINEASM);
215 
216   dbuf_append_char (&dbuf, ';');
217   va_start (ap, fmt);
218   dbuf_vprintf (&dbuf, fmt, ap);
219   va_end (ap);
220 
221   line = dbuf_detach_c_str (&dbuf);
222   emit_raw (line);
223   dbuf_free (line);
224 
225   pic16_addpCode2pBlock (pb, pic16_newpCodeCharP (genLine.lineCurr->line));
226 }
227 
228 void
DEBUGpic16_emitcode(char * inst,char * fmt,...)229 DEBUGpic16_emitcode (char *inst, char *fmt, ...)
230 {
231   va_list ap;
232 
233   if (!pic16_debug_verbose)
234     return;
235 
236   va_start (ap, fmt);
237   va_emitcode (inst, fmt, ap);
238   va_end (ap);
239 
240   pic16_addpCode2pBlock (pb, pic16_newpCodeCharP (genLine.lineCurr->line));
241 }
242 
243 void
pic16_emitpLabel(int key)244 pic16_emitpLabel (int key)
245 {
246   if (key > max_key)
247     max_key = key;
248 
249   pic16_addpCode2pBlock (pb, pic16_newpCodeLabel (NULL, labelKey2num (key + pic16_labelOffset)));
250 }
251 
252 void
pic16_emitpLabelFORCE(int key)253 pic16_emitpLabelFORCE (int key)
254 {
255   if (key > max_key)
256     max_key = key;
257 
258   pic16_addpCode2pBlock (pb, pic16_newpCodeLabelFORCE (NULL, labelKey2num (key + pic16_labelOffset)));
259 }
260 
261 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
262  * NEVER call pic16_emitpcode_real directly, please... */
263 void
pic16_emitpcode_real(PIC_OPCODE poc,pCodeOp * pcop)264 pic16_emitpcode_real (PIC_OPCODE poc, pCodeOp * pcop)
265 {
266 
267   if (pcop)
268     pic16_addpCode2pBlock (pb, pic16_newpCode (poc, pcop));
269   else
270     DEBUGpic16_emitcode (";", "%s  ignoring NULL pcop", __FUNCTION__);
271 }
272 
273 void
pic16_emitpinfo(INFO_TYPE itype,pCodeOp * pcop)274 pic16_emitpinfo (INFO_TYPE itype, pCodeOp * pcop)
275 {
276   if (pcop)
277     pic16_addpCode2pBlock (pb, pic16_newpCodeInfo (itype, pcop));
278   else
279     DEBUGpic16_emitcode (";", "%s  ignoring NULL pcop", __FUNCTION__);
280 }
281 
282 void
pic16_emitpcodeNULLop(PIC_OPCODE poc)283 pic16_emitpcodeNULLop (PIC_OPCODE poc)
284 {
285 
286   pic16_addpCode2pBlock (pb, pic16_newpCode (poc, NULL));
287 
288 }
289 
290 
291 #if 1
292 #define pic16_emitcode  DEBUGpic16_emitcode
293 #else
294 /*-----------------------------------------------------------------*/
295 /* pic16_emitcode - writes the code into a file : for now it is simple    */
296 /*-----------------------------------------------------------------*/
297 void
pic16_emitcode(char * inst,char * fmt,...)298 pic16_emitcode (char *inst, char *fmt, ...)
299 {
300   va_list ap;
301   char lb[INITIAL_INLINEASM];
302   unsigned char *lbp = lb;
303 
304   va_start (ap, fmt);
305 
306   if (inst && *inst)
307     {
308       if (fmt && *fmt)
309         SNPRINTF(lb, sizeof(lb), "%s\t", inst);
310       else
311         SNPRINTF(lb, sizeof(lb), "%s", inst);
312 
313       vsprintf (lb + (strlen (lb)), fmt, ap);
314     }
315   else
316     vsprintf (lb, fmt, ap);
317 
318   while (isspace (*lbp))
319     lbp++;
320 
321   if (lbp && *lbp)
322     genLine.lineCurr = (genLine.lineCurr ?
323                         connectLine (genLine.lineCurr, newLineNode (lb)) : (genLine.lineHead = newLineNode (lb)));
324   genLine.lineCurr->isInline = genLine.lineElement.isInline;
325   genLine.lineCurr->isDebug = genLine.lineElement.isDebug;
326   genLine.lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
327   genLine.lineCurr->isComment = (*lbp == ';');
328 
329 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
330 
331 //    if(pic16_debug_verbose)
332 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
333 
334   va_end (ap);
335 }
336 #endif
337 
338 
339 /*-----------------------------------------------------------------*/
340 /* pic16_emitDebuggerSymbol - associate the current code location  */
341 /*   with a debugger symbol                                        */
342 /*-----------------------------------------------------------------*/
343 void
pic16_emitDebuggerSymbol(const char * debugSym)344 pic16_emitDebuggerSymbol (const char *debugSym)
345 {
346   genLine.lineElement.isDebug = 1;
347   pic16_emitcode (";", "%s ==.", debugSym);
348   genLine.lineElement.isDebug = 0;
349 }
350 
351 /*-----------------------------------------------------------------*/
352 /* newAsmop - creates a new asmOp                                  */
353 /*-----------------------------------------------------------------*/
354 static asmop *
newAsmop(short type)355 newAsmop (short type)
356 {
357   asmop *aop;
358 
359   aop = Safe_alloc(sizeof(asmop));
360   aop->type = type;
361   return aop;
362 }
363 
364 /*-----------------------------------------------------------------*/
365 /* resolveIfx - converts an iCode ifx into a form more useful for  */
366 /*              generating code                                    */
367 /*-----------------------------------------------------------------*/
368 static void
resolveIfx(resolvedIfx * resIfx,iCode * ifx)369 resolveIfx (resolvedIfx * resIfx, iCode * ifx)
370 {
371   FENTRY2;
372 
373 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
374 
375   if (!resIfx)
376     return;
377 
378 
379   resIfx->condition = 1;        /* assume that the ifx is true */
380   resIfx->generated = 0;        /* indicate that the ifx has not been used */
381 
382   if (!ifx)
383     {
384       resIfx->lbl = newiTempLabel (NULL);       /* oops, there is no ifx. so create a label */
385 
386 #if 1
387       DEBUGpic16_emitcode ("; ***", "%s %d null ifx creating new label key =%d", __FUNCTION__, __LINE__, resIfx->lbl->key);
388 #endif
389 
390     }
391   else
392     {
393       if (IC_TRUE (ifx))
394         {
395           resIfx->lbl = IC_TRUE (ifx);
396         }
397       else
398         {
399           resIfx->lbl = IC_FALSE (ifx);
400           resIfx->condition = 0;
401         }
402 
403 #if 1
404       if (IC_TRUE (ifx))
405         DEBUGpic16_emitcode ("; +++", "ifx true is non-null");
406       else
407         DEBUGpic16_emitcode ("; +++", "ifx true is null");
408       if (IC_FALSE (ifx))
409         DEBUGpic16_emitcode ("; +++", "ifx false is non-null");
410       else
411         DEBUGpic16_emitcode ("; +++", "ifx false is null");
412 #endif
413     }
414 
415   DEBUGpic16_emitcode ("; ***", "%s lbl->key=%d, (lab offset=%d)", __FUNCTION__, resIfx->lbl->key, pic16_labelOffset);
416 
417 }
418 
419 #if 0
420 /*-----------------------------------------------------------------*/
421 /* pointerCode - returns the code for a pointer type               */
422 /*-----------------------------------------------------------------*/
423 static int
424 pointerCode (sym_link * etype)
425 {
426 
427   return PTR_TYPE (SPEC_OCLS (etype));
428 
429 }
430 #endif
431 
432 /*-----------------------------------------------------------------*/
433 /* aopForSym - for a true symbol                                   */
434 /*-----------------------------------------------------------------*/
435 static asmop *
aopForSym(iCode * ic,operand * op,bool result)436 aopForSym (iCode * ic, operand * op, bool result)
437 {
438   symbol *sym = OP_SYMBOL (op);
439   asmop *aop;
440   memmap *space = SPEC_OCLS (sym->etype);
441 
442   FENTRY2;
443 
444   _G.resDirect = 0;             /* clear flag that instructs the result is loaded directly from aopForSym */
445 
446 //    sym = OP_SYMBOL(op);
447 
448   /* if already has one */
449   if (sym->aop)
450     {
451       DEBUGpic16_emitcode ("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
452       return sym->aop;
453     }
454 
455 #if 0
456   /* if symbol was initially placed onStack then we must re-place it
457    * to direct memory, since pic16 does not have a specific stack */
458   if (sym->onStack)
459     {
460       fprintf (stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL (op)->name);
461     }
462 #endif
463 
464 
465 #if 0
466   if (sym->iaccess)
467     {
468       if (space->paged)
469         {
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         {
506 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
507 
508           for (i = 0; i < aop->size; i++)
509             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx (AOP (IC_RESULT (ic))->aopu.aop_reg[i]->rIdx);
510           _G.resDirect = 1;     /* notify that result will be loaded directly from aopForSym */
511         }
512       else if (1 && ic->op == SEND)
513         {
514 
515           /* if SEND do the send here */
516           _G.resDirect = 1;
517         }
518       else
519         {
520 //                debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
521           for (i = 0; i < aop->size; i++)
522             {
523               aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond (_G.fregsUsed, _G.sregsAlloc, 0);
524               _G.sregsAlloc = bitVectSetBit (_G.sregsAlloc, PCOR (pcop[i])->r->rIdx);
525             }
526         }
527 
528 
529 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
530 
531 #if 1
532       DEBUGpic16_emitcode (";", "%d sym->rname = %s, size = %d stack = %d", __LINE__, sym->rname, aop->size, sym->stack);
533 
534       // we do not need to load the value if it is to be defined...
535       if (result)
536         return aop;
537 
538       if (_G.accInUse)
539         {
540           pic16_pushpCodeOp (pic16_popCopyReg (&pic16_pc_wreg));
541         }
542 
543       for (i = 0; i < aop->size; i++)
544         {
545 
546           /* initialise for stack access via frame pointer */
547           // operands on stack are accessible via "{FRAME POINTER} + index" with index
548           // starting at 2 for arguments and growing from 0 downwards for
549           // local variables (index == 0 is not assigned so we add one here)
550           {
551             int soffs = sym->stack;
552             if (soffs <= 0)
553               {
554                 assert (soffs < 0);
555                 soffs++;
556               }                 // if
557 
558             if (1 && ic->op == SEND)
559               {
560                 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (soffs + aop->size - i - 1 /*+ _G.stack_lat */ ));
561                 pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg (pic16_frame_plusw),
562                                  pic16_popCopyReg (pic16_stack_postdec)));
563               }
564             else
565               {
566                 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (soffs + i /*+ _G.stack_lat */ ));
567                 pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg (pic16_frame_plusw), pcop[i]));
568               }
569           }
570         }
571 
572       if (_G.accInUse)
573         {
574           pic16_poppCodeOp (pic16_popCopyReg (&pic16_pc_wreg));
575         }
576 
577       return (aop);
578 #endif
579 
580 #if 0
581       /* now assign the address of the variable to
582          the pointer register */
583       if (aop->type != AOP_STK)
584         {
585 
586           if (sym->onStack)
587             {
588               if (_G.accInUse)
589                 pic16_emitcode ("push", "acc");
590 
591               pic16_emitcode ("mov", "a,_bp");
592               pic16_emitcode ("add", "a,#0x%02x",
593                               ((sym->stack < 0) ? ((char) (sym->stack - _G.nRegsSaved)) : ((char) sym->stack)) & 0xff);
594               pic16_emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
595 
596               if (_G.accInUse)
597                 pic16_emitcode ("pop", "acc");
598             }
599           else
600             pic16_emitcode ("mov", "%s,#%s", aop->aopu.aop_ptr->name, sym->rname);
601           aop->paged = space->paged;
602         }
603       else
604         aop->aopu.aop_stk = sym->stack;
605       return aop;
606 #endif
607 
608     }
609 #endif
610 
611 #if 1
612   /* special case for a function */
613   if (IS_FUNC (sym->type))
614     {
615       sym->aop = aop = newAsmop (AOP_PCODE);
616       aop->aopu.pcop = pic16_popGetImmd (sym->rname, 0, 0);
617       PCOI (aop->aopu.pcop)->_const = IN_CODESPACE (space);
618       PCOI (aop->aopu.pcop)->index = 0;
619       aop->size = FARPTRSIZE;
620       DEBUGpic16_emitcode (";", "%d size = %d, name =%s", __LINE__, aop->size, sym->rname);
621       return aop;
622     }
623 #endif
624 
625 
626 
627   //DEBUGpic16_emitcode(";","%d",__LINE__);
628   /* if in bit space */
629   if (IN_BITSPACE (space))
630     {
631       sym->aop = aop = newAsmop (AOP_CRY);
632       aop->aopu.aop_dir = sym->rname;
633       aop->size = getSize (sym->type);
634       DEBUGpic16_emitcode (";", "%d sym->rname = %s, size = %d", __LINE__, sym->rname, aop->size);
635       return aop;
636     }
637   /* if it is in direct space */
638   if (IN_DIRSPACE (space))
639     {
640       if (!strcmp (sym->rname, "_WREG"))
641         {
642           sym->aop = aop = newAsmop (AOP_ACC);
643           aop->size = getSize (sym->type);      /* should always be 1 */
644           assert (aop->size == 1);
645           DEBUGpic16_emitcode (";", "%d sym->rname (AOP_ACC) = %s, size = %d", __LINE__, sym->rname, aop->size);
646           return (aop);
647         }
648       else
649         {
650           sym->aop = aop = newAsmop (AOP_DIR);
651           aop->aopu.aop_dir = sym->rname;
652           aop->size = getSize (sym->type);
653           DEBUGpic16_emitcode (";", "%d sym->rname (AOP_DIR) = %s, size = %d", __LINE__, sym->rname, aop->size);
654           pic16_allocDirReg (IC_LEFT (ic));
655           return (aop);
656         }
657     }
658 
659   if (IN_FARSPACE (space) && !IN_CODESPACE (space))
660     {
661       sym->aop = aop = newAsmop (AOP_DIR);
662       aop->aopu.aop_dir = sym->rname;
663       aop->size = getSize (sym->type);
664       DEBUGpic16_emitcode (";", "%d sym->rname = %s, size = %d", __LINE__, sym->rname, aop->size);
665       pic16_allocDirReg (IC_LEFT (ic));
666       return aop;
667     }
668 
669 
670   /* only remaining is far space */
671   sym->aop = aop = newAsmop (AOP_PCODE);
672 
673   /* change the next if to 1 to revert to good old immediate code */
674   if (IN_CODESPACE (space))
675     {
676       aop->aopu.pcop = pic16_popGetImmd (sym->rname, 0, 0);
677       PCOI (aop->aopu.pcop)->_const = IN_CODESPACE (space);
678       PCOI (aop->aopu.pcop)->index = 0;
679     }
680   else
681     {
682       /* try to allocate via direct register */
683       aop->aopu.pcop = pic16_popRegFromString (sym->rname, getSize (sym->type), sym->offset, op);       // Patch 8
684 //              aop->size = getSize( sym->type );
685     }
686 
687   DEBUGpic16_emitcode (";", "%d: rname %s, val %d, const = %d", __LINE__, sym->rname, 0, PCOI (aop->aopu.pcop)->_const);
688 
689 #if 0
690   if (!pic16_allocDirReg (IC_LEFT (ic)))
691     return NULL;
692 #endif
693 
694   if (IN_DIRSPACE (space))
695     aop->size = NEARPTRSIZE;
696   else if (IN_CODESPACE (space) || IN_FARSPACE (space))
697     aop->size = FARPTRSIZE;
698   else if (IC_LEFT (ic) && AOP (IC_LEFT (ic)))
699     aop->size = AOP_SIZE (IC_LEFT (ic));
700   else if (IC_RIGHT (ic) && AOP (IC_RIGHT (ic)))
701     aop->size = AOP_SIZE (IC_RIGHT (ic));
702   else if (sym->onStack)
703     {
704       aop->size = NEARPTRSIZE;
705     }
706   else
707     {
708       if (SPEC_SCLS (sym->etype) == S_PDATA)
709         {
710           fprintf (stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
711           aop->size = FARPTRSIZE;
712         }
713       else
714         assert (0);
715     }
716 
717   DEBUGpic16_emitcode (";", "%d size = %d", __LINE__, aop->size);
718 
719   /* if it is in code space */
720   if (IN_CODESPACE (space))
721     aop->code = 1;
722 
723   return aop;
724 }
725 
726 /*-----------------------------------------------------------------*/
727 /* aopForRemat - rematerialzes an object                           */
728 /*-----------------------------------------------------------------*/
729 static asmop *
aopForRemat(operand * op,bool result)730 aopForRemat (operand * op, bool result) // x symbol *sym)
731 {
732   symbol *sym = OP_SYMBOL (op);
733   operand *refop;
734   iCode *ic = NULL;
735   asmop *aop = newAsmop (AOP_PCODE);
736   int val = 0;
737   int viaimmd = 0;
738 
739   FENTRY2;
740 
741   ic = sym->rematiCode;
742 
743   if (IS_OP_POINTER (op))
744     {
745       DEBUGpic16_emitcode (";", "%s %d IS_OP_POINTER", __FUNCTION__, __LINE__);
746     }
747 
748 //    if(!result)               /* fixme-vr */
749   for (;;)
750     {
751 //              chat *iLine = printILine(ic);
752 //              pic16_emitpcomment("ic: %s\n", iLine);
753 //              dbuf_free(iLine);
754 
755       if (ic->op == '+')
756         {
757           val += (int) operandLitValue (IC_RIGHT (ic));
758         }
759       else if (ic->op == '-')
760         {
761           val -= (int) operandLitValue (IC_RIGHT (ic));
762         }
763       else
764         break;
765 
766       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
767     }
768 
769   refop = IC_LEFT (ic);
770 
771   if (!op->isaddr)
772     viaimmd++;
773   else
774     viaimmd = 0;
775 
776   /* set the following if to 1 to revert to good old immediate code */
777   if (IN_CODESPACE (SPEC_OCLS (OP_SYM_ETYPE (refop))) || viaimmd)
778     {
779 
780       DEBUGpic16_emitcode (";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize (sym->type));
781 
782       aop->aopu.pcop = pic16_popGetImmd (OP_SYMBOL (IC_LEFT (ic))->rname, 0, val);
783 
784 #if 0
785       PCOI (aop->aopu.pcop)->_const = IS_PTR_CONST (operandType (op));
786 #else
787       PCOI (aop->aopu.pcop)->_const = IS_CODEPTR (operandType (op));
788 #endif
789 
790       PCOI (aop->aopu.pcop)->index = val;
791 
792       aop->size = getSize (sym->type);
793     }
794   else
795     {
796       DEBUGpic16_emitcode (";", "%s:%d dir size: %d", __FILE__, __LINE__, getSize (OP_SYMBOL (IC_LEFT (ic))->type));
797 
798       aop->aopu.pcop = pic16_popRegFromString (OP_SYMBOL (IC_LEFT (ic))->rname,
799                        getSize (OP_SYMBOL (IC_LEFT (ic))->type), val, op);
800 
801       aop->size = getSize (OP_SYMBOL (IC_LEFT (ic))->type);
802     }
803 
804 
805   DEBUGpic16_emitcode (";", "%d: rname %s, val %d, const = %d", __LINE__, OP_SYMBOL (IC_LEFT (ic))->rname,
806 #if 0
807                        val, IS_PTR_CONST (operandType (op)));
808 #else
809                        val, IS_CODEPTR (operandType (op)));
810 #endif
811 
812 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
813 
814   pic16_allocDirReg (IC_LEFT (ic));
815 
816   if (IN_CODESPACE (SPEC_OCLS (OP_SYM_ETYPE (op))))
817     aop->code = 1;
818 
819   return aop;
820 }
821 
822 #if 0
823 static int
824 aopIdx (asmop * aop, int offset)
825 {
826   if (!aop)
827     return -1;
828 
829   if (aop->type != AOP_REG)
830     return -2;
831 
832   return aop->aopu.aop_reg[offset]->rIdx;
833 
834 }
835 #endif
836 
837 /*-----------------------------------------------------------------*/
838 /* regsInCommon - two operands have some registers in common       */
839 /*-----------------------------------------------------------------*/
840 static bool
regsInCommon(operand * op1,operand * op2)841 regsInCommon (operand * op1, operand * op2)
842 {
843   symbol *sym1, *sym2;
844   int i;
845 
846   /* if they have registers in common */
847   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
848     return FALSE;
849 
850   sym1 = OP_SYMBOL (op1);
851   sym2 = OP_SYMBOL (op2);
852 
853   if (sym1->nRegs == 0 || sym2->nRegs == 0)
854     return FALSE;
855 
856   for (i = 0; i < sym1->nRegs; i++)
857     {
858       int j;
859       if (!sym1->regs[i])
860         continue;
861 
862       for (j = 0; j < sym2->nRegs; j++)
863         {
864           if (!sym2->regs[j])
865             continue;
866 
867           if (sym2->regs[j] == sym1->regs[i])
868             return TRUE;
869         }
870     }
871 
872   return FALSE;
873 }
874 
875 /*-----------------------------------------------------------------*/
876 /* operandsEqu - equivalent                                        */
877 /*-----------------------------------------------------------------*/
878 static bool
operandsEqu(operand * op1,operand * op2)879 operandsEqu (operand * op1, operand * op2)
880 {
881   symbol *sym1, *sym2;
882 
883   /* if they not symbols */
884   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
885     return FALSE;
886 
887   sym1 = OP_SYMBOL (op1);
888   sym2 = OP_SYMBOL (op2);
889 
890   /* if both are itemps & one is spilt
891      and the other is not then false */
892   if (IS_ITEMP (op1) && IS_ITEMP (op2) && sym1->isspilt != sym2->isspilt)
893     return FALSE;
894 
895   /* if they are the same */
896   if (sym1 == sym2)
897     return TRUE;
898 
899   if (sym1->rname[0] && sym2->rname[0] && strcmp (sym1->rname, sym2->rname) == 0)
900     return TRUE;
901 
902 
903   /* if left is a tmp & right is not */
904   if (IS_ITEMP (op1) && !IS_ITEMP (op2) && sym1->isspilt && (SYM_SPIL_LOC (sym1) == sym2))
905     return TRUE;
906 
907   if (IS_ITEMP (op2) && !IS_ITEMP (op1) && sym2->isspilt && sym1->level > 0 && (SYM_SPIL_LOC (sym2) == sym1))
908     return TRUE;
909 
910   return FALSE;
911 }
912 
913 /*-----------------------------------------------------------------*/
914 /* pic16_sameRegs - two asmops have the same registers                   */
915 /*-----------------------------------------------------------------*/
916 bool
pic16_sameRegs(asmop * aop1,asmop * aop2)917 pic16_sameRegs (asmop * aop1, asmop * aop2)
918 {
919   int i;
920 
921   if (aop1 == aop2)
922     return TRUE;
923 
924   DEBUGpic16_emitcode (";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
925                        pic16_AopType (aop1->type), pic16_AopType (aop2->type));
926 
927   if (aop1->type == AOP_ACC && aop2->type == AOP_ACC)
928     return TRUE;
929 
930   if (aop1->type != AOP_REG || aop2->type != AOP_REG)
931     return FALSE;
932 
933   /* This is a bit too restrictive if one is a subset of the other...
934      if (aop1->size != aop2->size )
935      return FALSE ;
936    */
937 
938   for (i = 0; i < min (aop1->size, aop2->size); i++)
939     {
940 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
941 
942 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
943       if (strcmp (aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name))
944         return FALSE;
945     }
946 
947   return TRUE;
948 }
949 
950 bool
pic16_sameRegsOfs(asmop * aop1,asmop * aop2,int offset)951 pic16_sameRegsOfs (asmop * aop1, asmop * aop2, int offset)
952 {
953   DEBUGpic16_emitcode (";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
954                        pic16_AopType (aop1->type), pic16_AopType (aop2->type), offset);
955 
956   if (aop1 == aop2)
957     return TRUE;
958   if (aop1->type != AOP_REG || aop2->type != AOP_REG)
959     return FALSE;
960 
961   if (strcmp (aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))
962     return FALSE;
963 
964   return TRUE;
965 }
966 
967 
968 /*-----------------------------------------------------------------*/
969 /* pic16_aopOp - allocates an asmop for an operand  :                    */
970 /*-----------------------------------------------------------------*/
971 void
pic16_aopOp(operand * op,iCode * ic,bool result)972 pic16_aopOp (operand * op, iCode * ic, bool result)
973 {
974   asmop *aop;
975   symbol *sym;
976   int i;
977 
978   if (!op)
979     return;
980 
981   DEBUGpic16_emitcode (";", "%s %d", __FUNCTION__, __LINE__);
982 
983   /* if this a literal */
984   if (IS_OP_LITERAL (op))
985     {
986       op->aop = aop = newAsmop (AOP_LIT);
987       aop->aopu.aop_lit = OP_VALUE (op);
988       aop->size = getSize (operandType (op));
989       return;
990     }
991 
992   {
993     sym_link *type = operandType (op);
994 #if 0
995     if (IS_PTR_CONST (type))
996 #else
997     if (IS_CODEPTR (type))
998 #endif
999       DEBUGpic16_emitcode (";", "%d aop type is const pointer", __LINE__);
1000   }
1001 
1002   /* if already has a asmop then continue */
1003   if (op->aop)
1004     return;
1005 
1006   /* if the underlying symbol has a aop */
1007   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1008     {
1009       DEBUGpic16_emitcode (";", "%d has symbol", __LINE__);
1010       op->aop = OP_SYMBOL (op)->aop;
1011       return;
1012     }
1013 
1014   /* if this is a true symbol */
1015   if (IS_TRUE_SYMOP (op))
1016     {
1017       DEBUGpic16_emitcode (";", "%d - true symop", __LINE__);
1018       op->aop = aopForSym (ic, op, result);
1019       return;
1020     }
1021 
1022   /* this is a temporary : this has
1023      only four choices :
1024      a) register
1025      b) spillocation
1026      c) rematerialize
1027      d) conditional
1028      e) can be a return use only */
1029 
1030   sym = OP_SYMBOL (op);
1031 
1032   DEBUGpic16_emitcode ("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1033   /* if the type is a conditional */
1034   if (sym->regType == REG_CND)
1035     {
1036       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1037       aop->size = 0;
1038       return;
1039     }
1040 
1041   /* if it is spilt then two situations
1042      a) is rematerialize
1043      b) has a spill location */
1044   if (sym->isspilt || sym->nRegs == 0)
1045     {
1046 
1047 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1048       DEBUGpic16_emitcode (";", "%d", __LINE__);
1049       /* rematerialize it NOW */
1050       if (sym->remat)
1051         {
1052 
1053           sym->aop = op->aop = aop = aopForRemat (op, result);
1054           return;
1055         }
1056 
1057 #if 1
1058       if (sym->accuse)
1059         {
1060           int i;
1061           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1062           aop->size = getSize (sym->type);
1063           for (i = 0; i < 1; i++)
1064             {
1065               aop->aopu.aop_str[i] = accUse[i];
1066 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, SYM_SPIL_LOC(sym)->offset);
1067             }
1068           fprintf (stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1069           DEBUGpic16_emitcode (";", "%d size=%d", __LINE__, aop->size);
1070           return;
1071         }
1072 #endif
1073 
1074 #if 1
1075       if (sym->ruonly)
1076         {
1077           /*
1078              sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1079              aop->aopu.pcop = pic16_popGetImmd(SYM_SPIL_LOC(sym)->rname,0,SYM_SPIL_LOC(sym)->offset);
1080              //pic16_allocDirReg (IC_LEFT(ic));
1081              aop->size = getSize(sym->type);
1082            */
1083 
1084           unsigned i;
1085 
1086           aop = op->aop = sym->aop = newAsmop (AOP_REG);
1087           aop->size = getSize (sym->type);
1088           for (i = 0; i < pic16_fReturnSizePic; i++)
1089             aop->aopu.aop_reg[i] = PCOR (pic16_popRegFromIdx (fReturnIdx[i]))->r;
1090 
1091           DEBUGpic16_emitcode (";", "%d", __LINE__);
1092           return;
1093         }
1094 #endif
1095       /* else spill location  */
1096       if (sym->isspilt && SYM_SPIL_LOC (sym) && getSize (sym->type) != getSize (SYM_SPIL_LOC (sym)->type))
1097         {
1098           /* force a new aop if sizes differ */
1099           SYM_SPIL_LOC (sym)->aop = NULL;
1100         }
1101 
1102 #if 0
1103       DEBUGpic16_emitcode (";", "%s %d %s sym->rname = %s, offset %d",
1104                            __FUNCTION__, __LINE__, SYM_SPIL_LOC (sym)->rname, sym->rname, SYM_SPIL_LOC (sym)->offset);
1105 #endif
1106 
1107       //aop->aopu.pcop = pic16_popGetImmd(SYM_SPIL_LOC(sym)->rname,0,SYM_SPIL_LOC(sym)->offset);
1108       if (sym->isspilt && SYM_SPIL_LOC (sym) && SYM_SPIL_LOC (sym)->rname)
1109         {
1110           sym->aop = op->aop = aop = newAsmop (AOP_PCODE);
1111           aop->aopu.pcop = pic16_popRegFromString (SYM_SPIL_LOC (sym)->rname,
1112                            getSize (sym->type), SYM_SPIL_LOC (sym)->offset, op);
1113         }
1114       else if (getSize (sym->type) <= 1)
1115         {
1116           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1117           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__,
1118                               __LINE__);
1119           assert (getSize (sym->type) <= 1);
1120           sym->aop = op->aop = aop = newAsmop (AOP_PCODE);
1121           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1122         }
1123       else
1124         {
1125           /* We need some kind of dummy area for getSize(sym->type) byte,
1126            * use WREG for all storage locations.
1127            * XXX: This only works if we are implementing a `dummy read',
1128            *      the stored value will not be retrievable...
1129            *      See #1503234 for a case requiring this. */
1130           sym->aop = op->aop = aop = newAsmop (AOP_REG);
1131           aop->size = getSize (sym->type);
1132           for (i = 0; i < aop->size; i++)
1133             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1134         }
1135       aop->size = getSize (sym->type);
1136 
1137       return;
1138     }
1139 
1140   {
1141     sym_link *type = operandType (op);
1142 #if 0
1143     if (IS_PTR_CONST (type))
1144 #else
1145     if (IS_CODEPTR (type))
1146 #endif
1147       DEBUGpic16_emitcode (";", "%d aop type is const pointer", __LINE__);
1148   }
1149 
1150   /* must be in a register */
1151   DEBUGpic16_emitcode (";", "%d register type nRegs=%d", __LINE__, sym->nRegs);
1152   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1153   aop->size = sym->nRegs;
1154   for (i = 0; i < sym->nRegs; i++)
1155     aop->aopu.aop_reg[i] = sym->regs[i];
1156 }
1157 
1158 /*-----------------------------------------------------------------*/
1159 /* pic16_freeAsmop - free up the asmop given to an operand               */
1160 /*----------------------------------------------------------------*/
1161 void
pic16_freeAsmop(operand * op,asmop * aaop,iCode * ic,bool pop)1162 pic16_freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1163 {
1164   asmop *aop;
1165 
1166   if (!op)
1167     aop = aaop;
1168   else
1169     aop = op->aop;
1170 
1171   if (!aop)
1172     return;
1173 
1174   if (aop->freed)
1175     goto dealloc;
1176 
1177   aop->freed = 1;
1178 
1179 #if 1
1180   switch (aop->type)
1181     {
1182     case AOP_STA:
1183     {
1184       int i;
1185 
1186       /* we must store the result on stack */
1187       if ((op == IC_RESULT (ic)) && RESULTONSTA (ic))
1188         {
1189           // operands on stack are accessible via "FSR2 + index" with index
1190           // starting at 2 for arguments and growing from 0 downwards for
1191           // local variables (index == 0 is not assigned so we add one here)
1192           int soffs = OP_SYMBOL (IC_RESULT (ic))->stack;
1193           if (soffs <= 0)
1194             {
1195               assert (soffs < 0);
1196               soffs++;
1197             }                 // if
1198           if (_G.accInUse)
1199             pic16_pushpCodeOp (pic16_popCopyReg (&pic16_pc_wreg));
1200           for (i = 0; i < aop->size; i++)
1201             {
1202               /* initialise for stack access via frame pointer */
1203               pic16_emitpcode (POC_MOVLW, pic16_popGetLit (soffs + i /*+ _G.stack_lat */ ));
1204               pic16_emitpcode (POC_MOVFF, pic16_popGet2p (aop->aopu.stk.pop[i], pic16_popCopyReg (pic16_frame_plusw)));
1205             }
1206 
1207           if (_G.accInUse)
1208             pic16_poppCodeOp (pic16_popCopyReg (&pic16_pc_wreg));
1209         }
1210 
1211       if (!_G.resDirect)
1212         {
1213           for (i = 0; i < aop->size; i++)
1214             {
1215               PCOR (aop->aopu.stk.pop[i])->r->isFree = 1;
1216 
1217               if (bitVectBitValue (_G.sregsAlloc, PCOR (aop->aopu.stk.pop[i])->r->rIdx))
1218                 {
1219                   bitVectUnSetBit (_G.sregsAlloc, PCOR (aop->aopu.stk.pop[i])->r->rIdx);
1220 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1221                 }
1222             }
1223 
1224           if (_G.sregsAllocSet)
1225             {
1226               reg_info *sr;
1227 
1228               _G.sregsAllocSet = reverseSet (_G.sregsAllocSet);
1229               for (sr = setFirstItem (_G.sregsAllocSet); sr; sr = setFirstItem (_G.sregsAllocSet))
1230                 {
1231                   pic16_poppCodeOp (pic16_popRegFromIdx (sr->rIdx));
1232                   deleteSetItem (&_G.sregsAllocSet, sr);
1233                 }
1234             }
1235         }
1236       _G.resDirect = 0;
1237     }
1238     break;
1239 #if 0
1240     case AOP_STK:
1241     {
1242       int sz = aop->size;
1243       int stk = aop->aopu.aop_stk + aop->size;
1244       bitVectUnSetBit (ic->rUsed, R0_IDX);
1245       bitVectUnSetBit (ic->rUsed, R1_IDX);
1246 
1247       getFreePtr (ic, &aop, FALSE);
1248 
1249       if (options.stack10bit)
1250         {
1251           /* I'm not sure what to do here yet... */
1252           /* #STUB */
1253           fprintf (stderr, "*** Warning: probably generating bad code for " "10 bit stack mode.\n");
1254         }
1255 
1256       if (stk)
1257         {
1258           pic16_emitcode ("mov", "a,_bp");
1259           pic16_emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1260           pic16_emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1261         }
1262       else
1263         {
1264           pic16_emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1265         }
1266 
1267       while (sz--)
1268         {
1269           pic16_emitcode ("pop", "acc");
1270           pic16_emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1271           if (!sz)
1272             break;
1273           pic16_emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1274         }
1275       op->aop = aop;
1276       pic16_freeAsmop (op, NULL, ic, TRUE);
1277       if (_G.r0Pushed)
1278         {
1279           pic16_emitcode ("pop", "ar0");
1280           _G.r0Pushed--;
1281         }
1282 
1283       if (_G.r1Pushed)
1284         {
1285           pic16_emitcode ("pop", "ar1");
1286           _G.r1Pushed--;
1287         }
1288     }
1289 #endif
1290 
1291     }
1292 #endif
1293 
1294 dealloc:
1295   /* all other cases just dealloc */
1296   if (op)
1297     {
1298       op->aop = NULL;
1299       if (IS_SYMOP (op))
1300         {
1301           OP_SYMBOL (op)->aop = NULL;
1302           /* if the symbol has a spill */
1303           if (SPIL_LOC (op))
1304             SPIL_LOC (op)->aop = NULL;
1305         }
1306     }
1307 }
1308 
1309 /*-----------------------------------------------------------------*/
1310 /* pic16_aopGet - for fetching value of the aop                          */
1311 /*-----------------------------------------------------------------*/
1312 char *
pic16_aopGet(asmop * aop,int offset,bool bit16,bool dname)1313 pic16_aopGet (asmop * aop, int offset, bool bit16, bool dname)
1314 {
1315   //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1316 
1317   /* offset is greater than size then zero */
1318   if (offset > (aop->size - 1) && aop->type != AOP_LIT)
1319     return zero;
1320 
1321   /* depending on type */
1322   switch (aop->type)
1323     {
1324     case AOP_DIR:
1325       if (offset > 0)
1326         {
1327           SNPRINTF(buffer, sizeof(buffer), "(%s + %d)", aop->aopu.aop_dir, offset);
1328           DEBUGpic16_emitcode (";", "oops AOP_DIR did this %s\n", buffer);
1329           return Safe_strdup(buffer);
1330         }
1331       else
1332         return Safe_strdup(aop->aopu.aop_dir);
1333 
1334     case AOP_REG:
1335       return aop->aopu.aop_reg[offset]->name;
1336 
1337     case AOP_CRY:
1338       return aop->aopu.aop_dir;
1339 
1340     case AOP_ACC:
1341       DEBUGpic16_emitcode (";Warning -pic port ignoring get(AOP_ACC)", "%d\toffset: %d", __LINE__, offset);
1342 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1343 //        assert( 0 );
1344 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1345       return Safe_strdup("WREG");
1346 
1347     case AOP_LIT:
1348       SNPRINTF(buffer, sizeof(buffer), "0x%02x", pic16aopLiteral (aop->aopu.aop_lit, offset));
1349       return Safe_strdup(buffer);
1350 
1351     case AOP_STR:
1352       aop->coff = offset;
1353 
1354 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1355 //          dname)
1356 //          return "acc";
1357       if (!strcmp (aop->aopu.aop_str[offset], "WREG"))
1358         {
1359           aop->type = AOP_ACC;
1360           return Safe_strdup ("_WREG");
1361         }
1362       DEBUGpic16_emitcode (";", "%d - %s", __LINE__, aop->aopu.aop_str[offset]);
1363       return aop->aopu.aop_str[offset];
1364 
1365     case AOP_PCODE:
1366     {
1367       pCodeOp *pcop = aop->aopu.pcop;
1368       DEBUGpic16_emitcode (";", "%d: pic16_aopGet AOP_PCODE type %s", __LINE__, pic16_pCodeOpType (pcop));
1369       if (pcop->name)
1370         {
1371           DEBUGpic16_emitcode (";", "%s offset %d", pcop->name, PCOI (pcop)->offset);
1372           //SNPRINTF(buffer, sizeof(buffer), "(%s+0x%02x)", pcop->name, PCOI(aop->aopu.pcop)->offset);
1373           if (offset > 0)
1374             {
1375               SNPRINTF(buffer, sizeof(buffer), "(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1376             }
1377           else
1378             {
1379               SNPRINTF(buffer, sizeof(buffer), "%s", pic16_get_op (pcop, NULL, 0));
1380             }
1381         }
1382       else
1383         SNPRINTF(buffer, sizeof(buffer), "0x%02x", PCOI (aop->aopu.pcop)->offset);
1384 
1385     }
1386     return Safe_strdup(buffer);
1387 
1388 #if 0
1389     case AOP_PAGED:
1390       DEBUGpic16_emitcode (";", "oops AOP_PAGED did this %s\n", s);
1391       if (offset)
1392         {
1393           SNPRINTF(buffer, sizeof(buffer), "(%s + %d)", aop->aopu.aop_dir, offset);
1394         }
1395       else
1396         SNPRINTF(buffer, sizeof(buffer), "%s", aop->aopu.aop_dir);
1397       DEBUGpic16_emitcode (";", "oops AOP_PAGED did this %s\n", s);
1398       return Safe_strdup(buffer);
1399 #endif
1400 
1401     case AOP_STA:
1402       return Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1403 
1404     case AOP_STK:
1405 //        pCodeOp *pcop = aop->aop
1406       break;
1407 
1408     }
1409 
1410   fprintf (stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType (aop->type));
1411   werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "aopget got unsupported aop->type");
1412   exit (0);
1413 }
1414 
1415 
1416 
1417 /* lock has the following meaning: When allocating temporary registers
1418  * for stack variables storage, the value of the temporary register is
1419  * saved on stack. Its value is restored at the end. This procedure is
1420  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1421  * a possibility that before a call to pic16_aopOp, a temporary register
1422  * is allocated for a while and it is freed after some time, this will
1423  * mess the stack and values will not be restored properly. So use lock=1
1424  * to allocate temporary registers used internally by the programmer, and
1425  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1426  * to inform the compiler developer about a possible bug. This is an internal
1427  * feature for developing the compiler -- VR */
1428 
1429 int _TempReg_lock = 0;
1430 /*-----------------------------------------------------------------*/
1431 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1432 /*-----------------------------------------------------------------*/
1433 pCodeOp *
pic16_popGetTempReg(int lock)1434 pic16_popGetTempReg (int lock)
1435 {
1436   pCodeOp *pcop = NULL;
1437   symbol *cfunc;
1438 
1439 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1440   if (_TempReg_lock)
1441     {
1442 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1443     }
1444 
1445   _TempReg_lock += lock;
1446 
1447   cfunc = currFunc;
1448   currFunc = NULL;
1449 
1450   pcop = pic16_newpCodeOp (NULL, PO_GPR_TEMP);
1451   if (pcop && pcop->type == PO_GPR_TEMP && PCOR (pcop)->r)
1452     {
1453       PCOR (pcop)->r->wasUsed = 1;
1454       PCOR (pcop)->r->isFree = 0;
1455 
1456       /* push value on stack */
1457       pic16_pushpCodeOp (pic16_pCodeOpCopy (pcop));
1458     }
1459 
1460   currFunc = cfunc;
1461 
1462   return pcop;
1463 }
1464 
1465 /*-----------------------------------------------------------------*/
1466 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1467 /*                           is not part of f, but don't save if   */
1468 /*                           inside v                              */
1469 /*-----------------------------------------------------------------*/
1470 pCodeOp *
pic16_popGetTempRegCond(bitVect * f,bitVect * v,int lock)1471 pic16_popGetTempRegCond (bitVect * f, bitVect * v, int lock)
1472 {
1473   pCodeOp *pcop = NULL;
1474   symbol *cfunc;
1475   int i;
1476 
1477 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1478 
1479   if (_TempReg_lock)
1480     {
1481 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1482     }
1483 
1484   _TempReg_lock += lock;
1485 
1486   cfunc = currFunc;
1487   currFunc = NULL;
1488 
1489   i = bitVectFirstBit (f);
1490   while (i < 128)
1491     {
1492 
1493       /* bypass registers that are used by function */
1494       if (!bitVectBitValue (f, i))
1495         {
1496 
1497           /* bypass registers that are already allocated for stack access */
1498           if (!bitVectBitValue (v, i))
1499             {
1500 
1501 //          debugf("getting register rIdx = %d\n", i);
1502               /* ok, get the operand */
1503               pcop = pic16_newpCodeOpReg (i);
1504 
1505               /* should never by NULL */
1506               assert (pcop != NULL);
1507 
1508 
1509               /* sanity check */
1510               if (pcop && pcop->type == PO_GPR_TEMP && PCOR (pcop)->r)
1511                 {
1512                   int found = 0;
1513 
1514                   PCOR (pcop)->r->wasUsed = 1;
1515                   PCOR (pcop)->r->isFree = 0;
1516 
1517 
1518                   {
1519                     reg_info *sr;
1520 
1521                     for (sr = setFirstItem (_G.sregsAllocSet); sr; sr = setNextItem (_G.sregsAllocSet))
1522                       {
1523 
1524                         if (sr->rIdx == PCOR (pcop)->r->rIdx)
1525                           {
1526                             /* already used in previous steps, break */
1527                             found = 1;
1528                             break;
1529                           }
1530                       }
1531                   }
1532 
1533                   /* caller takes care of the following */
1534 //              bitVectSetBit(v, i);
1535 
1536                   if (!found)
1537                     {
1538                       /* push value on stack */
1539                       pic16_pushpCodeOp (pic16_pCodeOpCopy (pcop));
1540                       addSet (&_G.sregsAllocSet, PCOR (pcop)->r);
1541                     }
1542 
1543                   break;
1544                 }
1545             }
1546         }
1547       i++;
1548     }
1549 
1550   currFunc = cfunc;
1551 
1552   return pcop;
1553 }
1554 
1555 
1556 /*-----------------------------------------------------------------*/
1557 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1558 /*-----------------------------------------------------------------*/
1559 void
pic16_popReleaseTempReg(pCodeOp * pcop,int lock)1560 pic16_popReleaseTempReg (pCodeOp * pcop, int lock)
1561 {
1562   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
1563 
1564   _TempReg_lock -= lock;
1565 
1566   if (pcop && pcop->type == PO_GPR_TEMP && PCOR (pcop)->r)
1567     {
1568       PCOR (pcop)->r->isFree = 1;
1569 
1570       pic16_poppCodeOp (pic16_pCodeOpCopy (pcop));
1571     }
1572 }
1573 
1574 /*-----------------------------------------------------------------*/
1575 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1576 /*-----------------------------------------------------------------*/
1577 pCodeOp *
pic16_popGetLabel(int key)1578 pic16_popGetLabel (int key)
1579 {
1580 
1581   DEBUGpic16_emitcode ("; ***", "%s  key=%d, label offset %d", __FUNCTION__, key, pic16_labelOffset);
1582 
1583   if (key > max_key)
1584     max_key = key;
1585 
1586   return pic16_newpCodeOpLabel (NULL, labelKey2num (key + pic16_labelOffset));
1587 }
1588 
1589 /*-----------------------------------------------------------------*/
1590 /* pic16_popCopyReg - copy a pcode operator                              */
1591 /*-----------------------------------------------------------------*/
1592 pCodeOp *
pic16_popCopyReg(pCodeOpReg * pc)1593 pic16_popCopyReg (pCodeOpReg * pc)
1594 {
1595   pCodeOpReg *pcor;
1596 
1597   pcor = Safe_malloc(sizeof(pCodeOpReg));
1598   memcpy(pcor, pc, sizeof(pCodeOpReg));
1599   pcor->r->wasUsed = TRUE;
1600 
1601   //pcor->pcop.type = pc->pcop.type;
1602   if (pc->pcop.name)
1603     {
1604       if (!(pcor->pcop.name = Safe_strdup (pc->pcop.name)))
1605         fprintf (stderr, "oops %s %d", __FILE__, __LINE__);
1606     }
1607   else
1608     pcor->pcop.name = NULL;
1609 
1610   //pcor->r = pc->r;
1611   //pcor->rIdx = pc->rIdx;
1612   //pcor->r->wasUsed=1;
1613   //pcor->instance = pc->instance;
1614 
1615 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1616 
1617   return PCOP (pcor);
1618 }
1619 
1620 /*-----------------------------------------------------------------*/
1621 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1622 /*-----------------------------------------------------------------*/
1623 pCodeOp *
pic16_popGetLit(int lit)1624 pic16_popGetLit (int lit)
1625 {
1626   return pic16_newpCodeOpLit (lit);
1627 }
1628 
1629 /* Allow for 12 bit literals (LFSR x, <here!>). */
1630 pCodeOp *
pic16_popGetLit12(int lit)1631 pic16_popGetLit12 (int lit)
1632 {
1633   return pic16_newpCodeOpLit12 (lit);
1634 }
1635 
1636 /*-----------------------------------------------------------------*/
1637 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1638 /*-----------------------------------------------------------------*/
1639 pCodeOp *
pic16_popGetLit2(int lit,pCodeOp * arg2)1640 pic16_popGetLit2 (int lit, pCodeOp * arg2)
1641 {
1642   return pic16_newpCodeOpLit2 (lit, arg2);
1643 }
1644 
1645 
1646 /*-----------------------------------------------------------------*/
1647 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1648 /*-----------------------------------------------------------------*/
1649 pCodeOp *
pic16_popGetImmd(char * name,unsigned int offset,int index)1650 pic16_popGetImmd (char *name, unsigned int offset, int index)
1651 {
1652   return pic16_newpCodeOpImmd (name, offset, index, 0);
1653 }
1654 
1655 
1656 /*-----------------------------------------------------------------*/
1657 /* pic16_popGet - asm operator to pcode operator conversion              */
1658 /*-----------------------------------------------------------------*/
1659 pCodeOp *
pic16_popGetWithString(char * str)1660 pic16_popGetWithString (char *str)
1661 {
1662   pCodeOp *pcop;
1663 
1664 
1665   if (!str)
1666     {
1667       fprintf (stderr, "NULL string %s %d\n", __FILE__, __LINE__);
1668       exit (1);
1669     }
1670 
1671   pcop = pic16_newpCodeOp (str, PO_STR);
1672 
1673   return pcop;
1674 }
1675 
1676 /*-----------------------------------------------------------------*/
1677 /* pic16_popRegFromString -                                        */
1678 /*-----------------------------------------------------------------*/
1679 static pCodeOp *
pic16_popRegFromString(char * str,int size,int offset,operand * op)1680 pic16_popRegFromString (char *str, int size, int offset, operand * op)
1681 {
1682 
1683   pCodeOp *pcop = Safe_alloc(sizeof(pCodeOpReg));
1684   pcop->type = PO_DIR;
1685 
1686   DEBUGpic16_emitcode (";", "%d %s %s %d/%d", __LINE__, __FUNCTION__, str, size, offset);       // patch 14
1687   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1688 
1689   if (!str)
1690     str = "BAD_STRING";
1691 
1692   pcop->name = Safe_strdup(str);
1693 
1694   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1695 
1696   PCOR (pcop)->r = pic16_dirregWithName (pcop->name);
1697 //  PCOR(pcop)->r->wasUsed = 1;
1698 
1699   /* make sure that register doesn't exist,
1700    * and operand isn't NULL
1701    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1702   if ((PCOR (pcop)->r == NULL) && (op) && !IN_CODESPACE (SPEC_OCLS (OP_SYM_ETYPE (op))))
1703     {
1704 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1705 //              __FUNCTION__, __LINE__, str, size, offset);
1706 
1707       PCOR (pcop)->r = pic16_allocRegByName (pcop->name, size, op);
1708       //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1709 
1710     }
1711   PCOR (pcop)->instance = offset;
1712 
1713   return pcop;
1714 }
1715 
1716 static pCodeOp *
pic16_popRegFromIdx(int rIdx)1717 pic16_popRegFromIdx (int rIdx)
1718 {
1719   pCodeOp *pcop;
1720 
1721 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1722 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1723 
1724   pcop = Safe_alloc(sizeof(pCodeOpReg));
1725   PCOR (pcop)->rIdx = rIdx;
1726   PCOR (pcop)->r = pic16_regWithIdx (rIdx);
1727   if (!PCOR (pcop)->r)
1728     PCOR (pcop)->r = pic16_allocWithIdx (rIdx);
1729 
1730   PCOR (pcop)->r->isFree = 0;
1731   PCOR (pcop)->r->wasUsed = 1;
1732 
1733   pcop->type = PCOR (pcop)->r->pc_type;
1734 
1735   return pcop;
1736 }
1737 
1738 /*---------------------------------------------------------------------------------*/
1739 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1740 /*                 VR 030601                                                       */
1741 /*---------------------------------------------------------------------------------*/
1742 pCodeOp *
pic16_popGet2(asmop * aop_src,asmop * aop_dst,int offset)1743 pic16_popGet2 (asmop * aop_src, asmop * aop_dst, int offset)
1744 {
1745   pCodeOp2 *pcop2 = (pCodeOp2 *) pic16_newpCodeOp2 (pic16_popGet (aop_src, offset), pic16_popGet (aop_dst, offset));
1746   return PCOP (pcop2);
1747 }
1748 
1749 /*--------------------------------------------------------------------------------.-*/
1750 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1751 /*                  VR 030601 , adapted by Hans Dorn                                */
1752 /*--------------------------------------------------------------------------------.-*/
1753 pCodeOp *
pic16_popGet2p(pCodeOp * src,pCodeOp * dst)1754 pic16_popGet2p (pCodeOp * src, pCodeOp * dst)
1755 {
1756   pCodeOp2 *pcop2;
1757   pcop2 = (pCodeOp2 *) pic16_newpCodeOp2 (src, dst);
1758   return PCOP (pcop2);
1759 }
1760 
1761 /*---------------------------------------------------------------------------------*/
1762 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1763 /*                     movff instruction                                           */
1764 /*---------------------------------------------------------------------------------*/
1765 pCodeOp *
pic16_popCombine2(pCodeOpReg * src,pCodeOpReg * dst,int noalloc)1766 pic16_popCombine2 (pCodeOpReg * src, pCodeOpReg * dst, int noalloc)
1767 {
1768   pCodeOp2 *pcop2 = (pCodeOp2 *) pic16_newpCodeOp2 (pic16_popCopyReg (src), pic16_popCopyReg (dst));
1769 
1770   return PCOP (pcop2);
1771 }
1772 
1773 /*-----------------------------------------------------------------*/
1774 /* pic16_popGet - asm operator to pcode operator conversion              */
1775 /*-----------------------------------------------------------------*/
1776 pCodeOp *
pic16_popGet(asmop * aop,int offset)1777 pic16_popGet (asmop * aop, int offset)  //, bool bit16, bool dname)
1778 {
1779 //  char *s = buffer ;
1780 //  char *rs;
1781   pCodeOp *pcop;
1782 
1783   FENTRY2;
1784 
1785   /* offset is greater than size then zero */
1786 
1787 //    if (offset > (aop->size - 1) &&
1788 //        aop->type != AOP_LIT)
1789 //      return NULL;  //zero;
1790 
1791   /* depending on type */
1792   switch (aop->type)
1793     {
1794     case AOP_STA:
1795       /* pCodeOp is already allocated from aopForSym */
1796       DEBUGpic16_emitcode (";---", "%d getting stack + offset %d\n", __LINE__, offset);
1797       pcop = pic16_pCodeOpCopy (aop->aopu.stk.pop[offset]);
1798       return (pcop);
1799 
1800     case AOP_ACC:
1801     {
1802       int rIdx = IDX_WREG;    //aop->aopu.aop_reg[offset]->rIdx;
1803 
1804 //      fprintf (stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1805 
1806       DEBUGpic16_emitcode (";", "%d\tAOP_ACC", __LINE__);
1807 
1808       pcop = Safe_alloc(sizeof(pCodeOpReg));
1809       PCOR (pcop)->rIdx = rIdx;
1810       PCOR (pcop)->r = pic16_typeRegWithIdx (rIdx, REG_SFR, 1);       // pic16_regWithIdx(rIdx);
1811       PCOR (pcop)->r->wasUsed = 1;
1812       PCOR (pcop)->r->isFree = 0;
1813 
1814       PCOR (pcop)->instance = offset;
1815       pcop->type = PCOR (pcop)->r->pc_type;
1816 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1817       return pcop;
1818 
1819 
1820 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1821 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1822 
1823 //      assert( 0 );
1824     }
1825 
1826     case AOP_DIR:
1827       DEBUGpic16_emitcode (";", "%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
1828       return pic16_popRegFromString (aop->aopu.aop_dir, aop->size, offset, NULL);
1829 
1830 #if 0
1831     case AOP_PAGED:
1832       DEBUGpic16_emitcode (";", "%d\tAOP_DIR", __LINE__);
1833       return pic16_popRegFromString (aop->aopu.aop_dir, aop->size, offset, NULL);
1834 #endif
1835 
1836     case AOP_REG:
1837     {
1838       int rIdx;
1839 
1840 //      debugf2("aop = %p\toffset = %d\n", aop, offset);
1841 //      assert (aop && aop->aopu.aop_reg[offset] != NULL);
1842       rIdx = aop->aopu.aop_reg[offset]->rIdx;
1843 
1844       DEBUGpic16_emitcode (";", "%d\tAOP_REG", __LINE__);
1845 
1846       pcop = Safe_alloc(sizeof(pCodeOpReg));
1847 //      pcop->type = PO_GPR_REGISTER;
1848       PCOR (pcop)->rIdx = rIdx;
1849       PCOR (pcop)->r = pic16_allocWithIdx (rIdx);     //pic16_regWithIdx(rIdx);
1850       PCOR (pcop)->r->wasUsed = 1;
1851       PCOR (pcop)->r->isFree = 0;
1852 
1853       PCOR (pcop)->instance = offset;
1854       pcop->type = PCOR (pcop)->r->pc_type;
1855 
1856       DEBUGpic16_emitcode (";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype (pcop->type));
1857 //      rs = aop->aopu.aop_reg[offset]->name;
1858 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1859       return pcop;
1860     }
1861 
1862     case AOP_CRY:
1863       DEBUGpic16_emitcode (";", "%d\tAOP_CRY", __LINE__);
1864 
1865       pcop = pic16_newpCodeOpBit (aop->aopu.aop_dir, -1, 1, PO_GPR_REGISTER);
1866       PCOR (pcop)->instance = offset;
1867       PCOR (pcop)->r = pic16_dirregWithName (aop->aopu.aop_dir);
1868       //if(PCOR(pcop)->r == NULL)
1869       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1870       return pcop;
1871 
1872     case AOP_LIT:
1873       DEBUGpic16_emitcode (";", "%d\tAOP_LIT", __LINE__);
1874       return pic16_newpCodeOpLit (pic16aopLiteral (aop->aopu.aop_lit, offset));
1875 
1876     case AOP_STR:
1877       DEBUGpic16_emitcode (";", "%d AOP_STR %s", __LINE__, aop->aopu.aop_str[offset]);
1878       return pic16_newpCodeOpRegFromStr (aop->aopu.aop_str[offset]);
1879 
1880       /*
1881          pcop = Safe_alloc(sizeof(pCodeOpReg));
1882          PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1883          PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1884          pcop->type = PCOR(pcop)->r->pc_type;
1885          pcop->name = PCOR(pcop)->r->name;
1886 
1887          return pcop;
1888        */
1889 
1890     case AOP_PCODE:
1891       DEBUGpic16_emitcode (";", "pic16_popGet AOP_PCODE (%s) %d %s offset %d", pic16_pCodeOpType (aop->aopu.pcop),
1892                            __LINE__, ((aop->aopu.pcop->name) ? (aop->aopu.pcop->name) : "no name"), offset);
1893       pcop = pic16_pCodeOpCopy (aop->aopu.pcop);
1894       switch (aop->aopu.pcop->type)
1895         {
1896         case PO_DIR:
1897           PCOR (pcop)->instance += offset;
1898           break;
1899         case PO_IMMEDIATE:
1900           PCOI (pcop)->offset = offset;
1901           break;
1902         case PO_WREG:
1903           assert (offset == 0);
1904           break;
1905         default:
1906           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
1907           assert (0); /* should never reach here */ ;
1908         }
1909       return pcop;
1910     }
1911 
1912   werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "pic16_popGet got unsupported aop->type");
1913   exit (0);
1914 }
1915 
1916 /*-------------------------------------------------------------------------*/
1917 /* pic16_popGetImmed - immediate asm operator to pcode operator conversion */
1918 /*-------------------------------------------------------------------------*/
1919 static pCodeOp *
pic16_popGetImmed(asmop * aop,int offset,int overload)1920 pic16_popGetImmed(asmop *aop, int offset, int overload)
1921 {
1922   pCodeOp *pcop;
1923 
1924   FENTRY2;
1925 
1926   if (aop->type == AOP_PCODE)
1927     {
1928       if (aop->aopu.pcop->type == PO_IMMEDIATE)
1929         {
1930           pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1931           PCOI(pcop)->offset = offset;  // offset: "LOW", "HIGH", "UPPER"
1932           PCOI(pcop)->index += overload;  // LOW(ptr + index + overload)
1933           return pcop;
1934         }
1935 
1936       fprintf(stderr, "%s: Only handled PO_IMMEDIATE.\n", __FUNCTION__);
1937       assert(0);
1938     }
1939 
1940   werror(E_INTERNAL_ERROR, __FILE__, __LINE__, "pic16_popGetImmed supported only AOP_PCODE.");
1941   exit(0);
1942 }
1943 
1944 /*-----------------------------------------------------------------*/
1945 /* pic16_aopPut - puts a string for a aop                                */
1946 /*-----------------------------------------------------------------*/
1947 void
pic16_aopPut(asmop * aop,char * s,int offset)1948 pic16_aopPut (asmop * aop, char *s, int offset)
1949 {
1950   symbol *lbl;
1951 
1952   return;
1953 
1954   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
1955 
1956   if (aop->size && offset > (aop->size - 1))
1957     {
1958       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "pic16_aopPut got offset > aop->size");
1959       exit (0);
1960     }
1961 
1962   /* will assign value to value */
1963   /* depending on where it is ofcourse */
1964   switch (aop->type)
1965     {
1966     case AOP_DIR:
1967       if (offset > 0)
1968         {
1969           SNPRINTF(buffer, sizeof(buffer), "(%s + %d)", aop->aopu.aop_dir, offset);
1970           fprintf (stderr, "oops pic16_aopPut:AOP_DIR did this %s\n", s);
1971         }
1972       else
1973         SNPRINTF(buffer, sizeof(buffer), "%s", aop->aopu.aop_dir);
1974 
1975       if (strcmp(buffer, s))
1976         {
1977           DEBUGpic16_emitcode (";", "%d", __LINE__);
1978           if (strcmp (s, "W"))
1979             pic16_emitcode ("movf", "%s,w", s);
1980 
1981           pic16_emitcode ("movwf", "%s", buffer);
1982 
1983           if (strcmp (s, "W"))
1984             {
1985               pic16_emitcode (";BUG!? should have this:movf", "%s,w   %d", s, __LINE__);
1986               if (offset >= aop->size)
1987                 {
1988                   pic16_emitpcode (POC_CLRF, pic16_popGet (aop, offset));
1989                   break;
1990                 }
1991               else
1992                 pic16_emitpcode (POC_MOVLW, pic16_popGetImmd (s, offset, 0));
1993             }
1994 
1995           pic16_emitpcode (POC_MOVWF, pic16_popGet (aop, offset));
1996 
1997 
1998         }
1999       break;
2000 
2001     case AOP_REG:
2002       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0)     // &&
2003         {
2004           //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2005           /*
2006              if (*s == '@'           ||
2007              strcmp(s,"r0") == 0 ||
2008              strcmp(s,"r1") == 0 ||
2009              strcmp(s,"r2") == 0 ||
2010              strcmp(s,"r3") == 0 ||
2011              strcmp(s,"r4") == 0 ||
2012              strcmp(s,"r5") == 0 ||
2013              strcmp(s,"r6") == 0 ||
2014              strcmp(s,"r7") == 0 )
2015              pic16_emitcode("mov","%s,%s  ; %d",
2016              aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2017              else
2018            */
2019 
2020           if (strcmp (s, "W") == 0)
2021             pic16_emitcode ("movf", "%s,w  ; %d", s, __LINE__);
2022 
2023           pic16_emitcode ("movwf", "%s", aop->aopu.aop_reg[offset]->name);
2024 
2025           if (strcmp (s, zero) == 0)
2026             {
2027               pic16_emitpcode (POC_CLRF, pic16_popGet (aop, offset));
2028 
2029             }
2030           else if (strcmp (s, "W") == 0)
2031             {
2032               pCodeOp *pcop = Safe_alloc(sizeof(pCodeOpReg));
2033               pcop->type = PO_GPR_REGISTER;
2034 
2035               PCOR (pcop)->rIdx = -1;
2036               PCOR (pcop)->r = NULL;
2037 
2038               DEBUGpic16_emitcode (";", "%d", __LINE__);
2039               pcop->name = Safe_strdup (s);
2040               pic16_emitpcode (POC_MOVFW, pcop);
2041               pic16_emitpcode (POC_MOVWF, pic16_popGet (aop, offset));
2042             }
2043           else if (strcmp (s, one) == 0)
2044             {
2045               pic16_emitpcode (POC_CLRF, pic16_popGet (aop, offset));
2046               pic16_emitpcode (POC_INCF, pic16_popGet (aop, offset));
2047             }
2048           else
2049             {
2050               pic16_emitpcode (POC_MOVWF, pic16_popGet (aop, offset));
2051             }
2052         }
2053       break;
2054 
2055     case AOP_STK:
2056       if (strcmp (s, "a") == 0)
2057         pic16_emitcode ("push", "acc");
2058       else
2059         pic16_emitcode ("push", "%s", s);
2060       break;
2061 
2062     case AOP_CRY:
2063       /* if bit variable */
2064       if (!aop->aopu.aop_dir)
2065         {
2066           pic16_emitcode ("clr", "a");
2067           pic16_emitcode ("rlc", "a");
2068         }
2069       else
2070         {
2071           if (s == zero)
2072             pic16_emitcode ("clr", "%s", aop->aopu.aop_dir);
2073           else if (s == one)
2074             pic16_emitcode ("setb", "%s", aop->aopu.aop_dir);
2075           else if (!strcmp (s, "c"))
2076             pic16_emitcode ("mov", "%s,c", aop->aopu.aop_dir);
2077           else
2078             {
2079               lbl = newiTempLabel (NULL);
2080 
2081               if (strcmp (s, "a"))
2082                 {
2083                   MOVA (s);
2084                 }
2085               pic16_emitcode ("clr", "c");
2086               pic16_emitcode ("jz", "%05d_DS_", labelKey2num (lbl->key));
2087               pic16_emitcode ("cpl", "c");
2088               pic16_emitcode ("", "%05d_DS_:", labelKey2num (lbl->key));
2089               pic16_emitcode ("mov", "%s,c", aop->aopu.aop_dir);
2090             }
2091         }
2092       break;
2093 
2094     case AOP_STR:
2095       aop->coff = offset;
2096       if (strcmp (aop->aopu.aop_str[offset], s))
2097         pic16_emitcode ("mov", "%s,%s ; %d", aop->aopu.aop_str[offset], s, __LINE__);
2098       break;
2099 
2100     case AOP_ACC:
2101       aop->coff = offset;
2102       if (!offset && (strcmp (s, "acc") == 0))
2103         break;
2104 
2105       if (strcmp (aop->aopu.aop_str[offset], s))
2106         pic16_emitcode ("mov", "%s,%s ; %d", aop->aopu.aop_str[offset], s, __LINE__);
2107       break;
2108 
2109     default:
2110       fprintf (stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2111 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2112 //             "pic16_aopPut got unsupported aop->type");
2113 //      exit(0);
2114     }
2115 
2116 }
2117 
2118 /*-----------------------------------------------------------------*/
2119 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2120 /*-----------------------------------------------------------------*/
2121 void
pic16_mov2w(asmop * aop,int offset)2122 pic16_mov2w (asmop * aop, int offset)
2123 {
2124   int isWREG = (aop->type != AOP_STA && ! strcmp (pic16_aopGet(aop, 0, TRUE, FALSE), "WREG"));
2125 
2126   DEBUGpic16_emitcode ("; ***", "%s  %d  offset=%d", __FUNCTION__, __LINE__, offset);
2127 
2128   if (pic16_isLitAop (aop))
2129     pic16_emitpcode (POC_MOVLW, pic16_popGet (aop, offset));
2130   else if (isWREG)
2131     DEBUGpic16_emitcode ("; ***", "ignore MOVF\tWREG, W", __FUNCTION__, __LINE__);
2132   else
2133     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
2134 }
2135 
2136 void
pic16_mov2w_volatile(asmop * aop)2137 pic16_mov2w_volatile (asmop * aop)
2138 {
2139   int i;
2140 
2141   if (!pic16_isLitAop (aop))
2142     {
2143       // may need to protect this from the peepholer -- this is not nice but works...
2144       pic16_addpCode2pBlock (pb, pic16_newpCodeAsmDir (";", "VOLATILE READ - BEGIN"));
2145       for (i = 0; i < aop->size; i++)
2146         {
2147           if (i > 0)
2148             {
2149               pic16_addpCode2pBlock (pb, pic16_newpCodeAsmDir (";", "VOLATILE READ - MORE"));
2150             }                   // if
2151           pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, i));
2152         }                       // for
2153       pic16_addpCode2pBlock (pb, pic16_newpCodeAsmDir (";", "VOLATILE READ - END"));
2154     }
2155 }
2156 
2157 void
pic16_mov2f(asmop * dst,asmop * src,int offset)2158 pic16_mov2f (asmop * dst, asmop * src, int offset)
2159 {
2160   if (pic16_isLitAop (src))
2161     {
2162       int dstIsWREG = (dst->type != AOP_STA && ! strcmp(pic16_aopGet(dst, 0, TRUE, FALSE), "WREG"));
2163 
2164       pic16_emitpcode (POC_MOVLW, pic16_popGet (src, offset));
2165 
2166       if (! dstIsWREG)
2167         {
2168           pic16_emitpcode (POC_MOVWF, pic16_popGet(dst, offset));
2169         }
2170     }
2171   else
2172     {
2173       int srcIsWREG;
2174 
2175       if (pic16_sameRegsOfs (src, dst, offset))
2176         return;
2177 
2178       srcIsWREG = (src->type != AOP_STA && ! strcmp (pic16_aopGet (src, 0, TRUE, FALSE), "WREG"));
2179 
2180       if (srcIsWREG)
2181         {
2182           pic16_emitpcode (POC_MOVWF, pic16_popGet (dst, offset));
2183         }
2184       else
2185         {
2186           int dstIsINTCON = (src->type != AOP_STA && ! strcmp (pic16_aopGet(src, 0, TRUE, FALSE), "INTCON"));
2187           int dstIsPCL = (src->type != AOP_STA && ! strcmp (pic16_aopGet(src, 0, TRUE, FALSE), "PCL"));
2188 
2189           if (dstIsINTCON || dstIsPCL)
2190             {
2191               pic16_emitpcode (POC_MOVFW, pic16_popGet (src, offset));
2192               pic16_emitpcode (POC_MOVWF, pic16_popGet (dst, offset));
2193             }
2194           else
2195             {
2196               pic16_emitpcode(POC_MOVFF, pic16_popGet2p (pic16_popGet (src, offset),
2197                               pic16_popGet (dst, offset)));
2198             }
2199         }
2200     }
2201 }
2202 
2203 static void
pic16_movLit2f(pCodeOp * pc,int lit)2204 pic16_movLit2f (pCodeOp * pc, int lit)
2205 {
2206   if (0 == (lit & 0x00ff))
2207     {
2208       pic16_emitpcode (POC_CLRF, pc);
2209     }
2210   else if (0xff == (lit & 0x00ff))
2211     {
2212       pic16_emitpcode (POC_SETF, pc);
2213     }
2214   else
2215     {
2216       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2217       if (pc->type != PO_WREG)
2218         pic16_emitpcode (POC_MOVWF, pc);
2219     }
2220 }
2221 
2222 static void
mov2fp(pCodeOp * dst,asmop * src,int offset)2223 mov2fp (pCodeOp * dst, asmop * src, int offset)
2224 {
2225   if (pic16_isLitAop (src))
2226     {
2227       pic16_emitpcode (POC_MOVLW, pic16_popGet (src, offset));
2228 
2229       if (dst->type != PO_WREG)
2230         {
2231           pic16_emitpcode (POC_MOVWF, dst);
2232         }
2233     }
2234   else
2235     {
2236       if (dst->type == PO_INTCON || dst->type == PO_PCL)
2237         {
2238           pic16_emitpcode (POC_MOVFW, pic16_popGet (src, offset));
2239           pic16_emitpcode (POC_MOVWF, dst);
2240         }
2241       else
2242         {
2243           pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popGet (src, offset), dst));
2244         }
2245     }
2246 }
2247 
2248 void
pic16_testStackOverflow(void)2249 pic16_testStackOverflow (void)
2250 {
2251 #define GSTACK_TEST_NAME        "_gstack_test"
2252 
2253   pic16_emitpcode (POC_CALL, pic16_popGetWithString (GSTACK_TEST_NAME));
2254 
2255   {
2256     symbol *sym;
2257 
2258     sym = newSymbol (GSTACK_TEST_NAME, 0);
2259     SNPRINTF(sym->rname, sizeof(sym->rname), "%s", /*port->fun_prefix, */ GSTACK_TEST_NAME);
2260 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2261     checkAddSym (&externs, sym);
2262   }
2263 }
2264 
2265 /* push pcop into stack */
2266 void
pic16_pushpCodeOp(pCodeOp * pcop)2267 pic16_pushpCodeOp (pCodeOp * pcop)
2268 {
2269 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2270   if (pcop->type == PO_LITERAL)
2271     {
2272       pic16_emitpcode (POC_MOVLW, pcop);
2273       pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec));
2274     }
2275   else
2276     {
2277       pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pcop, pic16_popCopyReg (pic16_stack_postdec)));
2278     }
2279 
2280   if (pic16_options.gstack)
2281     pic16_testStackOverflow ();
2282 }
2283 
2284 /* pop pcop from stack */
2285 void
pic16_poppCodeOp(pCodeOp * pcop)2286 pic16_poppCodeOp (pCodeOp * pcop)
2287 {
2288   pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg (pic16_stack_preinc), pcop));
2289   if (pic16_options.gstack)
2290     pic16_testStackOverflow ();
2291 }
2292 
2293 
2294 /*-----------------------------------------------------------------*/
2295 /* pushw - pushes wreg to stack                                    */
2296 /*-----------------------------------------------------------------*/
2297 void
pushw(void)2298 pushw (void)
2299 {
2300   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
2301   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec));
2302   if (pic16_options.gstack)
2303     pic16_testStackOverflow ();
2304 }
2305 
2306 
2307 /*-----------------------------------------------------------------*/
2308 /* pushaop - pushes aop to stack                                   */
2309 /*-----------------------------------------------------------------*/
2310 void
pushaop(asmop * aop,int offset)2311 pushaop (asmop * aop, int offset)
2312 {
2313   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
2314 
2315   if (_G.resDirect)
2316     return;
2317 
2318   if (pic16_isLitAop (aop))
2319     {
2320       pic16_emitpcode (POC_MOVLW, pic16_popGet (aop, offset));
2321       pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec));
2322     }
2323   else
2324     {
2325       pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popGet (aop, offset), pic16_popCopyReg (pic16_stack_postdec)));
2326     }
2327 
2328   if (pic16_options.gstack)
2329     pic16_testStackOverflow ();
2330 }
2331 
2332 /*-----------------------------------------------------------------*/
2333 /* popaop - pops aop from stack                                    */
2334 /*-----------------------------------------------------------------*/
2335 void
popaop(asmop * aop,int offset)2336 popaop (asmop * aop, int offset)
2337 {
2338   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
2339   pic16_emitpcode (POC_MOVFF, pic16_popCombine2 (pic16_stack_preinc, PCOR (pic16_popGet (aop, offset)), 0));
2340   if (pic16_options.gstack)
2341     pic16_testStackOverflow ();
2342 }
2343 
2344 void
popaopidx(asmop * aop,int offset,int index)2345 popaopidx (asmop * aop, int offset, int index)
2346 {
2347   int ofs = 1;
2348 
2349   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
2350 
2351   if (STACK_MODEL_LARGE)
2352     ofs++;
2353 
2354   pic16_emitpcode (POC_MOVLW, pic16_popGetLit (index + ofs));
2355   pic16_emitpcode (POC_MOVFF, pic16_popCombine2 (pic16_frame_plusw, PCOR (pic16_popGet (aop, offset)), 0));
2356   if (pic16_options.gstack)
2357     pic16_testStackOverflow ();
2358 }
2359 
2360 /*-----------------------------------------------------------------*/
2361 /* pic16_getDataSize - get the operand data size                         */
2362 /*-----------------------------------------------------------------*/
2363 int
pic16_getDataSize(operand * op)2364 pic16_getDataSize (operand * op)
2365 {
2366   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
2367 
2368 
2369   return AOP_SIZE (op);
2370 
2371   // tsd- in the pic port, the genptr size is 1, so this code here
2372   // fails. ( in the 8051 port, the size was 4).
2373 #if 0
2374   int size;
2375   size = AOP_SIZE (op);
2376   if (size == GPTRSIZE)
2377     {
2378       sym_link *type = operandType (op);
2379       if (IS_GENPTR (type))
2380         {
2381           /* generic pointer; arithmetic operations
2382            * should ignore the high byte (pointer type).
2383            */
2384           size--;
2385           DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
2386         }
2387     }
2388   return size;
2389 #endif
2390 }
2391 
2392 /*-----------------------------------------------------------------*/
2393 /* pic16_outAcc - output Acc                                             */
2394 /*-----------------------------------------------------------------*/
2395 void
pic16_outAcc(operand * result)2396 pic16_outAcc (operand * result)
2397 {
2398   int size, offset;
2399   DEBUGpic16_emitcode ("; ***", "%s  %d - ", __FUNCTION__, __LINE__);
2400   DEBUGpic16_pic16_AopType (__LINE__, NULL, NULL, result);
2401 
2402 
2403   size = pic16_getDataSize (result);
2404   if (size)
2405     {
2406       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
2407       size--;
2408       offset = 1;
2409       /* unsigned or positive */
2410       while (size--)
2411         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offset++));
2412     }
2413 
2414 }
2415 
2416 /*-----------------------------------------------------------------*/
2417 /* pic16_outBitC - output a bit C                                  */
2418 /*                 Move to result the value of Carry flag -- VR    */
2419 /*-----------------------------------------------------------------*/
2420 void
pic16_outBitC(operand * result)2421 pic16_outBitC (operand * result)
2422 {
2423   int i;
2424 
2425   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
2426 
2427   /* if the result is bit */
2428   if (AOP_TYPE (result) == AOP_CRY)
2429     {
2430       fprintf (stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2431       pic16_aopPut (AOP (result), "c", 0);
2432     }
2433   else
2434     {
2435 
2436       i = AOP_SIZE (result);
2437       while (i--)
2438         {
2439           pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), i));
2440         }
2441       pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), 0));
2442     }
2443 }
2444 
2445 /*-----------------------------------------------------------------*/
2446 /* pic16_outBitOp - output a bit from Op                           */
2447 /*                 Move to result the value of set/clr op -- VR    */
2448 /*-----------------------------------------------------------------*/
2449 void
pic16_outBitOp(operand * result,pCodeOp * pcop)2450 pic16_outBitOp (operand * result, pCodeOp * pcop)
2451 {
2452   int i;
2453 
2454   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
2455 
2456   /* if the result is bit */
2457   if (AOP_TYPE (result) == AOP_CRY)
2458     {
2459       fprintf (stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2460       pic16_aopPut (AOP (result), "c", 0);
2461     }
2462   else
2463     {
2464 
2465       i = AOP_SIZE (result);
2466       while (i--)
2467         {
2468           pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), i));
2469         }
2470       pic16_emitpcode (POC_RRCF, pcop);
2471       pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), 0));
2472     }
2473 }
2474 
2475 /*-----------------------------------------------------------------*/
2476 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2477 /*-----------------------------------------------------------------*/
2478 void
pic16_toBoolean(operand * oper)2479 pic16_toBoolean (operand * oper)
2480 {
2481   int size = AOP_SIZE (oper) - 1;
2482   int offset = 1;
2483 
2484   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
2485 
2486   if (AOP_TYPE (oper) != AOP_ACC)
2487     {
2488       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (oper), 0));
2489     }
2490   while (size--)
2491     {
2492       pic16_emitpcode (POC_IORFW, pic16_popGet (AOP (oper), offset++));
2493     }
2494 }
2495 
2496 /*-----------------------------------------------------------------*/
2497 /* genUminusFloat - unary minus for floating points                */
2498 /*-----------------------------------------------------------------*/
2499 static void
genUminusFloat(operand * op,operand * result)2500 genUminusFloat (operand * op, operand * result)
2501 {
2502   int size, offset = 0;
2503 
2504   FENTRY;
2505   /* for this we just need to flip the
2506      first it then copy the rest in place */
2507   size = AOP_SIZE (op);
2508   assert (size == AOP_SIZE (result));
2509 
2510   while (size--)
2511     {
2512       pic16_mov2f (AOP (result), AOP (op), offset);
2513       offset++;
2514     }
2515 
2516   /* toggle the MSB's highest bit */
2517   pic16_emitpcode (POC_BTG, pic16_popCopyGPR2Bit (pic16_popGet (AOP (result), offset - 1), 7));
2518 }
2519 
2520 /*-----------------------------------------------------------------*/
2521 /* genUminus - unary minus code generation                         */
2522 /*-----------------------------------------------------------------*/
2523 static void
genUminus(iCode * ic)2524 genUminus (iCode * ic)
2525 {
2526   int lsize, rsize, i;
2527   sym_link *optype;
2528   symbol *label;
2529   int needLabel = 0;
2530 
2531   FENTRY;
2532 
2533   /* assign asmops */
2534   pic16_aopOp (IC_LEFT (ic), ic, FALSE);
2535   pic16_aopOp (IC_RESULT (ic), ic, TRUE);
2536 
2537   /* if both in bit space then special case */
2538   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY && AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2539     {
2540 
2541       pic16_emitpcode (POC_BCF, pic16_popGet (AOP (IC_RESULT (ic)), 0));
2542       pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP (IC_LEFT (ic)), 0));
2543       pic16_emitpcode (POC_BSF, pic16_popGet (AOP (IC_RESULT (ic)), 0));
2544       goto release;
2545     }
2546 
2547   optype = operandType (IC_LEFT (ic));
2548 
2549   /* if float then do float stuff */
2550   if (IS_FLOAT (optype) || IS_FIXED (optype))
2551     {
2552       if (IS_FIXED (optype))
2553         debugf ("implement fixed16x16 type\n", 0);
2554 
2555       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2556       goto release;
2557     }
2558 
2559   /* otherwise subtract from zero by taking the 2's complement */
2560   lsize = AOP_SIZE (IC_LEFT (ic));
2561   rsize = AOP_SIZE (IC_RESULT (ic));
2562   label = newiTempLabel (NULL);
2563 
2564   if (pic16_sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2565     {
2566       /* If the result is longer than the operand,
2567          store sign extension (0x00 or 0xff) in W */
2568       if (rsize > lsize)
2569         {
2570           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0x00));
2571           pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet (AOP (IC_LEFT (ic)), lsize - 1), 7));
2572           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
2573         }
2574       for (i = rsize - 1; i > 0; --i)
2575         {
2576           if (i > lsize - 1)
2577             {
2578               pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (IC_RESULT (ic)), i));
2579             }
2580           else
2581             {
2582               pic16_emitpcode (POC_COMF, pic16_popGet (AOP (IC_RESULT (ic)), i));
2583             }                   // if
2584         }                       // for
2585       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP (IC_RESULT (ic)), 0));
2586       for (i = 1; i < rsize; ++i)
2587         {
2588           if (i == rsize - 1)
2589             {
2590               emitSKPNZ;
2591             }
2592           else
2593             {
2594               pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key));
2595               needLabel++;
2596             }
2597           pic16_emitpcode (POC_INCF, pic16_popGet (AOP (IC_RESULT (ic)), i));
2598         }                       // for
2599     }
2600   else
2601     {
2602       for (i = min (rsize, lsize) - 1; i >= 0; i--)
2603         {
2604           pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (IC_LEFT (ic)), i));
2605           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (IC_RESULT (ic)), i));
2606         }                       // for
2607       /* Sign extend if the result is longer than the operand */
2608       if (rsize > lsize)
2609         {
2610           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0x00));
2611           pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (pic16_popGet (AOP (IC_RESULT (ic)), lsize - 1), 7));
2612           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
2613           for (i = rsize - 1; i > lsize - 1; --i)
2614             {
2615               pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (IC_RESULT (ic)), i));
2616             }                   // for
2617         }                       // if
2618       if (rsize > 1)
2619         {
2620           for (i = 0; i < rsize - 2; i++)
2621             {
2622               pic16_emitpcode (POC_INCF, pic16_popGet (AOP (IC_RESULT (ic)), i));
2623               pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key));
2624               needLabel++;
2625             }                   // for
2626           pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP (IC_RESULT (ic)), rsize - 2));
2627         }                       // if
2628       pic16_emitpcode (POC_INCF, pic16_popGet (AOP (IC_RESULT (ic)), rsize - 1));
2629     }
2630   if (needLabel)
2631     pic16_emitpLabel (label->key);
2632 
2633 release:
2634   /* release the aops */
2635   pic16_freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2636   pic16_freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2637 }
2638 
2639 void
pic16_loadFromReturn(operand * op,int offset,pCodeOp * src)2640 pic16_loadFromReturn (operand * op, int offset, pCodeOp * src)
2641 {
2642   if ((AOP (op)->type == AOP_PCODE) && (AOP (op)->aopu.pcop->type == PO_IMMEDIATE))
2643     {
2644       pic16_emitpcode (POC_MOVFW, src);
2645       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (op), offset));
2646     }
2647   else
2648     {
2649       pic16_emitpcode (POC_MOVFF, pic16_popGet2p (src, pic16_popGet (AOP (op), offset)));
2650     }
2651 }
2652 
2653 /*-----------------------------------------------------------------*/
2654 
2655 static void
free_stack_parameters(int Parameter_count)2656 free_stack_parameters (int Parameter_count)
2657 {
2658   if (Parameter_count < 1)
2659     {
2660       return;
2661     }
2662 
2663   if (Parameter_count == 1)
2664     {
2665       pic16_emitpcode (POC_MOVF, pic16_popCopyReg (pic16_stack_postinc));
2666     }
2667   else if (Parameter_count == 2)
2668     {
2669       pic16_emitpcode (POC_MOVF, pic16_popCopyReg (pic16_stack_postinc));
2670       pic16_emitpcode (POC_MOVF, pic16_popCopyReg (pic16_stack_postinc));
2671     }
2672   else
2673     {
2674       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (Parameter_count));
2675       pic16_emitpcode (POC_ADDWF, pic16_popCopyReg (pic16_stackpnt_lo));  // &pic16_pc_fsr1l));
2676 
2677       if (STACK_MODEL_LARGE)
2678         {
2679           emitSKPNC;
2680           pic16_emitpcode (POC_INCF, pic16_popCopyReg (pic16_stackpnt_hi)); // &pic16_pc_fsr1h));
2681         }
2682     }
2683 }
2684 
2685 /*-----------------------------------------------------------------*/
2686 /* assignResultValue - assign results to oper, rescall==1 is       */
2687 /*                     called from genCall() or genPcall()         */
2688 /*-----------------------------------------------------------------*/
2689 static void
assignResultValue(operand * oper,int res_size,int rescall)2690 assignResultValue (operand * oper, int res_size, int rescall)
2691 {
2692   int size = AOP_SIZE (oper);
2693   int offset = 0;
2694 
2695   FENTRY2;
2696 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2697   DEBUGpic16_pic16_AopType (__LINE__, oper, NULL, NULL);
2698 
2699   if (rescall)
2700     {
2701       /* assign result from a call/pcall function() */
2702 
2703       /* function results are stored in a special order,
2704        * see top of file with Function return policy, or manual */
2705 
2706       if (size <= 4)
2707         {
2708           /* 8-bits, result in WREG */
2709           if (AOP_TYPE(oper) != AOP_ACC)
2710             {
2711               /* If destination NOT WREG. */
2712               pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (oper), 0));
2713             }
2714           else
2715             {
2716               DEBUGpic16_emitcode ("; ***", "ignore MOVWF\tWREG", __FUNCTION__, __LINE__);
2717             }
2718 
2719           if (size > 1 && res_size > 1)
2720             {
2721               /* 16-bits, result in PRODL:WREG */
2722               pic16_loadFromReturn (oper, 1, pic16_popCopyReg (&pic16_pc_prodl));
2723             }
2724 
2725           if (size > 2 && res_size > 2)
2726             {
2727               /* 24-bits, result in PRODH:PRODL:WREG */
2728               pic16_loadFromReturn (oper, 2, pic16_popCopyReg (&pic16_pc_prodh));       // patch 14
2729             }
2730 
2731           if (size > 3 && res_size > 3)
2732             {
2733               /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2734               pic16_loadFromReturn (oper, 3, pic16_popCopyReg (&pic16_pc_fsr0l));       // patch14
2735             }
2736 
2737           pic16_addSign (oper, res_size, IS_UNSIGNED (operandType (oper)));
2738 
2739         }
2740       else
2741         {
2742           /* >32-bits, result on stack, and FSR0 points to beginning.
2743            * Fix stack when done */
2744           /* FIXME FIXME */
2745 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2746           while (size--)
2747             {
2748 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpseudoStkPtr);
2749 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2750 
2751               popaopidx (AOP (oper), size, GpseudoStkPtr);
2752               GpseudoStkPtr++;
2753             }
2754 
2755           /* fix stack */
2756           free_stack_parameters (AOP_SIZE (oper));
2757         }
2758     }
2759   else
2760     {
2761       int areg = 0;             /* matching argument register */
2762 
2763 //      debugf("_G.useWreg = %d\tGpseudoStkPtr = %d\n", _G.useWreg, GpseudoStkPtr);
2764       areg = SPEC_ARGREG (OP_SYM_ETYPE (oper)) - 1;
2765 
2766 
2767       /* its called from genReceive (probably) -- VR */
2768       /* I hope this code will not be called from somewhere else in the future!
2769        * We manually set the pseudo stack pointer in genReceive. - dw
2770        */
2771       if (!GpseudoStkPtr && _G.useWreg)
2772         {
2773 //        DEBUGpic16_emitcode("; ", "pop %d", GpseudoStkPtr);
2774 
2775           /* The last byte in the assignment is in W */
2776           if (areg <= GpseudoStkPtr)
2777             {
2778               size--;
2779 
2780               if (AOP_TYPE(oper) != AOP_ACC)
2781                 {
2782                   /* If destination NOT WREG. */
2783                   pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (oper), offset /*size*/));
2784                 }
2785               else
2786                 {
2787                   DEBUGpic16_emitcode ("; ***", "ignore MOVWF\tWREG", __FUNCTION__, __LINE__);
2788                 }
2789 
2790               offset++;
2791 //          debugf("receive from WREG\n", 0);
2792             }
2793           GpseudoStkPtr++;      /* otherwise the calculation below fails (-_G.useWreg) */
2794         }
2795 //      GpseudoStkPtr++;
2796       _G.stack_lat = AOP_SIZE (oper) - 1;
2797 
2798       while (size)
2799         {
2800           size--;
2801           GpseudoStkPtr++;
2802           popaopidx (AOP (oper), offset, GpseudoStkPtr - _G.useWreg);
2803 //        debugf("receive from STACK\n", 0);
2804           offset++;
2805         }
2806     }
2807 }
2808 
2809 
2810 /*-----------------------------------------------------------------*/
2811 /* genIpush - generate code for pushing this gets a little complex */
2812 /*-----------------------------------------------------------------*/
2813 static void
genIpush(iCode * ic)2814 genIpush (iCode * ic)
2815 {
2816 //  int size, offset=0;
2817 
2818   FENTRY;
2819   DEBUGpic16_emitcode ("; ***", "%s  %d - WARNING no code generated", __FUNCTION__, __LINE__);
2820 
2821   if (ic->parmPush)
2822     {
2823       pic16_aopOp (IC_LEFT (ic), ic, FALSE);
2824 
2825       /* send to stack as normal */
2826       addSet (&_G.sendSet, ic);
2827 //    addSetHead(&_G.sendSet,ic);
2828       pic16_freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2829     }
2830 
2831 
2832 #if 0
2833   int size, offset = 0;
2834   char *l;
2835 
2836 
2837   /* if this is not a parm push : ie. it is spill push
2838      and spill push is always done on the local stack */
2839   if (!ic->parmPush)
2840     {
2841 
2842       /* and the item is spilt then do nothing */
2843       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2844         return;
2845 
2846       pic16_aopOp (IC_LEFT (ic), ic, FALSE);
2847       size = AOP_SIZE (IC_LEFT (ic));
2848       /* push it on the stack */
2849       while (size--)
2850         {
2851           l = pic16_aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2852           if (*l == '#')
2853             {
2854               MOVA (l);
2855               l = "acc";
2856             }
2857           pic16_emitcode ("push", "%s", l);
2858         }
2859       return;
2860     }
2861 
2862   pic16_freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2863 #endif
2864 }
2865 
2866 /*-----------------------------------------------------------------*/
2867 /* genIpop - recover the registers: can happen only for spilling   */
2868 /*-----------------------------------------------------------------*/
2869 static void
genIpop(iCode * ic)2870 genIpop (iCode * ic)
2871 {
2872   FENTRY;
2873   DEBUGpic16_emitcode ("; ***", "%s  %d - WARNING no code generated", __FUNCTION__, __LINE__);
2874 #if 0
2875   int size, offset;
2876 
2877 
2878   /* if the temp was not pushed then */
2879   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2880     return;
2881 
2882   pic16_aopOp (IC_LEFT (ic), ic, FALSE);
2883   size = AOP_SIZE (IC_LEFT (ic));
2884   offset = (size - 1);
2885   while (size--)
2886     pic16_emitcode ("pop", "%s", pic16_aopGet (AOP (IC_LEFT (ic)), offset--, FALSE, TRUE));
2887 
2888   pic16_freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2889 #endif
2890 }
2891 
2892 static int
wparamCmp(void * p1,void * p2)2893 wparamCmp (void *p1, void *p2)
2894 {
2895   return (!strcmp ((char *) p1, (char *) p2));
2896 }
2897 
2898 int
inWparamList(char * s)2899 inWparamList (char *s)
2900 {
2901   return isinSetWith (wparamList, s, wparamCmp);
2902 }
2903 
2904 
2905 /*-----------------------------------------------------------------*/
2906 /* genCall - generates a call statement                            */
2907 /*-----------------------------------------------------------------*/
2908 static void
genCall(iCode * ic)2909 genCall (iCode * ic)
2910 {
2911   sym_link *ftype;
2912   int stackParms = 0;
2913   int use_wreg = 0;
2914   int inwparam = 0;
2915   char *fname;
2916 
2917   FENTRY;
2918 
2919   ftype = OP_SYM_TYPE (IC_LEFT (ic));
2920   /* if caller saves & we have not saved then */
2921 //    if (!ic->regsSaved)
2922 //      saveRegisters(ic);
2923 
2924   /* initialise stackParms for IPUSH pushes */
2925 //      stackParms = pseudoStkPtr;
2926 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2927   fname = OP_SYMBOL (IC_LEFT (ic))->rname[0] ? OP_SYMBOL (IC_LEFT (ic))->rname : OP_SYMBOL (IC_LEFT (ic))->name;
2928   inwparam = (inWparamList (OP_SYMBOL (IC_LEFT (ic))->name)) || (FUNC_ISWPARAM (OP_SYM_TYPE (IC_LEFT (ic))));
2929 
2930 #if 0
2931   gpsimDebug_StackDump (__FILE__, __LINE__, fname);
2932 #endif
2933 
2934   /* if send set is not empty the assign */
2935   if (_G.sendSet)
2936     {
2937       iCode *sic;
2938       int pseudoStkPtr = -1;
2939       int firstTimeThruLoop = 1;
2940 
2941 
2942       /* reverse sendSet if function is not reentrant */
2943       if (!IFFUNC_ISREENT (ftype))
2944         _G.sendSet = reverseSet (_G.sendSet);
2945 
2946       /* First figure how many parameters are getting passed */
2947       stackParms = 0;
2948       use_wreg = 0;
2949 
2950       for (sic = setFirstItem (_G.sendSet); sic; sic = setNextItem (_G.sendSet))
2951         {
2952           int size;
2953 //          int offset = 0;
2954 
2955           pic16_aopOp (IC_LEFT (sic), sic, FALSE);
2956           size = AOP_SIZE (IC_LEFT (sic));
2957 
2958           stackParms += size;
2959 
2960           /* pass the last byte through WREG */
2961           if (inwparam)
2962             {
2963 
2964               while (size--)
2965                 {
2966                   DEBUGpic16_emitcode ("; ", "%d left %s", __LINE__, pic16_AopType (AOP_TYPE (IC_LEFT (sic))));
2967                   DEBUGpic16_emitcode ("; ", "push %d", pseudoStkPtr - 1);
2968 
2969                   if (!firstTimeThruLoop)
2970                     {
2971                       /* If this is not the first time we've been through the loop
2972                        * then we need to save the parameter in a temporary
2973                        * register. The last byte of the last parameter is
2974                        * passed in W. */
2975 
2976                       pushw ();
2977 //                  --pseudoStkPtr;             // sanity check
2978                       use_wreg = 1;
2979                     }
2980 
2981                   firstTimeThruLoop = 0;
2982 
2983                   pic16_mov2w (AOP (IC_LEFT (sic)), size);
2984 
2985 //                offset++;
2986                 }
2987             }
2988           else
2989             {
2990               /* all arguments are passed via stack */
2991               use_wreg = 0;
2992 
2993               while (size--)
2994                 {
2995                   DEBUGpic16_emitcode ("; ", "%d left %s", __LINE__, pic16_AopType (AOP_TYPE (IC_LEFT (sic))));
2996                   DEBUGpic16_emitcode ("; ", "push %d", pseudoStkPtr - 1);
2997 
2998 //                pushaop(AOP(IC_LEFT(sic)), size);
2999                   pic16_mov2w (AOP (IC_LEFT (sic)), size);
3000 
3001                   if (!_G.resDirect)
3002                     pushw ();
3003                 }
3004             }
3005 
3006           pic16_freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
3007         }
3008 
3009       if (inwparam)
3010         {
3011           if (IFFUNC_HASVARARGS (ftype) || IFFUNC_ISREENT (ftype))
3012             {
3013               pushw ();         /* save last parameter to stack if functions has varargs */
3014               use_wreg = 0;
3015             }
3016           else
3017             use_wreg = 1;
3018         }
3019       else
3020         use_wreg = 0;
3021 
3022       _G.stackRegSet = _G.sendSet;
3023       _G.sendSet = NULL;
3024     }
3025 
3026   /* make the call */
3027   pic16_emitpcode (POC_CALL, pic16_popGetWithString (fname));
3028 
3029   GpseudoStkPtr = 0;
3030 
3031   /* if we need to assign a result value */
3032   if ((IS_ITEMP (IC_RESULT (ic))
3033        && (OP_SYMBOL (IC_RESULT (ic))->nRegs || OP_SYMBOL (IC_RESULT (ic))->spildir)) || IS_TRUE_SYMOP (IC_RESULT (ic)))
3034     {
3035 
3036       _G.accInUse++;
3037       pic16_aopOp (IC_RESULT (ic), ic, FALSE);
3038       _G.accInUse--;
3039 
3040       /* Must not assign an 8-bit result to a 16-bit variable;
3041        * this would use (used...) the uninitialized PRODL! */
3042       /* FIXME: Need a proper way to obtain size of function result type,
3043        * OP_SYM_ETYPE does not work: it dereferences pointer types! */
3044       assignResultValue (IC_RESULT (ic), getSize (OP_SYM_TYPE (IC_LEFT (ic))->next), 1);
3045 
3046       DEBUGpic16_emitcode ("; ", "%d left %s", __LINE__, pic16_AopType (AOP_TYPE (IC_RESULT (ic))));
3047 
3048       pic16_freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3049     }
3050 
3051   if (!stackParms && ic->parmBytes)
3052     {
3053       stackParms = ic->parmBytes;
3054     }
3055 
3056   stackParms -= use_wreg;
3057   free_stack_parameters (stackParms);
3058 
3059 #if 0
3060   gpsimDebug_StackDump (__FILE__, __LINE__, fname);
3061 #endif
3062 
3063   /* adjust the stack for parameters if required */
3064 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3065 
3066 #if 0
3067   /* if register bank was saved then pop them */
3068   if (ic->bankSaved)
3069     unsaverbank (FUNC_REGBANK (dtype), ic, TRUE);
3070 
3071   /* if we hade saved some registers then unsave them */
3072   if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3073     unsaveRegisters (ic);
3074 #endif
3075 }
3076 
3077 
3078 
3079 /*-----------------------------------------------------------------*/
3080 /* genPcall - generates a call by pointer statement                */
3081 /*            new version, created from genCall - HJD              */
3082 /*-----------------------------------------------------------------*/
3083 static void
genPcall(iCode * ic)3084 genPcall (iCode * ic)
3085 {
3086   sym_link *fntype;
3087   int stackParms = 0;
3088   symbol *retlbl = newiTempLabel (NULL);
3089   pCodeOp *pcop_lbl = pic16_popGetLabel (retlbl->key);
3090 
3091   FENTRY;
3092 
3093   fntype = operandType (IC_LEFT (ic))->next;
3094 
3095   /* if send set is not empty the assign */
3096   if (_G.sendSet)
3097     {
3098       iCode *sic;
3099       int pseudoStkPtr = -1;
3100 
3101       /* reverse sendSet if function is not reentrant */
3102       if (!IFFUNC_ISREENT (fntype))
3103         _G.sendSet = reverseSet (_G.sendSet);
3104 
3105       stackParms = 0;
3106 
3107       for (sic = setFirstItem (_G.sendSet); sic; sic = setNextItem (_G.sendSet))
3108         {
3109           int size;
3110 
3111           pic16_aopOp (IC_LEFT (sic), sic, FALSE);
3112           size = AOP_SIZE (IC_LEFT (sic));
3113           stackParms += size;
3114 
3115           /* all parameters are passed via stack, since WREG is clobbered
3116            * by the calling sequence */
3117           while (size--)
3118             {
3119               DEBUGpic16_emitcode ("; ", "%d left %s", __LINE__, pic16_AopType (AOP_TYPE (IC_LEFT (sic))));
3120               DEBUGpic16_emitcode ("; ", "push %d", pseudoStkPtr - 1);
3121 
3122               pic16_mov2w (AOP (IC_LEFT (sic)), size);
3123               pushw ();
3124             }
3125 
3126           pic16_freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
3127         }
3128 
3129       _G.stackRegSet = _G.sendSet;
3130       _G.sendSet = NULL;
3131     }
3132 
3133   pic16_aopOp (IC_LEFT (ic), ic, FALSE);
3134 
3135   // push return address
3136   // push $ on return stack, then replace with retlbl
3137 
3138   /* Thanks to Thorsten Klose for pointing out that the following
3139    * snippet should be interrupt safe */
3140   pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg (&pic16_pc_intcon), pic16_popCopyReg (&pic16_pc_postdec1)));
3141   pic16_emitpcode (POC_BCF, pic16_popCopyGPR2Bit (pic16_popCopyReg (&pic16_pc_intcon), 7));
3142 
3143   pic16_emitpcodeNULLop (POC_PUSH);
3144 
3145   pic16_emitpcode (POC_MOVLW, pic16_popGetImmd (pcop_lbl->name, 0, 0));
3146   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_tosl));
3147   pic16_emitpcode (POC_MOVLW, pic16_popGetImmd (pcop_lbl->name, 1, 0));
3148   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_tosh));
3149   pic16_emitpcode (POC_MOVLW, pic16_popGetImmd (pcop_lbl->name, 2, 0));
3150   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_tosu));
3151 
3152   /* Conditionally re-enable interrupts, but keep interrupt flags in
3153    * INTCON intact (thanks to J. van der Boon, #3420588). */
3154   pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (pic16_popCopyReg (&pic16_pc_preinc1), 7));
3155   pic16_emitpcode (POC_BSF, pic16_popCopyGPR2Bit (pic16_popCopyReg (&pic16_pc_intcon), 7));
3156 
3157   /* make the call by writing the pointer into pc */
3158   mov2fp (pic16_popCopyReg (&pic16_pc_pclatu), AOP (IC_LEFT (ic)), 2);
3159   mov2fp (pic16_popCopyReg (&pic16_pc_pclath), AOP (IC_LEFT (ic)), 1);
3160 
3161   // note: MOVFF to PCL not allowed
3162   pic16_mov2w (AOP (IC_LEFT (ic)), 0);
3163   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_pcl));
3164 
3165 
3166   /* return address is here: (X) */
3167   pic16_emitpLabelFORCE (retlbl->key);
3168 
3169   pic16_freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3170 
3171   GpseudoStkPtr = 0;
3172   /* if we need assign a result value */
3173   if ((IS_ITEMP (IC_RESULT (ic))
3174        && (OP_SYMBOL (IC_RESULT (ic))->nRegs || OP_SYMBOL (IC_RESULT (ic))->spildir)) || IS_TRUE_SYMOP (IC_RESULT (ic)))
3175     {
3176 
3177       _G.accInUse++;
3178       pic16_aopOp (IC_RESULT (ic), ic, FALSE);
3179       _G.accInUse--;
3180 
3181       /* FIXME: Need proper way to obtain the function result's type.
3182        * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
3183       assignResultValue (IC_RESULT (ic), getSize (OP_SYM_TYPE (IC_LEFT (ic))->next->next), 1);
3184 
3185       DEBUGpic16_emitcode ("; ", "%d left %s", __LINE__, pic16_AopType (AOP_TYPE (IC_RESULT (ic))));
3186 
3187       pic16_freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3188     }
3189 
3190 //    stackParms -= use_wreg;
3191 
3192   free_stack_parameters (stackParms);
3193 }
3194 
3195 /*-----------------------------------------------------------------*/
3196 /* resultRemat - result  is rematerializable                       */
3197 /*-----------------------------------------------------------------*/
3198 static int
resultRemat(iCode * ic)3199 resultRemat (iCode * ic)
3200 {
3201   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3202   if (SKIP_IC (ic) || ic->op == IFX)
3203     return 0;
3204 
3205   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3206     {
3207       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3208       if (sym->remat && !POINTER_SET (ic))
3209         return 1;
3210     }
3211 
3212   return 0;
3213 }
3214 
3215 #if 0
3216 /*-----------------------------------------------------------------*/
3217 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3218 /*-----------------------------------------------------------------*/
3219 static bool
3220 inExcludeList (char *s)
3221 {
3222   DEBUGpic16_emitcode ("; ***", "%s  %d - WARNING no code generated", __FUNCTION__, __LINE__);
3223   int i = 0;
3224 
3225   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
3226   if (options.excludeRegs[i] && STRCASECMP (options.excludeRegs[i], "none") == 0)
3227     return FALSE;
3228 
3229   for (i = 0; options.excludeRegs[i]; i++)
3230     {
3231       if (options.excludeRegs[i] && STRCASECMP (s, options.excludeRegs[i]) == 0)
3232         return TRUE;
3233     }
3234   return FALSE;
3235 }
3236 #endif
3237 
3238 /*-----------------------------------------------------------------*/
3239 /* genFunction - generated code for function entry                 */
3240 /*-----------------------------------------------------------------*/
3241 static void
genFunction(iCode * ic)3242 genFunction (iCode * ic)
3243 {
3244   symbol *sym;
3245   sym_link *ftype;
3246 
3247   FENTRY;
3248   DEBUGpic16_emitcode ("; ***", "%s  %d curr label offset=%dprevious max_key=%d ", __FUNCTION__, __LINE__, pic16_labelOffset,
3249                        max_key);
3250 
3251   pic16_labelOffset += (max_key + 4);
3252   max_key = 0;
3253   GpseudoStkPtr = 0;
3254   _G.nRegsSaved = 0;
3255 
3256   ftype = operandType (IC_LEFT (ic));
3257   sym = OP_SYMBOL (IC_LEFT (ic));
3258 
3259   if (IFFUNC_ISISR (sym->type))
3260     {
3261       /* create an absolute section at the interrupt vector:
3262        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3263       symbol *asym;
3264       char asymname[128];
3265       pBlock *apb;
3266 
3267       //debugf ("interrupt number: %hhi\n", FUNC_INTNO (sym->type));
3268 
3269       if (FUNC_INTNO (sym->type) == INTNO_UNSPEC)
3270         SNPRINTF(asymname, sizeof(asymname), "ivec_%s", sym->name);
3271       else
3272         SNPRINTF(asymname, sizeof(asymname), "ivec_0x%x_%s", FUNC_INTNO (sym->type), sym->name);
3273 
3274       /* when an interrupt is declared as naked, do not emit the special
3275        * wrapper segment at vector address. The user should take care for
3276        * this instead. -- VR */
3277 
3278       if (!IFFUNC_ISNAKED (ftype) && (FUNC_INTNO (sym->type) != INTNO_UNSPEC))
3279         {
3280           asym = newSymbol (asymname, 0);
3281           apb = pic16_newpCodeChain (NULL, 'A', pic16_newpCodeCharP ("; Starting pCode block for absolute section"));
3282           pic16_addpBlock (apb);
3283 
3284           pic16_addpCode2pBlock (apb, pic16_newpCodeCharP (";-----------------------------------------"));
3285           pic16_addpCode2pBlock (apb, pic16_newpCodeFunction (moduleName, asym->name));
3286           //pic16_addpCode2pBlock (apb, pic16_newpCode (POC_GOTO, pic16_popGetWithString (sym->rname)));
3287           //pic16_addpCode2pBlock (apb, pic16_newpCode (POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3288           pic16_addpCode2pBlock (apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3289 
3290           /* mark the end of this tiny function */
3291           pic16_addpCode2pBlock (apb, pic16_newpCodeFunction (NULL, NULL));
3292         }
3293       else
3294         {
3295           SNPRINTF(asymname, sizeof(asymname), "%s", sym->rname);
3296         }
3297 
3298       {
3299         absSym *abSym;
3300 
3301         abSym = Safe_alloc(sizeof(absSym));
3302         strncpy(abSym->name, asymname, sizeof(abSym->name) - 1);
3303         abSym->name[sizeof(abSym->name) - 1] = '\0';
3304 
3305         switch (FUNC_INTNO (sym->type))
3306           {
3307           case 0:
3308             abSym->address = 0x000000;
3309             break;
3310           case 1:
3311             abSym->address = 0x000008;
3312             break;
3313           case 2:
3314             abSym->address = 0x000018;
3315             break;
3316           default:
3317             //fprintf (stderr, "no interrupt number is given\n");
3318             abSym->address = -1;
3319             break;
3320           }
3321 
3322         /* relocate interrupt vectors if needed */
3323         if (abSym->address != -1)
3324           abSym->address += pic16_options.ivt_loc;
3325 
3326         addSet (&absSymSet, abSym);
3327       }
3328     }
3329 
3330   /* create the function header */
3331   pic16_emitcode (";", "-----------------------------------------");
3332   pic16_emitcode (";", " function %s", sym->name);
3333   pic16_emitcode (";", "-----------------------------------------");
3334 
3335   /* prevent this symbol from being emitted as 'extern' */
3336   pic16_stringInSet (sym->rname, &pic16_localFunctions, 1);
3337 
3338   pic16_emitcode ("", "%s:", sym->rname);
3339   pic16_addpCode2pBlock (pb, pic16_newpCodeFunction (moduleName, sym->rname));
3340 
3341   {
3342     absSym *ab;
3343 
3344     for (ab = setFirstItem (absSymSet); ab; ab = setNextItem (absSymSet))
3345       {
3346         if (!strcmp (ab->name, sym->rname))
3347           {
3348             pic16_pBlockConvert2Absolute (pb);
3349             break;
3350           }
3351       }
3352   }
3353 
3354   currFunc = sym;               /* update the currFunc symbol */
3355   _G.fregsUsed = sym->regsUsed;
3356   _G.sregsAlloc = newBitVect (128);
3357 
3358   if (IFFUNC_ISNAKED (ftype))
3359     {
3360       DEBUGpic16_emitcode ("; ***", "__naked function, no prologue");
3361       return;
3362     }
3363 
3364   /* if this is an interrupt service routine then
3365    * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3366   if (IFFUNC_ISISR (sym->type))
3367     {
3368       _G.usefastretfie = 1;     /* use shadow registers by default */
3369 
3370       /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3371       if (!FUNC_ISSHADOWREGS (sym->type))
3372         {
3373           /* do not save WREG, STATUS, BSR for high priority interrupts
3374            * because they are stored in the hardware shadow registers already */
3375           _G.usefastretfie = 0;
3376           pic16_pushpCodeOp (pic16_popCopyReg (&pic16_pc_status));
3377           pic16_pushpCodeOp (pic16_popCopyReg (&pic16_pc_bsr));
3378           pushw ();
3379         }
3380 
3381       /* these should really be optimized somehow, because not all
3382        * interrupt handlers modify them */
3383       pic16_pushpCodeOp (pic16_popCopyReg (&pic16_pc_prodl));
3384       pic16_pushpCodeOp (pic16_popCopyReg (&pic16_pc_prodh));
3385       pic16_pushpCodeOp (pic16_popCopyReg (&pic16_pc_fsr0l));
3386       pic16_pushpCodeOp (pic16_popCopyReg (&pic16_pc_fsr0h));
3387       pic16_pushpCodeOp (pic16_popCopyReg (&pic16_pc_pclath));
3388       pic16_pushpCodeOp (pic16_popCopyReg (&pic16_pc_pclatu));
3389 
3390       //pic16_pBlockConvert2ISR (pb);
3391     }
3392 
3393   /* emit code to setup stack frame if user enabled,
3394    * and function is not main () */
3395 
3396   //debugf (stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS (sym->type));
3397   if (strcmp (sym->name, "main"))
3398     {
3399       if (0 || !options.omitFramePtr
3400           //|| sym->regsUsed
3401           || IFFUNC_ARGS (sym->type) || FUNC_HASSTACKPARM (sym->etype))
3402         {
3403           /* setup the stack frame */
3404           if (STACK_MODEL_LARGE)
3405             pic16_pushpCodeOp (pic16_popCopyReg (pic16_framepnt_hi));
3406           pic16_pushpCodeOp (pic16_popCopyReg (pic16_framepnt_lo));
3407 
3408           if (STACK_MODEL_LARGE)
3409             pic16_emitpcode (POC_MOVFF, pic16_popCombine2 (pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3410           pic16_emitpcode (POC_MOVFF, pic16_popCombine2 (pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3411         }
3412     }
3413 
3414   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) && sym->stack)
3415     {
3416       if (sym->stack > 127)
3417         werror (W_STACK_OVERFLOW, sym->name);
3418 
3419       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (sym->stack));
3420       pic16_emitpcode (POC_SUBWF, pic16_popCopyReg (pic16_stackpnt_lo));        //&pic16_pc_fsr1l));
3421       emitSKPC;
3422       pic16_emitpcode (POC_DECF, pic16_popCopyReg (pic16_stackpnt_hi)); //&pic16_pc_fsr1h));
3423     }
3424 
3425   if (inWparamList (sym->name) || FUNC_ISWPARAM (sym->type))
3426     {
3427       if (IFFUNC_HASVARARGS (sym->type) || IFFUNC_ISREENT (sym->type))
3428         _G.useWreg = 0;
3429       else
3430         _G.useWreg = 1;
3431     }
3432   else
3433     _G.useWreg = 0;
3434 
3435   /* if callee-save to be used for this function
3436    * then save the registers being used in this function */
3437   //if (IFFUNC_CALLEESAVES (sym->type))
3438   if (strcmp (sym->name, "main"))
3439     {
3440       int i;
3441 
3442       /* if any registers used */
3443       if (sym->regsUsed)
3444         {
3445           pic16_emitpinfo (INF_LOCALREGS, pic16_newpCodeOpLocalRegs (LR_ENTRY_BEGIN));
3446 
3447           if (!pic16_options.xinst)
3448             {
3449               /* save the registers used */
3450               DEBUGpic16_emitcode ("; **", "Saving used registers in stack");
3451               for (i = 0; i < sym->regsUsed->size; i++)
3452                 {
3453                   if (bitVectBitValue (sym->regsUsed, i))
3454                     {
3455 #if 0
3456                       fprintf (stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3457 #endif
3458                       pic16_pushpCodeOp (pic16_popRegFromIdx (i));
3459                       _G.nRegsSaved++;
3460 
3461                       if (!pic16_regWithIdx (i)->wasUsed)
3462                         {
3463                           fprintf (stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3464                                    __FILE__, __LINE__, pic16_regWithIdx (i)->name);
3465                           pic16_regWithIdx (i)->wasUsed = 1;
3466                         }
3467                     }
3468                 }
3469             }
3470           else
3471             {
3472               /* xinst */
3473               DEBUGpic16_emitcode ("; **", "Allocate a space in stack to be used as temporary registers");
3474               for (i = 0; i < sym->regsUsed->size; i++)
3475                 {
3476                   if (bitVectBitValue (sym->regsUsed, i))
3477                     _G.nRegsSaved++;
3478                 }
3479 
3480               //pic16_emitpcode (POC_ADDFSR, pic16_popGetLit2 (2, pic16_popGetLit (_G.nRegsSaved)));
3481             }
3482 
3483           pic16_emitpinfo (INF_LOCALREGS, pic16_newpCodeOpLocalRegs (LR_ENTRY_END));
3484         }
3485     }
3486 
3487   /* if critical function then turn interrupts off */
3488   if (IFFUNC_ISCRITICAL (ftype))
3489     {
3490       genCritical (NULL);
3491     }                           // if
3492 
3493   DEBUGpic16_emitcode ("; ", "need to adjust stack = %d", sym->stack);
3494   //fprintf (stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3495 }
3496 
3497 /*-----------------------------------------------------------------*/
3498 /* genEndFunction - generates epilogue for functions               */
3499 /*-----------------------------------------------------------------*/
3500 static void
genEndFunction(iCode * ic)3501 genEndFunction (iCode * ic)
3502 {
3503   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3504 
3505   FENTRY;
3506 
3507   if (IFFUNC_ISNAKED (sym->type))
3508     {
3509       DEBUGpic16_emitcode ("; ***", "__naked function, no epilogue");
3510       return;
3511     }
3512 
3513   if (IFFUNC_ISCRITICAL (sym->type))
3514     {
3515       genEndCritical (NULL);
3516     }                           // if
3517 
3518   _G.stack_lat = 0;
3519 
3520   //sym->regsUsed = _G.fregsUsed;
3521 
3522   /* now we need to restore the registers */
3523   /* if any registers used */
3524 
3525   /* first restore registers that might be used for stack access */
3526   if (_G.sregsAllocSet)
3527     {
3528       reg_info *sr;
3529 
3530       _G.sregsAllocSet = reverseSet (_G.sregsAllocSet);
3531       for (sr = setFirstItem (_G.sregsAllocSet); sr; sr = setNextItem (_G.sregsAllocSet))
3532         {
3533           pic16_poppCodeOp (pic16_popRegFromIdx (sr->rIdx));
3534         }
3535     }
3536 
3537   if (strcmp (sym->name, "main") && sym->regsUsed)
3538     {
3539       int i;
3540 
3541       pic16_emitpinfo (INF_LOCALREGS, pic16_newpCodeOpLocalRegs (LR_EXIT_BEGIN));
3542       /* restore registers used */
3543       DEBUGpic16_emitcode ("; **", "Restoring used registers from stack");
3544       for (i = sym->regsUsed->size; i >= 0; i--)
3545         {
3546           if (bitVectBitValue (sym->regsUsed, i))
3547             {
3548               pic16_poppCodeOp (pic16_popRegFromIdx (i));
3549               _G.nRegsSaved--;
3550             }
3551         }
3552       pic16_emitpinfo (INF_LOCALREGS, pic16_newpCodeOpLocalRegs (LR_EXIT_END));
3553     }
3554 
3555   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) && sym->stack)
3556     {
3557       if (sym->stack == 1)
3558         {
3559           pic16_emitpcode (POC_INFSNZ, pic16_popCopyReg (pic16_stackpnt_lo));
3560           pic16_emitpcode (POC_INCF, pic16_popCopyReg (pic16_stackpnt_hi));
3561         }
3562       else
3563         {
3564           // we have to add more than one...
3565           pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postinc));  // this holds a return value!
3566           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (sym->stack - 1));
3567           pic16_emitpcode (POC_ADDWF, pic16_popCopyReg (pic16_stackpnt_lo));
3568           emitSKPNC;
3569           pic16_emitpcode (POC_INCF, pic16_popCopyReg (pic16_stackpnt_hi));
3570           pic16_emitpcode (POC_COMF, pic16_popCopyReg (&pic16_pc_wreg));        // WREG = - (WREG+1)!
3571           pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (pic16_stack_plusw));    // this holds a retrun value!
3572         }
3573     }
3574 
3575   if (strcmp (sym->name, "main"))
3576     {
3577       if (0 || !options.omitFramePtr
3578           //|| sym->regsUsed
3579           || IFFUNC_ARGS (sym->type) || FUNC_HASSTACKPARM (sym->etype))
3580         {
3581           /* restore stack frame */
3582           pic16_poppCodeOp (pic16_popCopyReg (pic16_framepnt_lo));
3583           if (STACK_MODEL_LARGE)
3584             pic16_poppCodeOp (pic16_popCopyReg (pic16_framepnt_hi));
3585         }
3586     }
3587 
3588   _G.useWreg = 0;
3589 
3590   if (IFFUNC_ISISR (sym->type))
3591     {
3592       pic16_poppCodeOp (pic16_popCopyReg (&pic16_pc_pclatu));
3593       pic16_poppCodeOp (pic16_popCopyReg (&pic16_pc_pclath));
3594       pic16_poppCodeOp (pic16_popCopyReg (&pic16_pc_fsr0h));
3595       pic16_poppCodeOp (pic16_popCopyReg (&pic16_pc_fsr0l));
3596       pic16_poppCodeOp (pic16_popCopyReg (&pic16_pc_prodh));
3597       pic16_poppCodeOp (pic16_popCopyReg (&pic16_pc_prodl));
3598 
3599       if (!FUNC_ISSHADOWREGS (sym->type))
3600         {
3601           /* do not restore interrupt vector for WREG, STATUS, BSR
3602            * for high priority interrupt, see genFunction */
3603           pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (pic16_stack_preinc));
3604           pic16_poppCodeOp (pic16_popCopyReg (&pic16_pc_bsr));
3605           pic16_poppCodeOp (pic16_popCopyReg (&pic16_pc_status));
3606         }
3607       //_G.interruptvector = 0;         /* sanity check */
3608 
3609       /* if debug then send end of function */
3610       /* if (options.debug && currFunc)  */
3611       if (currFunc)
3612         {
3613           debugFile->writeEndFunction (currFunc, ic, 1);
3614         }
3615 
3616       if (_G.usefastretfie)
3617         pic16_emitpcode (POC_RETFIE, pic16_newpCodeOpLit (1));
3618       else
3619         pic16_emitpcodeNULLop (POC_RETFIE);
3620 
3621       pic16_addpCode2pBlock (pb, pic16_newpCodeFunction (NULL, NULL));
3622 
3623       _G.usefastretfie = 0;
3624       return;
3625     }
3626 
3627   /* if debug then send end of function */
3628   if (currFunc)
3629     {
3630       debugFile->writeEndFunction (currFunc, ic, 1);
3631     }
3632 
3633   /* insert code to restore stack frame, if user enabled it
3634    * and function is not main () */
3635 
3636   pic16_emitpcodeNULLop (POC_RETURN);
3637 
3638   /* Mark the end of a function */
3639   pic16_addpCode2pBlock (pb, pic16_newpCodeFunction (NULL, NULL));
3640 }
3641 
3642 
3643 void
pic16_storeForReturn(iCode * ic,int offset,pCodeOp * dest)3644 pic16_storeForReturn (iCode * ic, /*operand *op, */ int offset, pCodeOp * dest)
3645 {
3646   unsigned long lit = 1;
3647   operand *op;
3648 
3649   op = IC_LEFT (ic);
3650 
3651   // this fails for pic16_isLitOp(op) (if op is an AOP_PCODE)
3652   if (AOP_TYPE (op) == AOP_LIT)
3653     {
3654       if (!IS_FLOAT (operandType (op)))
3655         {
3656           lit = ulFromVal (AOP (op)->aopu.aop_lit);
3657         }
3658       else
3659         {
3660           union
3661           {
3662             unsigned long lit_int;
3663             float lit_float;
3664           } info;
3665 
3666           /* take care if literal is a float */
3667           info.lit_float = (float)floatFromVal (AOP (op)->aopu.aop_lit);
3668           lit = info.lit_int;
3669         }
3670     }
3671 
3672   if (AOP_TYPE (op) == AOP_LIT)
3673     {
3674       /* FIXME: broken for
3675        *   char __at(0x456) foo;
3676        *   return &foo;
3677        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
3678       pic16_movLit2f (dest, (lit >> (8ul * offset)));
3679     }
3680   else if (AOP_TYPE (op) == AOP_PCODE && AOP (op)->aopu.pcop->type == PO_IMMEDIATE)
3681     {
3682       /* char *s= "aaa"; return s; */
3683       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
3684        *      that the generic pointer is interpreted correctly
3685        *      as referring to __code space, but this is fragile! */
3686       pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (op), offset));
3687       /* XXX: should check that dest != WREG */
3688       pic16_emitpcode (POC_MOVWF, dest);
3689     }
3690   else
3691     {
3692       if (dest->type == PO_WREG && (offset == 0))
3693         {
3694           pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (op), offset));
3695           return;
3696         }
3697       pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popGet (AOP (op), offset), dest));
3698     }
3699 }
3700 
3701 /*-----------------------------------------------------------------*/
3702 /* genRet - generate code for return statement                     */
3703 /*-----------------------------------------------------------------*/
3704 static void
genRet(iCode * ic)3705 genRet (iCode * ic)
3706 {
3707   int size;
3708   operand *left;
3709 
3710   FENTRY;
3711   /* if we have no return value then
3712    * just generate the "ret" */
3713 
3714   if (!IC_LEFT (ic))
3715     goto jumpret;
3716 
3717   /* we have something to return then
3718    * move the return value into place */
3719   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3720   size = AOP_SIZE (IC_LEFT (ic));
3721 
3722   if (size <= 4)
3723     {
3724       if (size > 3)
3725         pic16_storeForReturn (ic, /*IC_LEFT(ic), */ 3, pic16_popCopyReg (&pic16_pc_fsr0l));
3726 
3727       if (size > 2)
3728         pic16_storeForReturn (ic, /*IC_LEFT(ic), */ 2, pic16_popCopyReg (&pic16_pc_prodh));
3729 
3730       if (size > 1)
3731         pic16_storeForReturn (ic, /*IC_LEFT(ic), */ 1, pic16_popCopyReg (&pic16_pc_prodl));
3732 
3733       pic16_storeForReturn (ic, /*IC_LEFT(ic), */ 0, pic16_popCopyReg (&pic16_pc_wreg));
3734 
3735     }
3736   else
3737     {
3738       /* >32-bits, setup stack and FSR0 */
3739       while (size--)
3740         {
3741 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpseudoStkPtr);
3742 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3743 
3744           pic16_pushpCodeOp (pic16_popGet (AOP (IC_LEFT (ic)), size));
3745 
3746 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3747           GpseudoStkPtr++;
3748         }
3749 
3750       /* setup FSR0 */
3751       pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg (pic16_stackpnt_lo), pic16_popCopyReg (&pic16_pc_fsr0l)));
3752 
3753       if (STACK_MODEL_LARGE)
3754         {
3755           pic16_emitpcode (POC_MOVFF,
3756                            pic16_popGet2p (pic16_popCopyReg (pic16_stackpnt_hi), pic16_popCopyReg (&pic16_pc_fsr0h)));
3757         }
3758       else
3759         {
3760           pic16_emitpcode (POC_CLRF, pic16_popCopyReg (pic16_stackpnt_hi));
3761         }
3762     }
3763 
3764   pic16_freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3765 
3766 jumpret:
3767   /* generate a jump to the return label
3768    * if the next is not the return statement */
3769   if (!(ic->next && ic->next->op == LABEL && IC_LABEL (ic->next) == returnLabel))
3770     {
3771 
3772       pic16_emitpcode (POC_GOTO, pic16_popGetLabel (returnLabel->key));
3773       pic16_emitcode ("goto", "_%05d_DS_", labelKey2num (returnLabel->key + pic16_labelOffset));
3774     }
3775 }
3776 
3777 static set *critical_temps = NULL;
3778 
3779 static void
genCritical(iCode * ic)3780 genCritical (iCode * ic)
3781 {
3782   pCodeOp *saved_intcon;
3783 
3784   if (!critical_temps)
3785     critical_temps = newSet ();
3786 
3787   saved_intcon = pic16_popGetTempReg (0);
3788   pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg (&pic16_pc_intcon), saved_intcon));
3789   pic16_emitpcode (POC_BCF, pic16_popCopyGPR2Bit (pic16_popCopyReg (&pic16_pc_intcon), 7));
3790   addSetHead (&critical_temps, saved_intcon);
3791 }
3792 
3793 static void
genEndCritical(iCode * ic)3794 genEndCritical (iCode * ic)
3795 {
3796   pCodeOp *saved_intcon = NULL;
3797 
3798   saved_intcon = getSet (&critical_temps);
3799   if (!saved_intcon)
3800     {
3801       fprintf (stderr, "Critical section left, but none entered -- ignoring for now.\n");
3802       return;
3803     }                           // if
3804 
3805   pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (saved_intcon, 7));
3806   pic16_emitpcode (POC_BSF, pic16_popCopyGPR2Bit (pic16_popCopyReg (&pic16_pc_intcon), 7));
3807   pic16_popReleaseTempReg (saved_intcon, 0);
3808 }
3809 
3810 /*-----------------------------------------------------------------*/
3811 /* genLabel - generates a label                                    */
3812 /*-----------------------------------------------------------------*/
3813 static void
genLabel(iCode * ic)3814 genLabel (iCode * ic)
3815 {
3816   FENTRY;
3817 
3818   /* special case never generate */
3819   if (IC_LABEL (ic) == entryLabel)
3820     return;
3821 
3822   pic16_emitpLabel (IC_LABEL (ic)->key);
3823 //  pic16_emitcode("","_%05d_DS_:",labelKey2num (IC_LABEL(ic)->key + pic16_labelOffset));
3824 }
3825 
3826 /*-----------------------------------------------------------------*/
3827 /* genGoto - generates a goto                                      */
3828 /*-----------------------------------------------------------------*/
3829 //tsd
3830 static void
genGoto(iCode * ic)3831 genGoto (iCode * ic)
3832 {
3833   FENTRY;
3834   pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_LABEL (ic)->key));
3835 //  pic16_emitcode ("goto","_%05d_DS_",labelKey2num (IC_LABEL(ic)->key + pic16_labelOffset));
3836 }
3837 
3838 
3839 /*-----------------------------------------------------------------*/
3840 /* genMultbits :- multiplication of bits                           */
3841 /*-----------------------------------------------------------------*/
3842 static void
genMultbits(operand * left,operand * right,operand * result)3843 genMultbits (operand * left, operand * right, operand * result)
3844 {
3845   FENTRY;
3846 
3847   if (!pic16_sameRegs (AOP (result), AOP (right)))
3848     pic16_emitpcode (POC_BSF, pic16_popGet (AOP (result), 0));
3849 
3850   pic16_emitpcode (POC_BTFSC, pic16_popGet (AOP (right), 0));
3851   pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP (left), 0));
3852   pic16_emitpcode (POC_BCF, pic16_popGet (AOP (result), 0));
3853 
3854 }
3855 
3856 
3857 /*-----------------------------------------------------------------*/
3858 /* genMultOneByte : 8 bit multiplication & division                */
3859 /*-----------------------------------------------------------------*/
3860 static void
genMultOneByte(operand * left,operand * right,operand * result)3861 genMultOneByte (operand * left, operand * right, operand * result)
3862 {
3863 
3864   FENTRY;
3865   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
3866   DEBUGpic16_pic16_AopTypeSign (__LINE__, left, right, result);
3867 
3868   /* (if two literals, the value is computed before) */
3869   /* if one literal, literal on the right */
3870   if (AOP_TYPE (left) == AOP_LIT)
3871     {
3872       operand *t = right;
3873       right = left;
3874       left = t;
3875     }
3876 
3877   /* size is already checked in genMult == 1 */
3878 //      size = AOP_SIZE(result);
3879 
3880   if (AOP_TYPE (right) == AOP_LIT)
3881     {
3882       pic16_emitpcomment ("multiply lit val:%s by variable %s and store in %s",
3883                           pic16_aopGet (AOP (right), 0, FALSE, FALSE),
3884                           pic16_aopGet (AOP (left), 0, FALSE, FALSE), pic16_aopGet (AOP (result), 0, FALSE, FALSE));
3885     }
3886   else
3887     {
3888       pic16_emitpcomment ("multiply variable :%s by variable %s and store in %s",
3889                           pic16_aopGet (AOP (right), 0, FALSE, FALSE),
3890                           pic16_aopGet (AOP (left), 0, FALSE, FALSE), pic16_aopGet (AOP (result), 0, FALSE, FALSE));
3891     }
3892 
3893   pic16_genMult8X8_n (left, right, result);
3894 }
3895 
3896 #if 0
3897 /*-----------------------------------------------------------------*/
3898 /* genMultOneWord : 16 bit multiplication                          */
3899 /*-----------------------------------------------------------------*/
3900 static void
3901 genMultOneWord (operand * left, operand * right, operand * result)
3902 {
3903   FENTRY;
3904   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
3905   DEBUGpic16_pic16_AopTypeSign (__LINE__, left, right, result);
3906 
3907   /* (if two literals, the value is computed before)
3908    * if one literal, literal on the right */
3909   if (AOP_TYPE (left) == AOP_LIT)
3910     {
3911       operand *t = right;
3912       right = left;
3913       left = t;
3914     }
3915 
3916   /* size is checked already == 2 */
3917 //  size = AOP_SIZE(result);
3918 
3919   if (AOP_TYPE (right) == AOP_LIT)
3920     {
3921       pic16_emitpcomment ("multiply lit val:%s by variable %s and store in %s",
3922                           pic16_aopGet (AOP (right), 0, FALSE, FALSE),
3923                           pic16_aopGet (AOP (left), 0, FALSE, FALSE), pic16_aopGet (AOP (result), 0, FALSE, FALSE));
3924     }
3925   else
3926     {
3927       pic16_emitpcomment ("multiply variable :%s by variable %s and store in %s",
3928                           pic16_aopGet (AOP (right), 0, FALSE, FALSE),
3929                           pic16_aopGet (AOP (left), 0, FALSE, FALSE), pic16_aopGet (AOP (result), 0, FALSE, FALSE));
3930     }
3931 
3932   pic16_genMult16X16_16 (left, right, result);
3933 }
3934 #endif
3935 
3936 #if 0
3937 /*-----------------------------------------------------------------*/
3938 /* genMultOneLong : 32 bit multiplication                          */
3939 /*-----------------------------------------------------------------*/
3940 static void
3941 genMultOneLong (operand * left, operand * right, operand * result)
3942 {
3943   FENTRY;
3944   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
3945   DEBUGpic16_pic16_AopTypeSign (__LINE__, left, right, result);
3946 
3947   /* (if two literals, the value is computed before)
3948    * if one literal, literal on the right */
3949   if (AOP_TYPE (left) == AOP_LIT)
3950     {
3951       operand *t = right;
3952       right = left;
3953       left = t;
3954     }
3955 
3956   /* size is checked already == 4 */
3957 //  size = AOP_SIZE(result);
3958 
3959   if (AOP_TYPE (right) == AOP_LIT)
3960     {
3961       pic16_emitpcomment ("multiply lit val:%s by variable %s and store in %s",
3962                           pic16_aopGet (AOP (right), 0, FALSE, FALSE),
3963                           pic16_aopGet (AOP (left), 0, FALSE, FALSE), pic16_aopGet (AOP (result), 0, FALSE, FALSE));
3964     }
3965   else
3966     {
3967       pic16_emitpcomment ("multiply variable :%s by variable %s and store in %s",
3968                           pic16_aopGet (AOP (right), 0, FALSE, FALSE),
3969                           pic16_aopGet (AOP (left), 0, FALSE, FALSE), pic16_aopGet (AOP (result), 0, FALSE, FALSE));
3970     }
3971 
3972   pic16_genMult32X32_32 (left, right, result);
3973 }
3974 #endif
3975 
3976 
3977 
3978 /*-----------------------------------------------------------------*/
3979 /* genMult - generates code for multiplication                     */
3980 /*-----------------------------------------------------------------*/
3981 static void
genMult(iCode * ic)3982 genMult (iCode * ic)
3983 {
3984   operand *left = IC_LEFT (ic);
3985   operand *right = IC_RIGHT (ic);
3986   operand *result = IC_RESULT (ic);
3987 
3988   FENTRY;
3989   /* assign the amsops */
3990   pic16_aopOp (left, ic, FALSE);
3991   pic16_aopOp (right, ic, FALSE);
3992   pic16_aopOp (result, ic, TRUE);
3993 
3994   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
3995 
3996   /* special cases first *
3997    * both are bits */
3998   if (AOP_TYPE (left) == AOP_CRY && AOP_TYPE (right) == AOP_CRY)
3999     {
4000       genMultbits (left, right, result);
4001       goto release;
4002     }
4003 
4004   /* if both are of size == 1 */
4005   if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4006     {
4007       genMultOneByte (left, right, result);
4008       goto release;
4009     }
4010 
4011 #if 0
4012   /* if both are of size == 2 */
4013   if (AOP_SIZE (left) == 2 && AOP_SIZE (right) == 2)
4014     {
4015       genMultOneWord (left, right, result);
4016       goto release;
4017     }
4018 
4019   /* if both are of size == 4 */
4020   if (AOP_SIZE (left) == 4 && AOP_SIZE (right) == 4)
4021     {
4022       genMultOneLong (left, right, result);
4023       goto release;
4024     }
4025 #endif
4026 
4027   fprintf (stderr, "%s: should have been transformed into function call\n", __FUNCTION__);
4028   assert (!"Multiplication should have been transformed into function call!");
4029 
4030   pic16_emitcode ("multiply ", "sizes are greater than 4 ... need to insert proper algor.");
4031 
4032 
4033   fprintf (stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE (result), AOP_SIZE (left), AOP_SIZE (right));
4034   /* should have been converted to function call */
4035   assert (0);
4036 
4037 release:
4038   pic16_freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4039   pic16_freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4040   pic16_freeAsmop (result, NULL, ic, TRUE);
4041 }
4042 
4043 #if 0
4044 /*-----------------------------------------------------------------*/
4045 /* genDivbits :- division of bits                                  */
4046 /*-----------------------------------------------------------------*/
4047 static void
4048 genDivbits (operand * left, operand * right, operand * result)
4049 {
4050   char *l;
4051 
4052   FENTRY;
4053   /* the result must be bit */
4054   pic16_emitcode ("mov", "b,%s", pic16_aopGet (AOP (right), 0, FALSE, FALSE));
4055   l = pic16_aopGet (AOP (left), 0, FALSE, FALSE);
4056 
4057   MOVA (l);
4058 
4059   pic16_emitcode ("div", "ab");
4060   pic16_emitcode ("rrc", "a");
4061   pic16_aopPut (AOP (result), "c", 0);
4062 }
4063 
4064 /*-----------------------------------------------------------------*/
4065 /* genDivOneByte : 8 bit division                                  */
4066 /*-----------------------------------------------------------------*/
4067 static void
4068 genDivOneByte (operand * left, operand * right, operand * result)
4069 {
4070   sym_link *opetype = operandType (result);
4071   char *l;
4072   symbol *lbl;
4073   int size, offset;
4074 
4075   /* result = divident / divisor
4076    * - divident may be a register or a literal,
4077    * - divisor may be a register or a literal,
4078    * so there are 3 cases (literal / literal is optimized
4079    * by the front-end) to handle.
4080    * In addition we must handle signed and unsigned, which
4081    * result in 6 final different cases -- VR */
4082 
4083   FENTRY;
4084 
4085   size = AOP_SIZE (result) - 1;
4086   offset = 1;
4087   /* signed or unsigned */
4088   if (SPEC_USIGN (opetype))
4089     {
4090       pCodeOp *pct1,            /* count */
4091               *pct2,                   /* reste */
4092               *pct3;                   /* temp */
4093       symbol *label1, *label2, *label3;;
4094 
4095 
4096       /* unsigned is easy */
4097 
4098       pct1 = pic16_popGetTempReg (1);
4099       pct2 = pic16_popGetTempReg (1);
4100       pct3 = pic16_popGetTempReg (1);
4101 
4102       label1 = newiTempLabel (NULL);
4103       label2 = newiTempLabel (NULL);
4104       label3 = newiTempLabel (NULL);
4105 
4106       /* the following algorithm is extracted from divuint.c */
4107 
4108       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (8));
4109       pic16_emitpcode (POC_MOVWF, pic16_pCodeOpCopy (pct1));
4110 
4111       pic16_emitpcode (POC_CLRF, pic16_pCodeOpCopy (pct2));
4112 
4113       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), 0));
4114 
4115       pic16_emitpLabel (label1->key);
4116 
4117       emitCLRC;
4118       pic16_emitpcode (POC_RLCF, pic16_pCodeOpCopy (pct2));
4119 
4120 
4121       emitCLRC;
4122       pic16_emitpcode (POC_RLCF, pic16_popCopyReg (&pic16_pc_wreg));
4123 
4124 
4125       emitSKPNC;
4126       pic16_emitpcode (POC_INCF, pic16_pCodeOpCopy (pct2));
4127 
4128       pic16_emitpcode (POC_MOVWF, pic16_pCodeOpCopy (pct3));
4129       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (right), 0));
4130 
4131       pic16_emitpcode (POC_CPFSLT, pic16_pCodeOpCopy (pct2));
4132       pic16_emitpcode (POC_BRA, pic16_popGetLabel (label3->key));
4133       pic16_emitpcode (POC_BRA, pic16_popGetLabel (label2->key));
4134 
4135       pic16_emitpLabel (label3->key);
4136       pic16_emitpcode (POC_SUBWF, pic16_pCodeOpCopy (pct2));
4137       pic16_emitpcode (POC_INCF, pic16_pCodeOpCopy (pct3));
4138 
4139 
4140 
4141       pic16_emitpLabel (label2->key);
4142       pic16_emitpcode (POC_MOVFW, pic16_pCodeOpCopy (pct3));
4143       pic16_emitpcode (POC_DECFSZ, pic16_pCodeOpCopy (pct1));
4144       pic16_emitpcode (POC_BRA, pic16_popGetLabel (label1->key));
4145 
4146       /* result is in wreg */
4147       if (AOP_TYPE (result) != AOP_ACC)
4148         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
4149 
4150       pic16_popReleaseTempReg (pct3, 1);
4151       pic16_popReleaseTempReg (pct2, 1);
4152       pic16_popReleaseTempReg (pct1, 1);
4153 
4154       return;
4155     }
4156 
4157   /* signed is a little bit more difficult */
4158 
4159   /* save the signs of the operands */
4160   l = pic16_aopGet (AOP (left), 0, FALSE, FALSE);
4161   MOVA (l);
4162   pic16_emitcode ("xrl", "a,%s", pic16_aopGet (AOP (right), 0, FALSE, TRUE));
4163   pic16_emitcode ("push", "acc");       /* save it on the stack */
4164 
4165   /* now sign adjust for both left & right */
4166   l = pic16_aopGet (AOP (right), 0, FALSE, FALSE);
4167   MOVA (l);
4168   lbl = newiTempLabel (NULL);
4169   pic16_emitcode ("jnb", "acc.7,%05d_DS_", labelKey2num (lbl->key));
4170   pic16_emitcode ("cpl", "a");
4171   pic16_emitcode ("inc", "a");
4172   pic16_emitcode ("", "%05d_DS_:", labelKey2num (lbl->key));
4173   pic16_emitcode ("mov", "b,a");
4174 
4175   /* sign adjust left side */
4176   l = pic16_aopGet (AOP (left), 0, FALSE, FALSE);
4177   MOVA (l);
4178 
4179   lbl = newiTempLabel (NULL);
4180   pic16_emitcode ("jnb", "acc.7,%05d_DS_", labelKey2num (lbl->key));
4181   pic16_emitcode ("cpl", "a");
4182   pic16_emitcode ("inc", "a");
4183   pic16_emitcode ("", "%05d_DS_:", labelKey2num (lbl->key));
4184 
4185   /* now the division */
4186   pic16_emitcode ("div", "ab");
4187   /* we are interested in the lower order
4188      only */
4189   pic16_emitcode ("mov", "b,a");
4190   lbl = newiTempLabel (NULL);
4191   pic16_emitcode ("pop", "acc");
4192   /* if there was an over flow we don't
4193      adjust the sign of the result */
4194   pic16_emitcode ("jb", "ov,%05d_DS_", labelKey2num (lbl->key));
4195   pic16_emitcode ("jnb", "acc.7,%05d_DS_", labelKey2num (lbl->key));
4196   CLRC;
4197   pic16_emitcode ("clr", "a");
4198   pic16_emitcode ("subb", "a,b");
4199   pic16_emitcode ("mov", "b,a");
4200   pic16_emitcode ("", "%05d_DS_:", labelKey2num (lbl->key));
4201 
4202   /* now we are done */
4203   pic16_aopPut (AOP (result), "b", 0);
4204   if (size > 0)
4205     {
4206       pic16_emitcode ("mov", "c,b.7");
4207       pic16_emitcode ("subb", "a,acc");
4208     }
4209   while (size--)
4210     pic16_aopPut (AOP (result), "a", offset++);
4211 
4212 }
4213 #endif
4214 
4215 /*-----------------------------------------------------------------*/
4216 /* genDiv - generates code for division                            */
4217 /*-----------------------------------------------------------------*/
4218 static void
genDiv(iCode * ic)4219 genDiv (iCode * ic)
4220 {
4221   operand *left = IC_LEFT (ic);
4222   operand *right = IC_RIGHT (ic);
4223   operand *result = IC_RESULT (ic);
4224   int negated = 0;
4225   int leftVal = 0, rightVal = 0;
4226   int signedLits = 0;
4227   char *functions[2][2] = { {"__divschar", "__divuchar"}, {"__modschar", "__moduchar"} };
4228   int op = 0;
4229 
4230   /* Division is a very lengthy algorithm, so it is better
4231    * to call support routines than inlining algorithm.
4232    * Division functions written here just in case someone
4233    * wants to inline and not use the support libraries -- VR */
4234 
4235   FENTRY;
4236 
4237   /* assign the amsops */
4238   pic16_aopOp (left, ic, FALSE);
4239   pic16_aopOp (right, ic, FALSE);
4240   pic16_aopOp (result, ic, TRUE);
4241 
4242   if (ic->op == '/')
4243     op = 0;
4244   else if (ic->op == '%')
4245     op = 1;
4246   else
4247     assert (!"invalid operation requested in genDivMod");
4248 
4249   /* get literal values */
4250   if (IS_VALOP (left))
4251     {
4252       leftVal = (int) ulFromVal (OP_VALUE (left));
4253       assert (leftVal >= -128 && leftVal < 256);
4254       if (leftVal < 0)
4255         {
4256           signedLits++;
4257         }
4258     }
4259   if (IS_VALOP (right))
4260     {
4261       rightVal = (int) ulFromVal (OP_VALUE (right));
4262       assert (rightVal >= -128 && rightVal < 256);
4263       if (rightVal < 0)
4264         {
4265           signedLits++;
4266         }
4267     }
4268 
4269   /* We should only come here to convert all
4270    * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4271    * with exactly one operand being s8_t into
4272    * u8_t x u8_t -> u8_t. All other cases should have been
4273    * turned into calls to support routines beforehand... */
4274   if ((AOP_SIZE (left) == 1 || IS_VALOP (left)) && (AOP_SIZE (right) == 1 || IS_VALOP (right)))
4275     {
4276       if ((!IS_UNSIGNED (operandType (right)) || rightVal < 0) && (!IS_UNSIGNED (operandType (left)) || leftVal < 0))
4277         {
4278           /* Both operands are signed or negative, use _divschar
4279            * instead of _divuchar */
4280           pushaop (AOP (right), 0);
4281           pushaop (AOP (left), 0);
4282 
4283           /* call _divschar */
4284           pic16_emitpcode (POC_CALL, pic16_popGetWithString (functions[op][0]));
4285 
4286           {
4287             symbol *sym;
4288             sym = newSymbol (functions[op][0], 0);
4289             sym->used++;
4290             strcpy (sym->rname, functions[op][0]);
4291             checkAddSym (&externs, sym);
4292           }
4293 
4294           /* assign result */
4295           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
4296           if (AOP_SIZE (result) > 1)
4297             {
4298               pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg (&pic16_pc_prodl), pic16_popGet (AOP (result), 1)));
4299               /* sign extend */
4300               pic16_addSign (result, 2, 1);
4301             }
4302 
4303           /* clean up stack */
4304           pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (pic16_stack_preinc));
4305           pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (pic16_stack_preinc));
4306 
4307           goto release;
4308         }
4309 
4310       /* push right operand */
4311       if (IS_VALOP (right))
4312         {
4313           if (rightVal < 0)
4314             {
4315               pic16_pushpCodeOp (pic16_popGetLit (-rightVal));
4316               negated++;
4317             }
4318           else
4319             {
4320               pushaop (AOP (right), 0);
4321             }
4322         }
4323       else if (!IS_UNSIGNED (operandType (right)))
4324         {
4325           pic16_mov2w (AOP (right), 0);
4326           pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP (right), 0, 7));
4327           pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
4328           pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec));
4329           negated++;
4330         }
4331       else
4332         {
4333           pushaop (AOP (right), 0);
4334         }
4335 
4336       /* push left operand */
4337       if (IS_VALOP (left))
4338         {
4339           if (leftVal < 0)
4340             {
4341               pic16_pushpCodeOp (pic16_popGetLit (-leftVal));
4342               negated++;
4343             }
4344           else
4345             {
4346               pushaop (AOP (left), 0);
4347             }
4348         }
4349       else if (!IS_UNSIGNED (operandType (left)))
4350         {
4351           pic16_mov2w (AOP (left), 0);
4352           pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP (left), 0, 7));
4353           pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
4354           pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec));
4355           negated++;
4356         }
4357       else
4358         {
4359           pushaop (AOP (left), 0);
4360         }
4361 
4362       /* call _divuchar */
4363       pic16_emitpcode (POC_CALL, pic16_popGetWithString (functions[op][1]));
4364 
4365       {
4366         symbol *sym;
4367         sym = newSymbol (functions[op][1], 0);
4368         sym->used++;
4369         strcpy (sym->rname, functions[op][1]);
4370         checkAddSym (&externs, sym);
4371       }
4372 
4373       /* Revert negation(s) from above.
4374        * This is inefficient: if both operands are negative, this
4375        * should not touch WREG. However, determining that exactly
4376        * one operand was negated costs at least 3 instructions,
4377        * so there is nothing to be gained here, is there?
4378        *
4379        * I negate WREG because either operand might share registers with
4380        * result, so assigning first might destroy an operand. */
4381 
4382       /* For the modulus operator, (a/b)*b == a shall hold.
4383        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4384        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
4385        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
4386        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
4387        * Only invert the result if the left operand is negative (sigh).
4388        */
4389       if (AOP_SIZE (result) <= 1 || !negated)
4390         {
4391           if (ic->op == '/')
4392             {
4393               if (IS_VALOP (right))
4394                 {
4395                   if (rightVal < 0)
4396                     {
4397                       /* we negated this operand above */
4398                       pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
4399                     }
4400                 }
4401               else if (!IS_UNSIGNED (operandType (right)))
4402                 {
4403                   pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP (right), 0, 7));
4404                   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
4405                 }
4406             }
4407 
4408           if (IS_VALOP (left))
4409             {
4410               if (leftVal < 0)
4411                 {
4412                   /* we negated this operand above */
4413                   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
4414                 }
4415             }
4416           else if (!IS_UNSIGNED (operandType (left)))
4417             {
4418               pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP (left), 0, 7));
4419               pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
4420             }
4421 
4422           /* Move result to destination. */
4423           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
4424 
4425           /* Zero-extend:  no operand was signed (or result is just a byte). */
4426           pic16_addSign (result, 1, 0);
4427         }
4428       else
4429         {
4430           assert (AOP_SIZE (result) > 1);
4431           pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), 1));
4432           if (ic->op == '/')
4433             {
4434               if (IS_VALOP (right))
4435                 {
4436                   if (rightVal < 0)
4437                     {
4438                       /* we negated this operand above */
4439                       pic16_emitpcode (POC_COMF, pic16_popGet (AOP (result), 1));
4440                     }
4441                 }
4442               else if (!IS_UNSIGNED (operandType (right)))
4443                 {
4444                   pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP (right), 0, 7));
4445                   pic16_emitpcode (POC_COMF, pic16_popGet (AOP (result), 1));
4446                 }
4447             }
4448 
4449           if (IS_VALOP (left))
4450             {
4451               if (leftVal < 0)
4452                 {
4453                   /* we negated this operand above */
4454                   pic16_emitpcode (POC_COMF, pic16_popGet (AOP (result), 1));
4455                 }
4456             }
4457           else if (!IS_UNSIGNED (operandType (left)))
4458             {
4459               pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP (left), 0, 7));
4460               pic16_emitpcode (POC_COMF, pic16_popGet (AOP (result), 1));
4461             }
4462 
4463           /* Move result to destination. */
4464           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
4465 
4466           /* Negate result if required. */
4467           pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP (result), 1, 7));
4468           pic16_emitpcode (POC_NEGF, pic16_popGet (AOP (result), 0));
4469 
4470           /* Sign-extend. */
4471           pic16_addSign (result, 2, 1);
4472         }
4473 
4474       /* clean up stack */
4475       pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (pic16_stack_preinc));
4476       pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (pic16_stack_preinc));
4477       goto release;
4478     }
4479 
4480 #if 0
4481   /* special cases first */
4482   /* both are bits */
4483   if (AOP_TYPE (left) == AOP_CRY && AOP_TYPE (right) == AOP_CRY)
4484     {
4485       genDivbits (left, right, result);
4486       goto release;
4487     }
4488 
4489   /* if both are of size == 1 */
4490   if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4491     {
4492       genDivOneByte (left, right, result);
4493       goto release;
4494     }
4495 #endif
4496 
4497   /* should have been converted to function call */
4498   assert (0);
4499 release:
4500   pic16_freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4501   pic16_freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4502   pic16_freeAsmop (result, NULL, ic, TRUE);
4503 }
4504 
4505 #if 0
4506 /*-----------------------------------------------------------------*/
4507 /* genModbits :- modulus of bits                                   */
4508 /*-----------------------------------------------------------------*/
4509 static void
4510 genModbits (operand * left, operand * right, operand * result)
4511 {
4512   char *l;
4513 
4514   FENTRY;
4515 
4516   werror (W_POSSBUG2, __FILE__, __LINE__);
4517   /* the result must be bit */
4518   pic16_emitcode ("mov", "b,%s", pic16_aopGet (AOP (right), 0, FALSE, FALSE));
4519   l = pic16_aopGet (AOP (left), 0, FALSE, FALSE);
4520 
4521   MOVA (l);
4522 
4523   pic16_emitcode ("div", "ab");
4524   pic16_emitcode ("mov", "a,b");
4525   pic16_emitcode ("rrc", "a");
4526   pic16_aopPut (AOP (result), "c", 0);
4527 }
4528 
4529 /*-----------------------------------------------------------------*/
4530 /* genModOneByte : 8 bit modulus                                   */
4531 /*-----------------------------------------------------------------*/
4532 static void
4533 genModOneByte (operand * left, operand * right, operand * result)
4534 {
4535   sym_link *opetype = operandType (result);
4536   char *l;
4537   symbol *lbl;
4538 
4539   FENTRY;
4540   werror (W_POSSBUG2, __FILE__, __LINE__);
4541 
4542   /* signed or unsigned */
4543   if (SPEC_USIGN (opetype))
4544     {
4545       /* unsigned is easy */
4546       pic16_emitcode ("mov", "b,%s", pic16_aopGet (AOP (right), 0, FALSE, FALSE));
4547       l = pic16_aopGet (AOP (left), 0, FALSE, FALSE);
4548       MOVA (l);
4549       pic16_emitcode ("div", "ab");
4550       pic16_aopPut (AOP (result), "b", 0);
4551       return;
4552     }
4553 
4554   /* signed is a little bit more difficult */
4555 
4556   /* save the signs of the operands */
4557   l = pic16_aopGet (AOP (left), 0, FALSE, FALSE);
4558   MOVA (l);
4559 
4560   pic16_emitcode ("xrl", "a,%s", pic16_aopGet (AOP (right), 0, FALSE, FALSE));
4561   pic16_emitcode ("push", "acc");       /* save it on the stack */
4562 
4563   /* now sign adjust for both left & right */
4564   l = pic16_aopGet (AOP (right), 0, FALSE, FALSE);
4565   MOVA (l);
4566 
4567   lbl = newiTempLabel (NULL);
4568   pic16_emitcode ("jnb", "acc.7,%05d_DS_", labelKey2num (lbl->key));
4569   pic16_emitcode ("cpl", "a");
4570   pic16_emitcode ("inc", "a");
4571   pic16_emitcode ("", "%05d_DS_:", labelKey2num (lbl->key));
4572   pic16_emitcode ("mov", "b,a");
4573 
4574   /* sign adjust left side */
4575   l = pic16_aopGet (AOP (left), 0, FALSE, FALSE);
4576   MOVA (l);
4577 
4578   lbl = newiTempLabel (NULL);
4579   pic16_emitcode ("jnb", "acc.7,%05d_DS_", labelKey2num (lbl->key));
4580   pic16_emitcode ("cpl", "a");
4581   pic16_emitcode ("inc", "a");
4582   pic16_emitcode ("", "%05d_DS_:", labelKey2num (lbl->key));
4583 
4584   /* now the multiplication */
4585   pic16_emitcode ("div", "ab");
4586   /* we are interested in the lower order
4587      only */
4588   lbl = newiTempLabel (NULL);
4589   pic16_emitcode ("pop", "acc");
4590   /* if there was an over flow we don't
4591      adjust the sign of the result */
4592   pic16_emitcode ("jb", "ov,%05d_DS_", labelKey2num (lbl->key));
4593   pic16_emitcode ("jnb", "acc.7,%05d_DS_", labelKey2num (lbl->key));
4594   CLRC;
4595   pic16_emitcode ("clr", "a");
4596   pic16_emitcode ("subb", "a,b");
4597   pic16_emitcode ("mov", "b,a");
4598   pic16_emitcode ("", "%05d_DS_:", labelKey2num (lbl->key));
4599 
4600   /* now we are done */
4601   pic16_aopPut (AOP (result), "b", 0);
4602 
4603 }
4604 #endif
4605 
4606 /*-----------------------------------------------------------------*/
4607 /* genMod - generates code for division                            */
4608 /*-----------------------------------------------------------------*/
4609 static void
genMod(iCode * ic)4610 genMod (iCode * ic)
4611 {
4612   /* Task deferred to genDiv */
4613   genDiv (ic);
4614 #if 0
4615   operand *left = IC_LEFT (ic);
4616   operand *right = IC_RIGHT (ic);
4617   operand *result = IC_RESULT (ic);
4618 
4619   FENTRY;
4620 
4621   /* assign the amsops */
4622   pic16_aopOp (left, ic, FALSE);
4623   pic16_aopOp (right, ic, FALSE);
4624   pic16_aopOp (result, ic, TRUE);
4625 
4626   /* special cases first */
4627   /* both are bits */
4628   if (AOP_TYPE (left) == AOP_CRY && AOP_TYPE (right) == AOP_CRY)
4629     {
4630       genModbits (left, right, result);
4631       goto release;
4632     }
4633 
4634   /* if both are of size == 1 */
4635   if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4636     {
4637       genModOneByte (left, right, result);
4638       goto release;
4639     }
4640 
4641   /* should have been converted to function call */
4642   assert (0);
4643 
4644 release:
4645   pic16_freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4646   pic16_freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4647   pic16_freeAsmop (result, NULL, ic, TRUE);
4648 #endif
4649 }
4650 
4651 /*-----------------------------------------------------------------*/
4652 /* genIfxJump :- will create a jump depending on the ifx           */
4653 /*-----------------------------------------------------------------*/
4654 /*
4655   note: May need to add parameter to indicate when a variable is in bit space.
4656 */
4657 static void
genIfxJump(iCode * ic,char * jval)4658 genIfxJump (iCode * ic, char *jval)
4659 {
4660   FENTRY;
4661 
4662   /* if true label then we jump if condition
4663      supplied is true */
4664   if (IC_TRUE (ic))
4665     {
4666 
4667       if (strcmp (jval, "a") == 0)
4668         emitSKPZ;
4669       else if (strcmp (jval, "c") == 0)
4670         emitSKPNC;
4671       else
4672         {
4673           DEBUGpic16_emitcode ("; ***", "%d - assuming %s is in bit space", __LINE__, jval);
4674           pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit (jval, -1, 1, PO_GPR_REGISTER));
4675         }
4676 
4677       pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_TRUE (ic)->key));
4678       pic16_emitcode (" goto", "_%05d_DS_", labelKey2num (IC_TRUE (ic)->key + pic16_labelOffset));
4679 
4680     }
4681   else
4682     {
4683       /* false label is present */
4684       if (strcmp (jval, "a") == 0)
4685         emitSKPNZ;
4686       else if (strcmp (jval, "c") == 0)
4687         emitSKPC;
4688       else
4689         {
4690           DEBUGpic16_emitcode ("; ***", "%d - assuming %s is in bit space", __LINE__, jval);
4691           pic16_emitpcode (POC_BTFSS, pic16_newpCodeOpBit (jval, -1, 1, PO_GPR_REGISTER));
4692         }
4693 
4694       pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_FALSE (ic)->key));
4695       pic16_emitcode (" goto", "_%05d_DS_", labelKey2num (IC_FALSE (ic)->key + pic16_labelOffset));
4696 
4697     }
4698 
4699 
4700   /* mark the icode as generated */
4701   ic->generated = 1;
4702 }
4703 
4704 static void
genIfxpCOpJump(iCode * ic,pCodeOp * jop)4705 genIfxpCOpJump (iCode * ic, pCodeOp * jop)
4706 {
4707   FENTRY;
4708 
4709   /* if true label then we jump if condition
4710      supplied is true */
4711   if (IC_TRUE (ic))
4712     {
4713       DEBUGpic16_emitcode ("; ***", "%d - assuming is in bit space", __LINE__);
4714       pic16_emitpcode (POC_BTFSC, jop);
4715 
4716       pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_TRUE (ic)->key));
4717       pic16_emitcode (" goto", "_%05d_DS_", labelKey2num (IC_TRUE (ic)->key + pic16_labelOffset));
4718 
4719     }
4720   else
4721     {
4722       /* false label is present */
4723       DEBUGpic16_emitcode ("; ***", "%d - assuming is in bit space", __LINE__);
4724       pic16_emitpcode (POC_BTFSS, jop);
4725 
4726       pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_FALSE (ic)->key));
4727       pic16_emitcode (" goto", "_%05d_DS_", labelKey2num (IC_FALSE (ic)->key + pic16_labelOffset));
4728     }
4729 
4730 
4731   /* mark the icode as generated */
4732   ic->generated = 1;
4733 }
4734 
4735 #if 0
4736 // not needed ATM
4737 
4738 /*-----------------------------------------------------------------*/
4739 /* genSkip                                                         */
4740 /*-----------------------------------------------------------------*/
4741 static void
4742 genSkip (iCode * ifx, int status_bit)
4743 {
4744   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
4745   if (!ifx)
4746     return;
4747 
4748   if (IC_TRUE (ifx))
4749     {
4750       switch (status_bit)
4751         {
4752         case 'z':
4753           emitSKPNZ;
4754           break;
4755 
4756         case 'c':
4757           emitSKPNC;
4758           break;
4759 
4760         case 'd':
4761           emitSKPDC;
4762           break;
4763 
4764         }
4765 
4766       pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_TRUE (ifx)->key));
4767       // pic16_emitcode("goto","_%05d_DS_",labelKey2num (IC_TRUE(ifx)->key + pic16_labelOffset));
4768 
4769     }
4770   else
4771     {
4772 
4773       switch (status_bit)
4774         {
4775 
4776         case 'z':
4777           emitSKPZ;
4778           break;
4779 
4780         case 'c':
4781           emitSKPC;
4782           break;
4783 
4784         case 'd':
4785           emitSKPDC;
4786           break;
4787         }
4788       pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_FALSE (ifx)->key));
4789       // pic16_emitcode("goto","_%05d_DS_",labelKey2num (IC_FALSE(ifx)->key + pic16_labelOffset));
4790 
4791     }
4792 
4793 }
4794 #endif
4795 
4796 /*-----------------------------------------------------------------*/
4797 /* genSkipc                                                        */
4798 /*-----------------------------------------------------------------*/
4799 static void
genSkipc(resolvedIfx * rifx)4800 genSkipc (resolvedIfx * rifx)
4801 {
4802   DEBUGpic16_emitcode ("; ***", "%s  %d rifx= %p", __FUNCTION__, __LINE__, rifx);
4803 
4804   if (!rifx)
4805     return;
4806 
4807   if (rifx->condition)
4808     emitSKPNC;
4809   else
4810     emitSKPC;
4811 
4812   pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rifx->lbl->key));
4813   rifx->generated = 1;
4814 }
4815 
4816 /*-----------------------------------------------------------------*/
4817 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4818 /*                  aop (if it's NOT a literal) or from lit (if    */
4819 /*                  aop is a literal)                              */
4820 /*-----------------------------------------------------------------*/
4821 void
mov2w_regOrLit(asmop * aop,unsigned long lit,int offset)4822 mov2w_regOrLit (asmop * aop, unsigned long lit, int offset)
4823 {
4824   if (aop->type == AOP_LIT)
4825     {
4826       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit >> (offset * 8)));
4827     }
4828   else
4829     {
4830       pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4831     }
4832 }
4833 
4834 /*-----------------------------------------------------------------*/
4835 /* genCmp :- greater or less than comparison                       */
4836 /*-----------------------------------------------------------------*/
4837 
4838 /* genCmp performs a left < right comparison, stores
4839  * the outcome in result (if != NULL) and generates
4840  * control flow code for the ifx (if != NULL).
4841  *
4842  * This version leaves in sequences like
4843  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4844  * which should be optmized by the peephole
4845  * optimizer - RN 2005-01-01 */
4846 static void
genCmp(operand * left,operand * right,operand * result,iCode * ifx,int sign)4847 genCmp (operand * left, operand * right, operand * result, iCode * ifx, int sign)
4848 {
4849   resolvedIfx rIfx;
4850   int size;
4851   int offs;
4852   symbol *templbl;
4853   operand *dummy;
4854   unsigned long lit;
4855   unsigned long mask;
4856   int performedLt;
4857 
4858   FENTRY;
4859 
4860   assert (left && right);
4861   assert (AOP_SIZE (left) == AOP_SIZE (right));
4862 
4863   size = AOP_SIZE (right) - 1;
4864   mask = (0x100UL << (size * 8)) - 1;
4865   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4866   performedLt = 1;
4867   templbl = NULL;
4868   lit = 0;
4869 
4870   resolveIfx (&rIfx, ifx);
4871 
4872   /* handle for special cases */
4873   if (pic16_genCmp_special (left, right, result, ifx, &rIfx, sign))
4874     return;
4875 
4876   /**********************************************************************
4877    * handle bits - bit compares are promoted to int compares seemingly! *
4878    **********************************************************************/
4879 #if 0
4880   // THIS IS COMPLETELY UNTESTED!
4881   if (AOP_TYPE (left) == AOP_CRY && AOP_TYPE (right) == AOP_CRY)
4882     {
4883       pCodeOp *pcleft = pic16_popGet (AOP (left), 0);
4884       pCodeOp *pcright = pic16_popGet (AOP (right), 0);
4885       assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4886 
4887       emitSETC;
4888       // 1 < {0,1} is false --> clear C by skipping the next instruction
4889       //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4890       pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP (left), 0));
4891       // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4892       pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet (AOP (right), 0), PCORB (pcright)->bit));
4893       emitCLRC;                 // only skipped for left=0 && right=1
4894 
4895       goto correct_result_in_carry;
4896     }                           // if
4897 #endif
4898 
4899   /*************************************************
4900    * make sure that left is register (or the like) *
4901    *************************************************/
4902   if (!isAOP_REGlike (left))
4903     {
4904       DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE (left), AOP_TYPE (right));
4905       assert (isAOP_LIT (left));
4906       assert (isAOP_REGlike (right));
4907       // swap left and right
4908       // left < right <==> right > left <==> (right >= left + 1)
4909       lit = ulFromVal (AOP (left)->aopu.aop_lit);
4910 
4911       if ((!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)))
4912         {
4913           // MAXVALUE < right? always false
4914           if (performedLt)
4915             emitCLRC;
4916           else
4917             emitSETC;
4918           goto correct_result_in_carry;
4919         }                       // if
4920 
4921       // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4922       // that's why we handled it above.
4923       lit++;
4924 
4925       dummy = left;
4926       left = right;
4927       right = dummy;
4928 
4929       performedLt ^= 1;         // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4930     }
4931   else if (isAOP_LIT (right))
4932     {
4933       lit = ulFromVal (AOP (right)->aopu.aop_lit);
4934     }                           // if
4935 
4936   assert (isAOP_REGlike (left));        // left must be register or the like
4937   assert (isAOP_REGlike (right) || isAOP_LIT (right));  // right may be register-like or a literal
4938 
4939   /*************************************************
4940    * special cases go here                         *
4941    *************************************************/
4942 
4943   if (isAOP_LIT (right))
4944     {
4945       if (!sign)
4946         {
4947           // unsigned comparison to a literal
4948           DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size + 1);
4949           if (lit == 0)
4950             {
4951               // unsigned left < 0? always false
4952               if (performedLt)
4953                 emitCLRC;
4954               else
4955                 emitSETC;
4956               goto correct_result_in_carry;
4957             }
4958         }
4959       else
4960         {
4961           // signed comparison to a literal
4962           DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size + 1,
4963                    mask);
4964           if ((lit & mask) == ((0x80 << (size * 8)) & mask))
4965             {
4966               // signed left < 0x80000000? always false
4967               if (performedLt)
4968                 emitCLRC;
4969               else
4970                 emitSETC;
4971               goto correct_result_in_carry;
4972             }
4973           else if (lit == 0)
4974             {
4975               // compare left < 0; set CARRY if SIGNBIT(left) is set
4976               if (performedLt)
4977                 emitSETC;
4978               else
4979                 emitCLRC;
4980               pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet (AOP (left), size), 7));
4981               if (performedLt)
4982                 emitCLRC;
4983               else
4984                 emitSETC;
4985               goto correct_result_in_carry;
4986             }
4987         }                       // if (!sign)
4988     }                           // right is literal
4989 
4990   /*************************************************
4991    * perform a general case comparison             *
4992    * make sure we get CARRY==1 <==> left >= right  *
4993    *************************************************/
4994   // compare most significant bytes
4995   //DEBUGpc ("comparing bytes at offset %d", size);
4996   if (!sign)
4997     {
4998       // unsigned comparison
4999       if (AOP_TYPE (left) == AOP_PCODE && AOP (left)->aopu.pcop->type == PO_IMMEDIATE)
5000         {
5001           // right >= left(PO_IMMEDIATE)
5002           pic16_emitpcode (POC_MOVLW, pic16_popGetImmed (AOP (left), size, 1)); // left+1
5003           pic16_emitpcode (POC_SUBFW, pic16_popGet(AOP (right), size));
5004           performedLt = 0;
5005         }
5006       else if (AOP_TYPE (right) == AOP_PCODE && AOP (right)->aopu.pcop->type == PO_IMMEDIATE)
5007         {
5008           // left < right(PO_IMMEDIATE)
5009           pic16_emitpcode (POC_MOVLW, pic16_popGetImmed (AOP (right), size, 0));  // right+0
5010           pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP (left), size));
5011         }
5012       else
5013         {
5014           mov2w_regOrLit (AOP(right), lit, size);
5015           pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP (left), size));
5016         }
5017     }
5018   else
5019     {
5020       // signed comparison
5021       // (add 2^n to both operands then perform an unsigned comparison)
5022       if (isAOP_LIT (right))
5023         {
5024           // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5025           unsigned char litbyte = (lit >> (8 * size)) & 0xFF;
5026 
5027           if (litbyte == 0x80)
5028             {
5029               // left >= 0x80 -- always true, but more bytes to come
5030               pic16_mov2w (AOP (left), size);
5031               pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80));      // set ZERO flag
5032               emitSETC;
5033             }
5034           else
5035             {
5036               // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5037               pic16_mov2w (AOP (left), size);
5038               pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5039               pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5040             }                   // if
5041         }
5042       else
5043         {
5044           /* using PRODL as a temporary register here */
5045           pCodeOp *pctemp = pic16_popCopyReg (&pic16_pc_prodl);
5046           //pCodeOp *pctemp = pic16_popGetTempReg(1);
5047           pic16_mov2w (AOP (left), size);
5048           pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5049           pic16_emitpcode (POC_MOVWF, pctemp);
5050           pic16_mov2w (AOP (right), size);
5051           pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5052           pic16_emitpcode (POC_SUBFW, pctemp);
5053           //pic16_popReleaseTempReg(pctemp, 1);
5054         }
5055     }                           // if (!sign)
5056 
5057   // compare remaining bytes (treat as unsigned case from above)
5058   templbl = newiTempLabel (NULL);
5059   offs = size;
5060   while (offs--)
5061     {
5062       //DEBUGpc ("comparing bytes at offset %d", offs);
5063       pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5064 
5065       if (AOP_TYPE (left) == AOP_PCODE && AOP (left)->aopu.pcop->type == PO_IMMEDIATE)
5066         {
5067           // right >= left(PO_IMMEDIATE)
5068           pic16_emitpcode (POC_MOVLW, pic16_popGetImmed( AOP (left), offs, 1)); // left+1
5069           pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP (right), offs));
5070           performedLt = 0;
5071         }
5072       else if (AOP_TYPE (right) == AOP_PCODE && AOP (right)->aopu.pcop->type == PO_IMMEDIATE)
5073         {
5074           // left < right(PO_IMMEDIATE)
5075           pic16_emitpcode (POC_MOVLW, pic16_popGetImmed (AOP (right), offs, 0));  // right+0
5076           pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP (left), offs));
5077         }
5078       else
5079         {
5080           mov2w_regOrLit (AOP (right), lit, offs);
5081           pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP (left), offs));
5082         }
5083     }                           // while (offs)
5084   pic16_emitpLabel (templbl->key);
5085   goto result_in_carry;
5086 
5087 result_in_carry:
5088 
5089   /****************************************************
5090    * now CARRY contains the result of the comparison: *
5091    * SUBWF sets CARRY iff                             *
5092    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5093    * (F=left, W=right)                                *
5094    ****************************************************/
5095 
5096   if (performedLt)
5097     {
5098       if (result && AOP_TYPE (result) != AOP_CRY)
5099         {
5100           // value will be stored
5101           emitTOGC;
5102         }
5103       else
5104         {
5105           // value wil only be used in the following genSkipc()
5106           rIfx.condition ^= 1;
5107         }
5108     }                           // if
5109 
5110 correct_result_in_carry:
5111 
5112   // assign result to variable (if neccessary)
5113   if (result && AOP_TYPE (result) != AOP_CRY)
5114     {
5115       //DEBUGpc ("assign result");
5116       size = AOP_SIZE (result);
5117       while (size--)
5118         {
5119           pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), size));
5120         }                       // while
5121       pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), 0));
5122     }                           // if (result)
5123 
5124   // perform conditional jump
5125   if (ifx)
5126     {
5127       //DEBUGpc ("generate control flow");
5128       genSkipc (&rIfx);
5129       ifx->generated = 1;
5130     }                           // if
5131 }
5132 
5133 /*-----------------------------------------------------------------*/
5134 /* genCmpGt :- greater than comparison                             */
5135 /*-----------------------------------------------------------------*/
5136 static void
genCmpGt(iCode * ic,iCode * ifx)5137 genCmpGt (iCode * ic, iCode * ifx)
5138 {
5139   operand *left, *right, *result;
5140   sym_link *letype, *retype;
5141   int sign;
5142 
5143   FENTRY;
5144 
5145   left = IC_LEFT (ic);
5146   right = IC_RIGHT (ic);
5147   result = IC_RESULT (ic);
5148 
5149   sign = 0;
5150   if (IS_SPEC (operandType (left)) && IS_SPEC (operandType (right)))
5151     {
5152       letype = getSpec (operandType (left));
5153       retype = getSpec (operandType (right));
5154       sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5155     }
5156 
5157   /* assign the amsops */
5158   pic16_aopOp (left, ic, FALSE);
5159   pic16_aopOp (right, ic, FALSE);
5160   pic16_aopOp (result, ic, TRUE);
5161 
5162   genCmp (right, left, result, ifx, sign);
5163 
5164   pic16_freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5165   pic16_freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5166   pic16_freeAsmop (result, NULL, ic, TRUE);
5167 }
5168 
5169 /*-----------------------------------------------------------------*/
5170 /* genCmpLt - less than comparisons                                */
5171 /*-----------------------------------------------------------------*/
5172 static void
genCmpLt(iCode * ic,iCode * ifx)5173 genCmpLt (iCode * ic, iCode * ifx)
5174 {
5175   operand *left, *right, *result;
5176   sym_link *letype, *retype;
5177   int sign;
5178 
5179   FENTRY;
5180 
5181   left = IC_LEFT (ic);
5182   right = IC_RIGHT (ic);
5183   result = IC_RESULT (ic);
5184 
5185   sign = 0;
5186   if (IS_SPEC (operandType (left)) && IS_SPEC (operandType (right)))
5187     {
5188       letype = getSpec (operandType (left));
5189       retype = getSpec (operandType (right));
5190       sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5191     }
5192 
5193   /* assign the amsops */
5194   pic16_aopOp (left, ic, FALSE);
5195   pic16_aopOp (right, ic, FALSE);
5196   pic16_aopOp (result, ic, TRUE);
5197 
5198   genCmp (left, right, result, ifx, sign);
5199 
5200   pic16_freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5201   pic16_freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5202   pic16_freeAsmop (result, NULL, ic, TRUE);
5203 }
5204 
5205 /*-----------------------------------------------------------------*/
5206 /* pic16_isLitOp - check if operand has to be treated as literal   */
5207 /*-----------------------------------------------------------------*/
5208 bool
pic16_isLitOp(operand * op)5209 pic16_isLitOp (operand * op)
5210 {
5211   return ((AOP_TYPE (op) == AOP_LIT)
5212           || ((AOP_TYPE (op) == AOP_PCODE)
5213               && ((AOP (op)->aopu.pcop->type == PO_LITERAL) || (AOP (op)->aopu.pcop->type == PO_IMMEDIATE))));
5214 }
5215 
5216 /*-----------------------------------------------------------------*/
5217 /* pic16_isLitAop - check if operand has to be treated as literal  */
5218 /*-----------------------------------------------------------------*/
5219 bool
pic16_isLitAop(asmop * aop)5220 pic16_isLitAop (asmop * aop)
5221 {
5222   return ((aop->type == AOP_LIT)
5223           || ((aop->type == AOP_PCODE) && ((aop->aopu.pcop->type == PO_LITERAL) || (aop->aopu.pcop->type == PO_IMMEDIATE))));
5224 }
5225 
5226 
5227 
5228 /*-----------------------------------------------------------------*/
5229 /* genCmpEq - generates code for equal to                          */
5230 /*-----------------------------------------------------------------*/
5231 static void
genCmpEq(iCode * ic,iCode * ifx)5232 genCmpEq (iCode * ic, iCode * ifx)
5233 {
5234   operand *left, *right, *result;
5235   symbol *falselbl = newiTempLabel (NULL);
5236   symbol *donelbl = newiTempLabel (NULL);
5237 
5238   int preserve_result = 0;
5239   int generate_result = 0;
5240   int i = 0;
5241   unsigned long lit = -1;
5242 
5243   FENTRY;
5244 
5245   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5246   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5247   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5248 
5249   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5250 
5251   if ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (left) == AOP_CRY))
5252     {
5253       werror (W_POSSBUG2, __FILE__, __LINE__);
5254       DEBUGpic16_emitcode ("; ***", "%s  %d -- ERROR", __FUNCTION__, __LINE__);
5255       fprintf (stderr, "%s  %d error - left/right CRY operands not supported\n", __FUNCTION__, __LINE__);
5256       goto release;
5257     }
5258 
5259   if (pic16_isLitOp (left) || (AOP_TYPE (right) == AOP_ACC))
5260     {
5261       operand *tmp = right;
5262       right = left;
5263       left = tmp;
5264     }
5265 
5266   if (AOP_TYPE (right) == AOP_LIT)
5267     {
5268       lit = ulFromVal (AOP (right)->aopu.aop_lit);
5269     }
5270 
5271   if (regsInCommon (left, result) || regsInCommon (right, result))
5272     preserve_result = 1;
5273 
5274   if (result && AOP_SIZE (result))
5275     generate_result = 1;
5276 
5277   if (generate_result && !preserve_result)
5278     {
5279       for (i = 0; i < AOP_SIZE (result); i++)
5280         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), i));
5281     }
5282 
5283   assert (AOP_SIZE (left) == AOP_SIZE (right));
5284   for (i = 0; i < AOP_SIZE (left); i++)
5285     {
5286       if (AOP_TYPE (left) != AOP_ACC)
5287         {
5288           if (pic16_isLitOp (left))
5289             pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (left), i));
5290           else
5291             pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), i));
5292         }
5293       if (pic16_isLitOp (right))
5294         {
5295           if (pic16_isLitOp (left) || (0 != ((lit >> (8 * i)) & 0x00FF)))
5296             {
5297               pic16_emitpcode (POC_XORLW, pic16_popGet (AOP (right), i));
5298             }
5299         }
5300       else
5301         pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (right), i));
5302 
5303       pic16_emitpcode (POC_BNZ, pic16_popGetLabel (falselbl->key));
5304     }
5305 
5306   // result == true
5307 
5308   if (generate_result && preserve_result)
5309     {
5310       for (i = 0; i < AOP_SIZE (result); i++)
5311         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), i));
5312     }
5313 
5314   if (generate_result)
5315     pic16_emitpcode (POC_INCF, pic16_popGet (AOP (result), 0)); // result = true
5316 
5317   if (generate_result && preserve_result)
5318     pic16_emitpcode (POC_GOTO, pic16_popGetLabel (donelbl->key));
5319 
5320   if (ifx && IC_TRUE (ifx))
5321     pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_TRUE (ifx)->key));
5322 
5323   if (ifx && IC_FALSE (ifx))
5324     pic16_emitpcode (POC_GOTO, pic16_popGetLabel (donelbl->key));
5325 
5326   pic16_emitpLabel (falselbl->key);
5327 
5328   // result == false
5329 
5330   if (ifx && IC_FALSE (ifx))
5331     pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_FALSE (ifx)->key));
5332 
5333   if (generate_result && preserve_result)
5334     {
5335       for (i = 0; i < AOP_SIZE (result); i++)
5336         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), i));
5337     }
5338 
5339   pic16_emitpLabel (donelbl->key);
5340 
5341   if (ifx)
5342     ifx->generated = 1;
5343 
5344 release:
5345   pic16_freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5346   pic16_freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5347   pic16_freeAsmop (result, NULL, ic, TRUE);
5348 
5349 }
5350 
5351 
5352 #if 0
5353 // old version kept for reference
5354 
5355 /*-----------------------------------------------------------------*/
5356 /* genCmpEq - generates code for equal to                          */
5357 /*-----------------------------------------------------------------*/
5358 static void
5359 genCmpEq (iCode * ic, iCode * ifx)
5360 {
5361   operand *left, *right, *result;
5362   unsigned long lit = 0L;
5363   int size, offset = 0;
5364   symbol *falselbl = newiTempLabel (NULL);
5365 
5366 
5367   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
5368 
5369   if (ifx)
5370     DEBUGpic16_emitcode ("; ifx is non-null", "");
5371   else
5372     DEBUGpic16_emitcode ("; ifx is null", "");
5373 
5374   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5375   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5376   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5377 
5378   size = max (AOP_SIZE (left), AOP_SIZE (right));
5379 
5380   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5381 
5382   /* if literal, literal on the right or
5383      if the right is in a pointer register and left
5384      is not */
5385   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT))
5386     {
5387       operand *tmp = right;
5388       right = left;
5389       left = tmp;
5390     }
5391 
5392 
5393   if (ifx && !AOP_SIZE (result))
5394     {
5395       symbol *tlbl;
5396       DEBUGpic16_emitcode ("; ***", "%s  %d CASE 1", __FUNCTION__, __LINE__);
5397       /* if they are both bit variables */
5398       if (AOP_TYPE (left) == AOP_CRY && ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5399         {
5400           DEBUGpic16_emitcode ("; ***", "%s  %d CASE 11", __FUNCTION__, __LINE__);
5401           if (AOP_TYPE (right) == AOP_LIT)
5402             {
5403               unsigned long lit = ulFromVal (AOP (right)->aopu.aop_lit);
5404               if (lit == 0L)
5405                 {
5406                   pic16_emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5407                   pic16_emitcode ("cpl", "c");
5408                 }
5409               else if (lit == 1L)
5410                 {
5411                   pic16_emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5412                 }
5413               else
5414                 {
5415                   pic16_emitcode ("clr", "c");
5416                 }
5417               /* AOP_TYPE(right) == AOP_CRY */
5418             }
5419           else
5420             {
5421               symbol *lbl = newiTempLabel (NULL);
5422               pic16_emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5423               pic16_emitcode ("jb", "%s,%05d_DS_", AOP (right)->aopu.aop_dir, labelKey2num (lbl->key));
5424               pic16_emitcode ("cpl", "c");
5425               pic16_emitcode ("", "%05d_DS_:", labelKey2num (lbl->key));
5426             }
5427           /* if true label then we jump if condition
5428              supplied is true */
5429           tlbl = newiTempLabel (NULL);
5430           if (IC_TRUE (ifx))
5431             {
5432               pic16_emitcode ("jnc", "%05d_DS_", labelKey2num (tlbl->key));
5433               pic16_emitcode ("ljmp", "%05d_DS_", labelKey2num (IC_TRUE (ifx)->key));
5434             }
5435           else
5436             {
5437               pic16_emitcode ("jc", "%05d_DS_", labelKey2num (tlbl->key));
5438               pic16_emitcode ("ljmp", "%05d_DS_", labelKey2num (IC_FALSE (ifx)->key));
5439             }
5440           pic16_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key + pic16_labelOffset));
5441 
5442           {
5443             /* left and right are both bit variables, result is carry */
5444             resolvedIfx rIfx;
5445 
5446             resolveIfx (&rIfx, ifx);
5447 
5448             pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (left), 0));
5449             pic16_emitpcode (POC_ANDFW, pic16_popGet (AOP (left), 0));
5450             pic16_emitpcode (POC_BTFSC, pic16_popGet (AOP (right), 0));
5451             pic16_emitpcode (POC_ANDLW, pic16_popGet (AOP (left), 0));
5452             genSkipz2 (&rIfx, 0);
5453           }
5454         }
5455       else
5456         {
5457 
5458           DEBUGpic16_emitcode ("; ***", "%s  %d CASE 12", __FUNCTION__, __LINE__);
5459 
5460           /* They're not both bit variables. Is the right a literal? */
5461           if (AOP_TYPE (right) == AOP_LIT)
5462             {
5463               lit = ulFromVal (AOP (right)->aopu.aop_lit);
5464 
5465               switch (size)
5466                 {
5467 
5468                 case 1:
5469                   switch (lit & 0xff)
5470                     {
5471                     case 1:
5472                       if (IC_TRUE (ifx))
5473                         {
5474                           pic16_emitpcode (POC_DECFW, pic16_popGet (AOP (left), offset));
5475                           emitSKPNZ;
5476                           pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_TRUE (ifx)->key));
5477                         }
5478                       else
5479                         {
5480                           pic16_emitpcode (POC_DECFSZW, pic16_popGet (AOP (left), offset));
5481                           pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_FALSE (ifx)->key));
5482                         }
5483                       break;
5484                     case 0xff:
5485                       if (IC_TRUE (ifx))
5486                         {
5487                           pic16_emitpcode (POC_INCFW, pic16_popGet (AOP (left), offset));
5488                           emitSKPNZ;
5489                           pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_TRUE (ifx)->key));
5490                         }
5491                       else
5492                         {
5493                           pic16_emitpcode (POC_INCFSZW, pic16_popGet (AOP (left), offset));
5494                           pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_FALSE (ifx)->key));
5495                         }
5496                       break;
5497                     default:
5498                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5499                       if (lit)
5500                         pic16_emitpcode (POC_XORLW, pic16_popGetLit (lit & 0xff));
5501                       genSkip (ifx, 'z');
5502                     }           // switch lit
5503 
5504 
5505                   /* end of size == 1 */
5506                   break;
5507 
5508                 case 2:
5509                   genc16bit2lit (left, lit, offset);
5510                   genSkip (ifx, 'z');
5511                   break;
5512                   /* end of size == 2 */
5513 
5514                 default:
5515                   /* size is 4 */
5516                   if (lit == 0)
5517                     {
5518                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), 0));
5519                       pic16_emitpcode (POC_IORFW, pic16_popGet (AOP (left), 1));
5520                       pic16_emitpcode (POC_IORFW, pic16_popGet (AOP (left), 2));
5521                       pic16_emitpcode (POC_IORFW, pic16_popGet (AOP (left), 3));
5522                       genSkip (ifx, 'z');
5523                     }
5524                   else
5525                     {
5526                       /* search for patterns that can be optimized */
5527 
5528                       genc16bit2lit (left, lit, 0);
5529                       lit >>= 16;
5530                       if (lit)
5531                         {
5532                           if (IC_TRUE (ifx))
5533                             emitSKPZ;   // if hi word unequal
5534                           else
5535                             emitSKPNZ;  // if hi word equal
5536                           // fail early
5537                           pic16_emitpcode (POC_GOTO, pic16_popGetLabel (falselbl->key));
5538                           genc16bit2lit (left, lit, 2);
5539                           genSkip (ifx, 'z');
5540                         }
5541                       else
5542                         {
5543                           pic16_emitpcode (POC_IORFW, pic16_popGet (AOP (left), 2));
5544                           pic16_emitpcode (POC_IORFW, pic16_popGet (AOP (left), 3));
5545                           genSkip (ifx, 'z');
5546                         }
5547                     }
5548                   pic16_emitpLabel (falselbl->key);
5549                   break;
5550 
5551                 }               // switch size
5552 
5553               ifx->generated = 1;
5554               goto release;
5555 
5556 
5557             }
5558           else if (AOP_TYPE (right) == AOP_CRY)
5559             {
5560               /* we know the left is not a bit, but that the right is */
5561               pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5562               pic16_emitpcode (((IC_TRUE (ifx)) ? POC_BTFSC : POC_BTFSS), pic16_popGet (AOP (right), offset));
5563               pic16_emitpcode (POC_XORLW, pic16_popGetLit (1));
5564 
5565               /* if the two are equal, then W will be 0 and the Z bit is set
5566                * we could test Z now, or go ahead and check the high order bytes if
5567                * the variable we're comparing is larger than a byte. */
5568 
5569               while (--size)
5570                 pic16_emitpcode (POC_IORFW, pic16_popGet (AOP (left), offset));
5571 
5572               if (IC_TRUE (ifx))
5573                 {
5574                   emitSKPNZ;
5575                   pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_TRUE (ifx)->key));
5576                   // pic16_emitcode(" goto","_%05d_DS_",labelKey2num (IC_TRUE(ifx)->key + pic16_labelOffset));
5577                 }
5578               else
5579                 {
5580                   emitSKPZ;
5581                   pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_FALSE (ifx)->key));
5582                   // pic16_emitcode(" goto","_%05d_DS_",labelKey2num (IC_FALSE(ifx)->key + pic16_labelOffset));
5583                 }
5584 
5585             }
5586           else
5587             {
5588               /* They're both variables that are larger than bits */
5589               int s = size;
5590 
5591               tlbl = newiTempLabel (NULL);
5592 
5593               while (size--)
5594                 {
5595                   pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5596                   pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (right), offset));
5597 
5598                   if (IC_TRUE (ifx))
5599                     {
5600                       if (size)
5601                         {
5602                           emitSKPZ;
5603 
5604                           DEBUGpic16_emitcode (";", "\tIC_TRUE emitSKPZ");
5605 
5606                           pic16_emitpcode (POC_GOTO, pic16_popGetLabel (tlbl->key));
5607                           pic16_emitcode (" goto", "_%05d_DS_", labelKey2num (tlbl->key + pic16_labelOffset));
5608                         }
5609                       else
5610                         {
5611                           emitSKPNZ;
5612 
5613                           DEBUGpic16_emitcode (";", "\tIC_TRUE emitSKPNZ");
5614 
5615 
5616                           pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_TRUE (ifx)->key));
5617                           pic16_emitcode (" goto", "_%05d_DS_", labelKey2num (IC_TRUE (ifx)->key + pic16_labelOffset));
5618                         }
5619                     }
5620                   else
5621                     {
5622                       emitSKPZ;
5623 
5624                       DEBUGpic16_emitcode (";", "\tnot IC_TRUE emitSKPZ");
5625 
5626                       pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_FALSE (ifx)->key));
5627                       pic16_emitcode (" goto", "_%05d_DS_", labelKey2num (IC_FALSE (ifx)->key + pic16_labelOffset));
5628                     }
5629                   offset++;
5630                 }
5631               if (s > 1 && IC_TRUE (ifx))
5632                 {
5633                   pic16_emitpLabel (tlbl->key);
5634                   pic16_emitcode ("", "_%05d_DS_:", labelKey2num (tlbl->key + pic16_labelOffset));
5635                 }
5636             }
5637         }
5638       /* mark the icode as generated */
5639       ifx->generated = 1;
5640       goto release;
5641     }
5642 
5643   /* if they are both bit variables */
5644   if (AOP_TYPE (left) == AOP_CRY && ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5645     {
5646       DEBUGpic16_emitcode ("; ***", "%s  %d CASE 2", __FUNCTION__, __LINE__);
5647       if (AOP_TYPE (right) == AOP_LIT)
5648         {
5649           unsigned long lit = ulFromVal (AOP (right)->aopu.aop_lit);
5650           if (lit == 0L)
5651             {
5652               pic16_emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5653               pic16_emitcode ("cpl", "c");
5654             }
5655           else if (lit == 1L)
5656             {
5657               pic16_emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5658             }
5659           else
5660             {
5661               pic16_emitcode ("clr", "c");
5662             }
5663           /* AOP_TYPE(right) == AOP_CRY */
5664         }
5665       else
5666         {
5667           symbol *lbl = newiTempLabel (NULL);
5668           pic16_emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5669           pic16_emitcode ("jb", "%s,%05d_DS_", AOP (right)->aopu.aop_dir, labelKey2num (lbl->key));
5670           pic16_emitcode ("cpl", "c");
5671           pic16_emitcode ("", "%05d_DS_:", labelKey2num (lbl->key));
5672         }
5673       /* c = 1 if egal */
5674       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5675         {
5676           pic16_outBitC (result);
5677           goto release;
5678         }
5679       if (ifx)
5680         {
5681           genIfxJump (ifx, "c");
5682           goto release;
5683         }
5684       /* if the result is used in an arithmetic operation
5685          then put the result in place */
5686       pic16_outBitC (result);
5687     }
5688   else
5689     {
5690 
5691       DEBUGpic16_emitcode ("; ***", "%s  %d CASE 3", __FUNCTION__, __LINE__);
5692       gencjne (left, right, result, ifx);
5693       /*
5694          if(ifx)
5695          gencjne(left,right,newiTempLabel(NULL));
5696          else {
5697          if(IC_TRUE(ifx)->key)
5698          gencjne(left,right,IC_TRUE(ifx)->key);
5699          else
5700          gencjne(left,right,IC_FALSE(ifx)->key);
5701          ifx->generated = 1;
5702          goto release ;
5703          }
5704          if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5705          pic16_aopPut(AOP(result),"a",0);
5706          goto release ;
5707          }
5708 
5709          if (ifx) {
5710          genIfxJump (ifx,"a");
5711          goto release ;
5712          }
5713        */
5714       /* if the result is used in an arithmetic operation
5715          then put the result in place */
5716       /*
5717          if (AOP_TYPE(result) != AOP_CRY)
5718          pic16_outAcc(result);
5719        */
5720       /* leave the result in acc */
5721     }
5722 
5723 release:
5724   pic16_freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5725   pic16_freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5726   pic16_freeAsmop (result, NULL, ic, TRUE);
5727 }
5728 #endif
5729 
5730 /*-----------------------------------------------------------------*/
5731 /* genAndOp - for && operation                                     */
5732 /*-----------------------------------------------------------------*/
5733 static void
genAndOp(iCode * ic)5734 genAndOp (iCode * ic)
5735 {
5736   operand *left, *right, *result;
5737   /*     symbol *tlbl; */
5738 
5739   FENTRY;
5740 
5741   /* note here that && operations that are in an
5742      if statement are taken away by backPatchLabels
5743      only those used in arthmetic operations remain */
5744   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5745   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5746   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5747 
5748   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5749 
5750   pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), 0));
5751   pic16_emitpcode (POC_ANDFW, pic16_popGet (AOP (right), 0));
5752   pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
5753 
5754   /* if both are bit variables */
5755   /*     if (AOP_TYPE(left) == AOP_CRY && */
5756   /*         AOP_TYPE(right) == AOP_CRY ) { */
5757   /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5758   /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5759   /*         pic16_outBitC(result); */
5760   /*     } else { */
5761   /*         tlbl = newiTempLabel(NULL); */
5762   /*         pic16_toBoolean(left);     */
5763   /*         pic16_emitcode("jz","%05d_DS_",labelKey2num (tlbl->key)); */
5764   /*         pic16_toBoolean(right); */
5765   /*         pic16_emitcode("","%05d_DS_:",labelKey2num (tlbl->key)); */
5766   /*         pic16_outBitAcc(result); */
5767   /*     } */
5768 
5769   pic16_freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5770   pic16_freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5771   pic16_freeAsmop (result, NULL, ic, TRUE);
5772 }
5773 
5774 
5775 /*-----------------------------------------------------------------*/
5776 /* genOrOp - for || operation                                      */
5777 /*-----------------------------------------------------------------*/
5778 /*
5779   tsd pic port -
5780   modified this code, but it doesn't appear to ever get called
5781 */
5782 
5783 static void
genOrOp(iCode * ic)5784 genOrOp (iCode * ic)
5785 {
5786   operand *left, *right, *result;
5787   symbol *tlbl;
5788 
5789   FENTRY;
5790 
5791   /* note here that || operations that are in an
5792      if statement are taken away by backPatchLabels
5793      only those used in arthmetic operations remain */
5794   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5795   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5796   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5797 
5798   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5799 
5800   /* if both are bit variables */
5801   if (AOP_TYPE (left) == AOP_CRY && AOP_TYPE (right) == AOP_CRY)
5802     {
5803       pic16_emitcode ("clrc", "");
5804       pic16_emitcode ("btfss", "(%s >> 3), (%s & 7)", AOP (left)->aopu.aop_dir, AOP (left)->aopu.aop_dir);
5805       pic16_emitcode ("btfsc", "(%s >> 3), (%s & 7)", AOP (right)->aopu.aop_dir, AOP (right)->aopu.aop_dir);
5806       pic16_emitcode ("setc", "");
5807 
5808     }
5809   else
5810     {
5811       tlbl = newiTempLabel (NULL);
5812       pic16_toBoolean (left);
5813       emitSKPZ;
5814       pic16_emitcode ("goto", "%05d_DS_", labelKey2num (tlbl->key + pic16_labelOffset));
5815       pic16_toBoolean (right);
5816       pic16_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key + pic16_labelOffset));
5817 
5818       pic16_outBitAcc (result);
5819     }
5820 
5821   pic16_freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5822   pic16_freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5823   pic16_freeAsmop (result, NULL, ic, TRUE);
5824 }
5825 
5826 /*-----------------------------------------------------------------*/
5827 /* isLiteralBit - test if lit == 2^n                               */
5828 /*-----------------------------------------------------------------*/
5829 static int
isLiteralBit(unsigned long lit)5830 isLiteralBit (unsigned long lit)
5831 {
5832   unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5833                            0x100L, 0x200L, 0x400L, 0x800L,
5834                            0x1000L, 0x2000L, 0x4000L, 0x8000L,
5835                            0x10000L, 0x20000L, 0x40000L, 0x80000L,
5836                            0x100000L, 0x200000L, 0x400000L, 0x800000L,
5837                            0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5838                            0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
5839                          };
5840   int idx;
5841 
5842   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
5843   for (idx = 0; idx < 32; idx++)
5844     if (lit == pw[idx])
5845       return idx + 1;
5846   return 0;
5847 }
5848 
5849 /*-----------------------------------------------------------------*/
5850 /* continueIfTrue -                                                */
5851 /*-----------------------------------------------------------------*/
5852 static void
continueIfTrue(iCode * ic)5853 continueIfTrue (iCode * ic)
5854 {
5855   FENTRY;
5856   if (IC_TRUE (ic))
5857     pic16_emitcode ("ljmp", "%05d_DS_", labelKey2num (IC_TRUE (ic)->key));
5858   ic->generated = 1;
5859 }
5860 
5861 /*-----------------------------------------------------------------*/
5862 /* jmpIfTrue -                                                     */
5863 /*-----------------------------------------------------------------*/
5864 static void
jumpIfTrue(iCode * ic)5865 jumpIfTrue (iCode * ic)
5866 {
5867   FENTRY;
5868   if (!IC_TRUE (ic))
5869     pic16_emitcode ("ljmp", "%05d_DS_", labelKey2num (IC_FALSE (ic)->key));
5870   ic->generated = 1;
5871 }
5872 
5873 /*-----------------------------------------------------------------*/
5874 /* jmpTrueOrFalse -                                                */
5875 /*-----------------------------------------------------------------*/
5876 static void
jmpTrueOrFalse(iCode * ic,symbol * tlbl)5877 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5878 {
5879   // ugly but optimized by peephole
5880   FENTRY;
5881   if (IC_TRUE (ic))
5882     {
5883       symbol *nlbl = newiTempLabel (NULL);
5884       pic16_emitcode ("sjmp", "%05d_DS_", labelKey2num (nlbl->key));
5885       pic16_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
5886       pic16_emitcode ("ljmp", "%05d_DS_", labelKey2num (IC_TRUE (ic)->key));
5887       pic16_emitcode ("", "%05d_DS_:", labelKey2num (nlbl->key));
5888     }
5889   else
5890     {
5891       pic16_emitcode ("ljmp", "%05d_DS_", labelKey2num (IC_FALSE (ic)->key));
5892       pic16_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
5893     }
5894   ic->generated = 1;
5895 }
5896 
5897 /*-----------------------------------------------------------------*/
5898 /* genAnd  - code for and                                          */
5899 /*-----------------------------------------------------------------*/
5900 static void
genAnd(iCode * ic,iCode * ifx)5901 genAnd (iCode * ic, iCode * ifx)
5902 {
5903   operand *left, *right, *result;
5904   int size, offset = 0;
5905   unsigned long lit = 0L;
5906   resolvedIfx rIfx;
5907 
5908   FENTRY;
5909 
5910   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5911   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5912   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5913 
5914   resolveIfx (&rIfx, ifx);
5915 
5916   /* if left is a literal & right is not then exchange them */
5917   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) || AOP_NEEDSACC (left))
5918     {
5919       operand *tmp = right;
5920       right = left;
5921       left = tmp;
5922     }
5923 
5924   /* if result = right then exchange them */
5925   if (pic16_sameRegs (AOP (result), AOP (right)))
5926     {
5927       operand *tmp = right;
5928       right = left;
5929       left = tmp;
5930     }
5931 
5932   /* if right is bit then exchange them */
5933   if (AOP_TYPE (right) == AOP_CRY && AOP_TYPE (left) != AOP_CRY)
5934     {
5935       operand *tmp = right;
5936       right = left;
5937       left = tmp;
5938     }
5939 
5940   if (AOP_TYPE (right) == AOP_LIT)
5941     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5942 
5943   size = AOP_SIZE (result);
5944 
5945   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5946 
5947   // if(bit & yy)
5948   // result = bit & yy;
5949   if (AOP_TYPE (left) == AOP_CRY)
5950     {
5951       // c = bit & literal;
5952       if (AOP_TYPE (right) == AOP_LIT)
5953         {
5954           if (lit & 1)
5955             {
5956               if (size && pic16_sameRegs (AOP (result), AOP (left)))
5957                 // no change
5958                 goto release;
5959               pic16_emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5960             }
5961           else
5962             {
5963               // bit(result) = 0;
5964               if (size && (AOP_TYPE (result) == AOP_CRY))
5965                 {
5966                   pic16_emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5967                   goto release;
5968                 }
5969               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5970                 {
5971                   jumpIfTrue (ifx);
5972                   goto release;
5973                 }
5974               pic16_emitcode ("clr", "c");
5975             }
5976         }
5977       else
5978         {
5979           if (AOP_TYPE (right) == AOP_CRY)
5980             {
5981               // c = bit & bit;
5982               pic16_emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5983               pic16_emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5984             }
5985           else
5986             {
5987               // c = bit & val;
5988               MOVA (pic16_aopGet (AOP (right), 0, FALSE, FALSE));
5989               // c = lsb
5990               pic16_emitcode ("rrc", "a");
5991               pic16_emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5992             }
5993         }
5994       // bit = c
5995       // val = c
5996       if (size)
5997         pic16_outBitC (result);
5998       // if(bit & ...)
5999       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6000         genIfxJump (ifx, "c");
6001       goto release;
6002     }
6003 
6004   // if (val & 0xZZ)      - size = 0, ifx != FALSE -
6005   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6006   if ((AOP_TYPE (right) == AOP_LIT) && (AOP_TYPE (result) == AOP_CRY) && (AOP_TYPE (left) != AOP_CRY))
6007     {
6008       symbol *tlbl = newiTempLabel (NULL);
6009       int sizel = AOP_SIZE (left);
6010       int nonnull = 0;
6011       char emitBra;
6012 
6013       if (size)
6014         emitSETC;
6015 
6016       /* get number of non null bytes in literal */
6017       while (sizel--)
6018         {
6019           if (lit & (0xff << (sizel * 8)))
6020             ++nonnull;
6021         }
6022 
6023       emitBra = nonnull || rIfx.condition;
6024 
6025       for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
6026         {
6027           unsigned char bytelit = lit & 0xFF;
6028 
6029           if (bytelit != 0)
6030             {
6031               int posbit;
6032 
6033               --nonnull;
6034 
6035               /* patch provided by Aaron Colwell */
6036               if ((posbit = isLiteralBit (bytelit)) != 0)
6037                 {
6038                   if (nonnull)
6039                     {
6040                       pic16_emitpcode (POC_BTFSC,
6041                                        pic16_newpCodeOpBit (pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0,
6042                                                             PO_GPR_REGISTER));
6043                       pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
6044                     }
6045                   else
6046                     {
6047                       pic16_emitpcode (rIfx.condition ? POC_BTFSC : POC_BTFSS,
6048                                        pic16_newpCodeOpBit (pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0,
6049                                                             PO_GPR_REGISTER));
6050                     }
6051                 }
6052               else
6053                 {
6054                   if (bytelit == 0xff)
6055                     {
6056                       /* Aaron had a MOVF instruction here, changed to MOVFW cause
6057                        * a peephole could optimize it out -- VR */
6058                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6059                     }
6060                   else
6061                     {
6062                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6063                       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit));
6064                     }
6065                   if (nonnull)
6066                     {
6067                       if (rIfx.condition)
6068                         {
6069                           emitSKPZ;
6070                           pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));        /* to false */
6071                         }
6072                       else
6073                         {
6074                           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key));     /* to true */
6075                         }
6076                     }
6077                   else
6078                     {
6079                       /* last non null byte */
6080                       if (rIfx.condition)
6081                         emitSKPZ;
6082                       else
6083                         emitSKPNZ;
6084                     }
6085                 }
6086             }
6087         }
6088 
6089       // bit = left & literal
6090       if (size)
6091         {
6092           emitCLRC;
6093           pic16_emitpLabel (tlbl->key);
6094         }
6095 
6096       // if(left & literal)
6097       else
6098         {
6099           if (ifx)
6100             {
6101               if (emitBra)
6102                 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));
6103               ifx->generated = 1;
6104             }
6105           pic16_emitpLabel (tlbl->key);
6106           goto release;
6107         }
6108       pic16_outBitC (result);
6109       goto release;
6110     }
6111 
6112   /* if left is same as result */
6113   if (pic16_sameRegs (AOP (result), AOP (left)))
6114     {
6115       int know_W = -1;
6116       for (; size--; offset++, lit >>= 8)
6117         {
6118           if (AOP_TYPE (right) == AOP_LIT)
6119             {
6120               switch (lit & 0xff)
6121                 {
6122                 case 0x00:
6123                   /*  and'ing with 0 has clears the result */
6124 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6125                   pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offset));
6126                   break;
6127                 case 0xff:
6128                   /* and'ing with 0xff is a nop when the result and left are the same */
6129                   break;
6130 
6131                 default:
6132                 {
6133                   int p = pic16_my_powof2 ((~lit) & 0xff);
6134                   if (p >= 0)
6135                     {
6136                       /* only one bit is clear in the literal, so use a bcf instruction */
6137 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6138                       pic16_emitpcode (POC_BCF,
6139                                        pic16_newpCodeOpBit (pic16_aopGet (AOP (left), offset, FALSE, FALSE), p, 0,
6140                                                             PO_GPR_REGISTER));
6141 
6142                     }
6143                   else
6144                     {
6145                       if (AOP_TYPE (left) == AOP_ACC)
6146                         {
6147                           pic16_emitcode ("andlw", "0x%x", lit & 0xff);
6148                           pic16_emitpcode (POC_ANDLW, pic16_popGetLit (lit & 0xff));
6149                           know_W = -1;
6150                         }
6151                       else
6152                         {
6153                           if (know_W != (lit & 0xff))
6154                             {
6155                               pic16_emitcode ("movlw", "0x%x", lit & 0xff);
6156                               pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0xff));
6157                             }
6158 
6159                           know_W = lit & 0xff;
6160                           pic16_emitcode ("andwf", "%s,f", pic16_aopGet (AOP (left), offset, FALSE, TRUE));
6161                           pic16_emitpcode (POC_ANDWF, pic16_popGet (AOP (left), offset));
6162                         }
6163                     }
6164                 }
6165                 }
6166             }
6167           else
6168             {
6169               if (AOP_TYPE (left) == AOP_ACC)
6170                 {
6171                   pic16_emitpcode (POC_ANDFW, pic16_popGet (AOP (right), offset));
6172                 }
6173               else
6174                 {
6175                   pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (right), offset));
6176                   pic16_emitpcode (POC_ANDWF, pic16_popGet (AOP (left), offset));
6177 
6178                 }
6179             }
6180         }
6181 
6182     }
6183   else
6184     {
6185       // left & result in different registers
6186       if (AOP_TYPE (result) == AOP_CRY)
6187         {
6188           // result = bit
6189           // if(size), result in bit
6190           // if(!size && ifx), conditional oper: if(left & right)
6191           symbol *tlbl = newiTempLabel (NULL);
6192           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6193           if (size)
6194             pic16_emitcode ("setb", "c");
6195           while (sizer--)
6196             {
6197               MOVA (pic16_aopGet (AOP (right), offset, FALSE, FALSE));
6198               pic16_emitcode ("anl", "a,%s", pic16_aopGet (AOP (left), offset, FALSE, FALSE));
6199               pic16_emitcode ("jnz", "%05d_DS_", labelKey2num (tlbl->key));
6200               offset++;
6201             }
6202           if (size)
6203             {
6204               CLRC;
6205               pic16_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
6206               pic16_outBitC (result);
6207             }
6208           else if (ifx)
6209             jmpTrueOrFalse (ifx, tlbl);
6210         }
6211       else
6212         {
6213           for (; (size--); offset++)
6214             {
6215               // normal case
6216               // result = left & right
6217               if (AOP_TYPE (right) == AOP_LIT)
6218                 {
6219                   int t = (lit >> (offset * 8)) & 0x0FFL;
6220                   switch (t)
6221                     {
6222                     case 0x00:
6223                       pic16_emitcode ("clrf", "%s", pic16_aopGet (AOP (result), offset, FALSE, FALSE));
6224                       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offset));
6225                       break;
6226                     case 0xff:
6227                       pic16_emitcode ("movf", "%s,w", pic16_aopGet (AOP (left), offset, FALSE, FALSE));
6228                       pic16_emitcode ("movwf", "%s", pic16_aopGet (AOP (result), offset, FALSE, FALSE));
6229                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6230                       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
6231                       break;
6232                     default:
6233                     {
6234                       if (AOP_TYPE (left) == AOP_ACC)
6235                         {
6236                           pic16_emitcode ("andlw", "0x%02x", t);
6237                           pic16_emitcode ("movwf", "%s", pic16_aopGet (AOP (result), offset, FALSE, FALSE));
6238                           pic16_emitpcode (POC_ANDLW, pic16_popGetLit (t));
6239                           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
6240                         }
6241                       else
6242                         {
6243                           pic16_emitcode ("movlw", "0x%02x", t);
6244                           pic16_emitcode ("andwf", "%s,w", pic16_aopGet (AOP (left), offset, FALSE, FALSE));
6245                           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (t));
6246                           pic16_emitpcode (POC_ANDFW, pic16_popGet (AOP (left), offset));
6247 
6248                           if (AOP_TYPE (result) != AOP_ACC)
6249                             {
6250                               pic16_emitcode ("movwf", "%s", pic16_aopGet (AOP (result), offset, FALSE, FALSE));
6251                               pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
6252                             }
6253                           else
6254                             {
6255                               DEBUGpic16_emitcode ("; ***", "ignore MOVWF\tWREG", __FUNCTION__, __LINE__);
6256                             }
6257                         }
6258                     }
6259                     }
6260                   continue;
6261                 }
6262 
6263               if (AOP_TYPE (left) == AOP_ACC)
6264                 {
6265                   pic16_emitcode ("andwf", "%s,w", pic16_aopGet (AOP (right), offset, FALSE, FALSE));
6266                   pic16_emitpcode (POC_ANDFW, pic16_popGet (AOP (right), offset));
6267                 }
6268               else
6269                 {
6270                   pic16_emitcode ("movf", "%s,w", pic16_aopGet (AOP (right), offset, FALSE, FALSE));
6271                   pic16_emitcode ("andwf", "%s,w", pic16_aopGet (AOP (left), offset, FALSE, FALSE));
6272                   pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (right), offset));
6273                   pic16_emitpcode (POC_ANDFW, pic16_popGet (AOP (left), offset));
6274                 }
6275               pic16_emitcode ("movwf", "%s", pic16_aopGet (AOP (result), offset, FALSE, FALSE));
6276               pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
6277             }
6278         }
6279     }
6280 
6281 release:
6282   pic16_freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6283   pic16_freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6284   pic16_freeAsmop (result, NULL, ic, TRUE);
6285 }
6286 
6287 /*-----------------------------------------------------------------*/
6288 /* genOr  - code for or                                            */
6289 /*-----------------------------------------------------------------*/
6290 static void
genOr(iCode * ic,iCode * ifx)6291 genOr (iCode * ic, iCode * ifx)
6292 {
6293   operand *left, *right, *result;
6294   int size, offset = 0;
6295   unsigned long lit = 0L;
6296   resolvedIfx rIfx;
6297 
6298   FENTRY;
6299 
6300   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6301   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6302   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6303 
6304   resolveIfx (&rIfx, ifx);
6305 
6306   /* if left is a literal & right is not then exchange them */
6307   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) || AOP_NEEDSACC (left))
6308     {
6309       operand *tmp = right;
6310       right = left;
6311       left = tmp;
6312     }
6313 
6314   /* if result = right then exchange them */
6315   if (pic16_sameRegs (AOP (result), AOP (right)))
6316     {
6317       operand *tmp = right;
6318       right = left;
6319       left = tmp;
6320     }
6321 
6322   /* if right is bit then exchange them */
6323   if (AOP_TYPE (right) == AOP_CRY && AOP_TYPE (left) != AOP_CRY)
6324     {
6325       operand *tmp = right;
6326       right = left;
6327       left = tmp;
6328     }
6329 
6330   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
6331 
6332   if (AOP_TYPE (right) == AOP_LIT)
6333     lit = ulFromVal (AOP (right)->aopu.aop_lit);
6334 
6335   size = AOP_SIZE (result);
6336 
6337   // if(bit | yy)
6338   // xx = bit | yy;
6339   if (AOP_TYPE (left) == AOP_CRY)
6340     {
6341       if (AOP_TYPE (right) == AOP_LIT)
6342         {
6343           // c = bit & literal;
6344           if (lit)
6345             {
6346               // lit != 0 => result = 1
6347               if (AOP_TYPE (result) == AOP_CRY)
6348                 {
6349                   if (size)
6350                     pic16_emitpcode (POC_BSF, pic16_popGet (AOP (result), 0));
6351                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6352                   //     AOP(result)->aopu.aop_dir,
6353                   //     AOP(result)->aopu.aop_dir);
6354                   else if (ifx)
6355                     continueIfTrue (ifx);
6356                   goto release;
6357                 }
6358             }
6359           else
6360             {
6361               // lit == 0 => result = left
6362               if (size && pic16_sameRegs (AOP (result), AOP (left)))
6363                 goto release;
6364               pic16_emitcode (";XXX mov", "c,%s  %s,%d", AOP (left)->aopu.aop_dir, __FILE__, __LINE__);
6365             }
6366         }
6367       else
6368         {
6369           if (AOP_TYPE (right) == AOP_CRY)
6370             {
6371               if (pic16_sameRegs (AOP (result), AOP (left)))
6372                 {
6373                   // c = bit | bit;
6374                   pic16_emitpcode (POC_BCF, pic16_popGet (AOP (result), 0));
6375                   pic16_emitpcode (POC_BTFSC, pic16_popGet (AOP (right), 0));
6376                   pic16_emitpcode (POC_BSF, pic16_popGet (AOP (result), 0));
6377 
6378                 }
6379               else
6380                 {
6381                   if (AOP_TYPE (result) == AOP_ACC)
6382                     {
6383                       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0));
6384                       pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP (right), 0));
6385                       pic16_emitpcode (POC_BTFSC, pic16_popGet (AOP (left), 0));
6386                       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (1));
6387 
6388                     }
6389                   else
6390                     {
6391 
6392                       pic16_emitpcode (POC_BCF, pic16_popGet (AOP (result), 0));
6393                       pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP (right), 0));
6394                       pic16_emitpcode (POC_BTFSC, pic16_popGet (AOP (left), 0));
6395                       pic16_emitpcode (POC_BSF, pic16_popGet (AOP (result), 0));
6396 
6397                     }
6398                 }
6399             }
6400           else
6401             {
6402               // c = bit | val;
6403               symbol *tlbl = newiTempLabel (NULL);
6404               pic16_emitcode (";XXX ", " %s,%d", __FILE__, __LINE__);
6405 
6406 
6407               pic16_emitpcode (POC_BCF, pic16_popGet (AOP (result), 0));
6408               if (AOP_TYPE (right) == AOP_ACC)
6409                 {
6410                   pic16_emitpcode (POC_IORLW, pic16_popGetLit (0));
6411                   emitSKPNZ;
6412                   pic16_emitpcode (POC_BTFSC, pic16_popGet (AOP (left), 0));
6413                   pic16_emitpcode (POC_BSF, pic16_popGet (AOP (result), 0));
6414                 }
6415 
6416 
6417 
6418               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6419                 pic16_emitcode (";XXX setb", "c");
6420               pic16_emitcode (";XXX jb", "%s,%05d_DS_", AOP (left)->aopu.aop_dir, labelKey2num (tlbl->key));
6421               pic16_toBoolean (right);
6422               pic16_emitcode (";XXX jnz", "%05d_DS_", labelKey2num (tlbl->key));
6423               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6424                 {
6425                   jmpTrueOrFalse (ifx, tlbl);
6426                   goto release;
6427                 }
6428               else
6429                 {
6430                   CLRC;
6431                   pic16_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
6432                 }
6433             }
6434         }
6435       // bit = c
6436       // val = c
6437       if (size)
6438         pic16_outBitC (result);
6439       // if(bit | ...)
6440       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6441         genIfxJump (ifx, "c");
6442       goto release;
6443     }
6444 
6445   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6446   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6447   if ((AOP_TYPE (right) == AOP_LIT) && (AOP_TYPE (result) == AOP_CRY) && (AOP_TYPE (left) != AOP_CRY))
6448     {
6449       if (IS_OP_VOLATILE (left))
6450         {
6451           pic16_mov2w_volatile (AOP (left));
6452         }                       // if
6453       if (lit)
6454         {
6455           if (rIfx.condition)
6456             pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));      /* to false */
6457           ifx->generated = 1;
6458         }
6459       else
6460         wassert (0);
6461 
6462       goto release;
6463     }
6464 
6465   /* if left is same as result */
6466   if (pic16_sameRegs (AOP (result), AOP (left)))
6467     {
6468       int know_W = -1;
6469       for (; size--; offset++, lit >>= 8)
6470         {
6471           if (AOP_TYPE (right) == AOP_LIT)
6472             {
6473               if (((lit & 0xff) == 0) && !IS_OP_VOLATILE (left))
6474                 {
6475                   /*  or'ing with 0 has no effect */
6476                   continue;
6477                 }
6478               else
6479                 {
6480                   int p = pic16_my_powof2 (lit & 0xff);
6481                   if (p >= 0)
6482                     {
6483                       /* only one bit is set in the literal, so use a bsf instruction */
6484                       pic16_emitpcode (POC_BSF,
6485                                        pic16_newpCodeOpBit (pic16_aopGet (AOP (left), offset, FALSE, FALSE), p, 0,
6486                                                             PO_GPR_REGISTER));
6487                     }
6488                   else
6489                     {
6490                       if (AOP_TYPE (left) == AOP_ACC)
6491                         {
6492                           pic16_emitpcode (POC_IORLW, pic16_popGetLit (lit & 0xff));
6493                           know_W = -1;
6494                         }
6495                       else
6496                         {
6497                           if (know_W != (lit & 0xff))
6498                             {
6499                               pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0xff));
6500                             }
6501 
6502                           know_W = lit & 0xff;
6503                           pic16_emitpcode (POC_IORWF, pic16_popGet (AOP(left), offset));
6504                         }
6505                     }
6506 
6507                 }
6508             }
6509           else
6510             {
6511               if (AOP_TYPE (left) == AOP_ACC)
6512                 {
6513                   pic16_emitpcode (POC_IORFW, pic16_popGet (AOP (right), offset));
6514                 }
6515               else
6516                 {
6517                   pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (right), offset));
6518                   pic16_emitpcode (POC_IORWF, pic16_popGet (AOP (left), offset));
6519                 }
6520             }
6521         }
6522     }
6523   else
6524     {
6525       // left & result in different registers
6526       if (AOP_TYPE (result) == AOP_CRY)
6527         {
6528           // result = bit
6529           // if(size), result in bit
6530           // if(!size && ifx), conditional oper: if(left | right)
6531           symbol *tlbl = newiTempLabel (NULL);
6532           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6533           pic16_emitcode (";XXX ", " %s,%d", __FILE__, __LINE__);
6534 
6535 
6536           if (size)
6537             pic16_emitcode (";XXX setb", "c");
6538           while (sizer--)
6539             {
6540               MOVA (pic16_aopGet (AOP (right), offset, FALSE, FALSE));
6541               pic16_emitcode (";XXX orl", "a,%s", pic16_aopGet (AOP (left), offset, FALSE, FALSE));
6542               pic16_emitcode (";XXX jnz", "%05d_DS_", labelKey2num (tlbl->key));
6543               offset++;
6544             }
6545           if (size)
6546             {
6547               CLRC;
6548               pic16_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
6549               pic16_outBitC (result);
6550             }
6551           else if (ifx)
6552             jmpTrueOrFalse (ifx, tlbl);
6553         }
6554       else
6555         for (; (size--); offset++)
6556           {
6557             // normal case
6558             // result = left & right
6559             if (AOP_TYPE (right) == AOP_LIT)
6560               {
6561                 int t = (lit >> (offset * 8)) & 0x0FFL;
6562                 switch (t)
6563                   {
6564                   case 0x00:
6565                     pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6566                     pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
6567                     break;
6568                   default:
6569                   {
6570                     if (AOP_TYPE (left) == AOP_ACC)
6571                       {
6572                         pic16_emitcode ("iorlw", "0x%02x", t);
6573                         pic16_emitcode ("movwf", "%s", pic16_aopGet (AOP (result), offset, FALSE, FALSE));
6574                         pic16_emitpcode (POC_IORLW, pic16_popGetLit (t));
6575                         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
6576                       }
6577                     else
6578                       {
6579                         pic16_emitcode("movlw", "0x%02x", t);
6580                         pic16_emitcode("iorwf", "%s", pic16_aopGet (AOP (left), offset, FALSE, FALSE));
6581                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit (t));
6582                         pic16_emitpcode(POC_IORFW, pic16_popGet (AOP (left), offset));
6583 
6584                         if (AOP_TYPE (result) != AOP_ACC)
6585                           {
6586                             pic16_emitcode ("movwf", "%s", pic16_aopGet (AOP (result), offset, FALSE, FALSE));
6587                             pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
6588                           }
6589                         else
6590                           {
6591                             DEBUGpic16_emitcode ("; ***", "ignore MOVWF\tWREG", __FUNCTION__, __LINE__);
6592                           }
6593                       }
6594                   }
6595                   }
6596                 continue;
6597               }
6598 
6599             // faster than result <- left, anl result,right
6600             // and better if result is SFR
6601             if (AOP_TYPE (left) == AOP_ACC)
6602               {
6603                 pic16_emitpcode (POC_IORWF, pic16_popGet (AOP (right), offset));
6604               }
6605             else
6606               {
6607                 pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (right), offset));
6608                 pic16_emitpcode (POC_IORFW, pic16_popGet (AOP (left), offset));
6609               }
6610             pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
6611           }
6612     }
6613 
6614 release:
6615   pic16_freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6616   pic16_freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6617   pic16_freeAsmop (result, NULL, ic, TRUE);
6618 }
6619 
6620 /*-----------------------------------------------------------------*/
6621 /* genXor - code for xclusive or                                   */
6622 /*-----------------------------------------------------------------*/
6623 static void
genXor(iCode * ic,iCode * ifx)6624 genXor (iCode * ic, iCode * ifx)
6625 {
6626   operand *left, *right, *result;
6627   int size, offset = 0;
6628   unsigned long lit = 0L;
6629   resolvedIfx rIfx;
6630 
6631   FENTRY;
6632 
6633   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6634   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6635   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6636 
6637   resolveIfx (&rIfx, ifx);
6638 
6639   /* if left is a literal & right is not ||
6640      if left needs acc & right does not */
6641   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6642     {
6643       operand *tmp = right;
6644       right = left;
6645       left = tmp;
6646     }
6647 
6648   /* if result = right then exchange them */
6649   if (pic16_sameRegs (AOP (result), AOP (right)))
6650     {
6651       operand *tmp = right;
6652       right = left;
6653       left = tmp;
6654     }
6655 
6656   /* if right is bit then exchange them */
6657   if (AOP_TYPE (right) == AOP_CRY && AOP_TYPE (left) != AOP_CRY)
6658     {
6659       operand *tmp = right;
6660       right = left;
6661       left = tmp;
6662     }
6663 
6664   if (AOP_TYPE (right) == AOP_LIT)
6665     lit = ulFromVal (AOP (right)->aopu.aop_lit);
6666 
6667   size = AOP_SIZE (result);
6668 
6669   // if(bit ^ yy)
6670   // xx = bit ^ yy;
6671   if (AOP_TYPE (left) == AOP_CRY)
6672     {
6673       if (AOP_TYPE (right) == AOP_LIT)
6674         {
6675           // c = bit & literal;
6676           if (lit >> 1)
6677             {
6678               // lit>>1  != 0 => result = 1
6679               if (AOP_TYPE (result) == AOP_CRY)
6680                 {
6681                   if (size)
6682                     {
6683                       pic16_emitpcode (POC_BSF, pic16_popGet (AOP (result), offset));
6684                     }
6685                   else if (ifx)
6686                     continueIfTrue (ifx);
6687                   goto release;
6688                 }
6689               pic16_emitcode ("setb", "c");
6690             }
6691           else
6692             {
6693               // lit == (0 or 1)
6694               if (lit == 0)
6695                 {
6696                   // lit == 0, result = left
6697                   if (size && pic16_sameRegs (AOP (result), AOP (left)))
6698                     goto release;
6699                   pic16_emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6700                 }
6701               else
6702                 {
6703                   // lit == 1, result = not(left)
6704                   if (size && pic16_sameRegs (AOP (result), AOP (left)))
6705                     {
6706                       pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (result), offset));
6707                       pic16_emitpcode (POC_XORWF, pic16_popGet (AOP (result), offset));
6708                       pic16_emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6709                       goto release;
6710                     }
6711                   else
6712                     {
6713                       pic16_emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6714                       pic16_emitcode ("cpl", "c");
6715                     }
6716                 }
6717             }
6718         }
6719       else
6720         {
6721           // right != literal
6722           symbol *tlbl = newiTempLabel (NULL);
6723           if (AOP_TYPE (right) == AOP_CRY)
6724             {
6725               // c = bit ^ bit;
6726               pic16_emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6727             }
6728           else
6729             {
6730               int sizer = AOP_SIZE (right);
6731               // c = bit ^ val
6732               // if val>>1 != 0, result = 1
6733               pic16_emitcode ("setb", "c");
6734               while (sizer)
6735                 {
6736                   MOVA (pic16_aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6737                   if (sizer == 1)
6738                     // test the msb of the lsb
6739                     pic16_emitcode ("anl", "a,#0xfe");
6740                   pic16_emitcode ("jnz", "%05d_DS_", labelKey2num (tlbl->key));
6741                   sizer--;
6742                 }
6743               // val = (0,1)
6744               pic16_emitcode ("rrc", "a");
6745             }
6746           pic16_emitcode ("jnb", "%s,%05d_DS_", AOP (left)->aopu.aop_dir, labelKey2num (tlbl->key));
6747           pic16_emitcode ("cpl", "c");
6748           pic16_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
6749         }
6750       // bit = c
6751       // val = c
6752       if (size)
6753         pic16_outBitC (result);
6754       // if(bit | ...)
6755       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6756         genIfxJump (ifx, "c");
6757       goto release;
6758     }
6759 
6760   // if(val ^ 0xZZ)       - size = 0, ifx != FALSE  -
6761   // bit = val ^ 0xZZ     - size = 1, ifx = FALSE -
6762   if ((AOP_TYPE (right) == AOP_LIT) && (AOP_TYPE (result) == AOP_CRY) && (AOP_TYPE (left) != AOP_CRY))
6763     {
6764       symbol *tlbl = newiTempLabel (NULL);
6765       int sizel;
6766 
6767       if (size)
6768         emitSETC;
6769 
6770       for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
6771         {
6772           unsigned char bytelit = lit & 0xFF;
6773 
6774           switch (bytelit)
6775             {
6776             case 0xff:
6777               pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
6778               break;
6779 
6780             case 0x00:
6781               pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6782               break;
6783 
6784             default:
6785               pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit));
6786               pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
6787               break;
6788             }
6789           if (sizel)
6790             {
6791               if (rIfx.condition)
6792                 {
6793                   /* rIfx.lbl might be far away... */
6794                   emitSKPZ;
6795                   pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));        /* to false */
6796                 }
6797               else
6798                 {
6799                   pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key));     /* to true */
6800                 }
6801             }
6802           else
6803             {
6804               /* last non null byte */
6805               if (rIfx.condition)
6806                 emitSKPZ;
6807               else
6808                 emitSKPNZ;
6809             }
6810         }
6811 
6812       // bit = left ^ literal
6813       if (size)
6814         {
6815           emitCLRC;
6816           pic16_emitpLabel (tlbl->key);
6817         }
6818       // if (left ^ literal)
6819       else
6820         {
6821           if (ifx)
6822             {
6823               pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));
6824               ifx->generated = 1;
6825             }
6826           pic16_emitpLabel (tlbl->key);
6827           goto release;
6828         }
6829 
6830       pic16_outBitC (result);
6831       goto release;
6832     }
6833 
6834   if (pic16_sameRegs (AOP (result), AOP (left)))
6835     {
6836       /* if left is same as result */
6837       int know_W = -1;
6838 
6839       for (; size--; offset++)
6840         {
6841           if (AOP_TYPE (right) == AOP_LIT)
6842             {
6843               int t = (lit >> (offset * 8)) & 0x0FFL;
6844               if (t == 0x00L)
6845                 continue;
6846               else
6847                 {
6848                   int p = pic16_my_powof2 (t);
6849 
6850                   if (p >= 0)
6851                     {
6852                       /* Only one bit is toggle in the literal, so use a btg instruction. */
6853                       pic16_emitpcode (POC_BTG,
6854                                        pic16_newpCodeOpBit (pic16_aopGet (AOP (left), offset, FALSE, FALSE), p, 0, PO_GPR_REGISTER));
6855                     }
6856                   else
6857                     {
6858                       if (AOP_TYPE (left) == AOP_ACC)
6859                         {
6860                           pic16_emitcode ("xorlw", "0x%02x", t);
6861                           pic16_emitpcode (POC_XORLW, pic16_popGetLit (t));
6862                           know_W = -1;
6863                         }
6864                       else
6865                         {
6866                           if (know_W != t)
6867                             {
6868                               pic16_emitcode ("movlw", "0x%02x", t);
6869                               pic16_emitpcode (POC_MOVLW, pic16_popGetLit (t));
6870                             }
6871 
6872                           know_W = t;
6873                         }
6874 
6875                       pic16_emitcode ("xorwf", "%s", pic16_aopGet (AOP (left), offset, FALSE, FALSE));
6876                       pic16_emitpcode (POC_XORWF, pic16_popGet (AOP (left), offset));
6877                     }
6878                 }
6879             }
6880           else
6881             {
6882               if (AOP_TYPE (left) == AOP_ACC)
6883                 pic16_emitcode ("xrl", "a,%s", pic16_aopGet (AOP (right), offset, FALSE, FALSE));
6884               else
6885                 {
6886                   pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (right), offset));
6887                   pic16_emitpcode (POC_XORWF, pic16_popGet (AOP (left), offset));
6888                 }
6889             }
6890         }
6891     }
6892   else
6893     {
6894       // left ^ result in different registers
6895       if (AOP_TYPE (result) == AOP_CRY)
6896         {
6897           // result = bit
6898           // if(size), result in bit
6899           // if(!size && ifx), conditional oper: if(left ^ right)
6900           symbol *tlbl = newiTempLabel (NULL);
6901           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6902           if (size)
6903             pic16_emitcode ("setb", "c");
6904           while (sizer--)
6905             {
6906               if ((AOP_TYPE (right) == AOP_LIT) && (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6907                 {
6908                   MOVA (pic16_aopGet (AOP (left), offset, FALSE, FALSE));
6909                 }
6910               else
6911                 {
6912                   MOVA (pic16_aopGet (AOP (right), offset, FALSE, FALSE));
6913                   pic16_emitcode ("xrl", "a,%s", pic16_aopGet (AOP (left), offset, FALSE, FALSE));
6914                 }
6915               pic16_emitcode ("jnz", "%05d_DS_", labelKey2num (tlbl->key));
6916               offset++;
6917             }
6918           if (size)
6919             {
6920               CLRC;
6921               pic16_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
6922               pic16_outBitC (result);
6923             }
6924           else if (ifx)
6925             jmpTrueOrFalse (ifx, tlbl);
6926         }
6927       else
6928         {
6929           for (; (size--); offset++)
6930             {
6931               // normal case
6932               // result = left ^ right
6933               if (AOP_TYPE (right) == AOP_LIT)
6934                 {
6935                   int t = (lit >> (offset * 8)) & 0x0FFL;
6936                   switch (t)
6937                     {
6938                     case 0x00:
6939                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6940                       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
6941                       break;
6942 
6943                     case 0xff:
6944                       pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
6945                       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
6946                       break;
6947 
6948                     default:
6949                     {
6950                       if (AOP_TYPE (left) == AOP_ACC)
6951                         {
6952                           pic16_emitcode ("xorlw", "0x%02x", t);
6953                           pic16_emitpcode (POC_XORLW, pic16_popGetLit (t));
6954                         }
6955                       else
6956                         {
6957                           pic16_emitcode ("movlw", "0x%02x", t);
6958                           pic16_emitcode ("xorwf", "%s", pic16_aopGet (AOP (left), offset, FALSE, FALSE));
6959                           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (t));
6960                           pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
6961                         }
6962 
6963                       pic16_emitcode ("movwf", "%s", pic16_aopGet (AOP (result), offset, FALSE, FALSE));
6964                       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
6965                     }
6966                     }
6967                   continue;
6968                 }
6969 
6970               // faster than result <- left, anl result,right
6971               // and better if result is SFR
6972               if (AOP_TYPE (left) == AOP_ACC)
6973                 {
6974                   pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (right), offset));
6975                 }
6976               else
6977                 {
6978                   pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (right), offset));
6979                   pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
6980                 }
6981               if (AOP_TYPE (result) != AOP_ACC)
6982                 {
6983                   pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
6984                 }
6985               else
6986                 {
6987                   DEBUGpic16_emitcode ("; ***", "ignore MOVWF\tWREG", __FUNCTION__, __LINE__);
6988                 }
6989             }
6990         }
6991     }
6992 
6993 release:
6994   pic16_freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6995   pic16_freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6996   pic16_freeAsmop (result, NULL, ic, TRUE);
6997 }
6998 
6999 /*-----------------------------------------------------------------*/
7000 /* genInline - write the inline code out                           */
7001 /*-----------------------------------------------------------------*/
7002 static void
pic16_genInline(iCode * ic)7003 pic16_genInline (iCode * ic)
7004 {
7005   char *buffer, *bp, *bp1;
7006   bool inComment = FALSE;
7007 
7008   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
7009 
7010   genLine.lineElement.isInline += (!options.asmpeep);
7011 
7012   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7013 
7014   while ((bp1 = strstr (bp, "\\n")))
7015     {
7016       *bp1++ = '\n';
7017       *bp1++ = ' ';
7018       bp = bp1;
7019     }
7020   bp = bp1 = buffer;
7021 
7022 #if 0
7023   /* This is an experimental code for #pragma inline
7024      and is temporarily disabled for 2.5.0 release */
7025   if (asmInlineMap)
7026     {
7027       symbol *sym;
7028       char *s;
7029       char *cbuf;
7030       int cblen;
7031 
7032       cbuf = Safe_strdup (buffer);
7033       cblen = strlen (buffer) + 1;
7034       memset (cbuf, 0, cblen);
7035 
7036       bp = buffer;
7037       bp1 = cbuf;
7038       while (*bp)
7039         {
7040           if (*bp != '%')
7041             *bp1++ = *bp++;
7042           else
7043             {
7044               int i;
7045 
7046               bp++;
7047               i = *bp - '0';
7048               if (i > elementsInSet (asmInlineMap))
7049                 break;
7050 
7051               bp++;
7052               s = indexSet (asmInlineMap, i);
7053               DEBUGpc ("searching symbol s = `%s'", s);
7054               sym = findSym (SymbolTab, NULL, s);
7055 
7056               if (sym->reqv)
7057                 {
7058                   strcat (bp1, sym->reqv->operand.symOperand->regs[0]->name);
7059                 }
7060               else
7061                 {
7062                   strcat (bp1, sym->rname);
7063                 }
7064 
7065               while (*bp1)
7066                 bp1++;
7067             }
7068 
7069           if (strlen (bp1) > cblen - 16)
7070             {
7071               int i = strlen (cbuf);
7072               cblen += 50;
7073               cbuf = realloc (cbuf, cblen);
7074               memset (cbuf + i, 0, 50);
7075               bp1 = cbuf + i;
7076             }
7077         }
7078 
7079       free (buffer);
7080       buffer = Safe_strdup (cbuf);
7081       free (cbuf);
7082 
7083       bp = bp1 = buffer;
7084     }
7085 #endif /* 0 */
7086 
7087   /* emit each line as a code */
7088   while (*bp)
7089     {
7090       switch (*bp)
7091         {
7092         case ';':
7093           inComment = TRUE;
7094           ++bp;
7095           break;
7096 
7097         case '\x87':
7098         case '\n':
7099           inComment = FALSE;
7100           *bp++ = '\0';
7101           if (*bp1)
7102             pic16_addpCode2pBlock (pb, pic16_newpCodeAsmDir (bp1, NULL));       // inline directly, no process
7103           bp1 = bp;
7104           break;
7105 
7106         default:
7107           /* Add \n for labels, not dirs such as c:\mydir */
7108           if (!inComment && (*bp == ':') && (isspace ((unsigned char) bp[1])))
7109             {
7110               ++bp;
7111               *bp = '\0';
7112               ++bp;
7113               /* print label, use this special format with NULL directive
7114                * to denote that the argument should not be indented with tab */
7115               pic16_addpCode2pBlock (pb, pic16_newpCodeAsmDir (NULL, bp1));     // inline directly, no process
7116               bp1 = bp;
7117             }
7118           else
7119             ++bp;
7120           break;
7121         }
7122     }
7123 
7124   if ((bp1 != bp) && *bp1)
7125     pic16_addpCode2pBlock (pb, pic16_newpCodeAsmDir (bp1, NULL));       // inline directly, no process
7126 
7127   Safe_free (buffer);
7128 
7129   /* consumed; we can free it here */
7130   dbuf_free (IC_INLINE (ic));
7131 
7132   genLine.lineElement.isInline -= (!options.asmpeep);
7133 }
7134 
7135 /*-----------------------------------------------------------------*/
7136 /* genRRC - rotate right with carry                                */
7137 /*-----------------------------------------------------------------*/
7138 static void
genRRC(iCode * ic)7139 genRRC (iCode * ic)
7140 {
7141   operand *left, *result;
7142   int size, same;
7143 
7144   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
7145 
7146   /* rotate right with carry */
7147   left = IC_LEFT (ic);
7148   result = IC_RESULT (ic);
7149   pic16_aopOp (left, ic, FALSE);
7150   pic16_aopOp (result, ic, TRUE);
7151 
7152   DEBUGpic16_pic16_AopType (__LINE__, left, NULL, result);
7153 
7154   same = pic16_sameRegs (AOP (result), AOP (left));
7155 
7156   size = AOP_SIZE (result);
7157 
7158   DEBUGpic16_emitcode ("; ***", "%s  %d size:%d same:%d", __FUNCTION__, __LINE__, size, same);
7159 
7160   /* get the lsb and put it into the carry */
7161   pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (left), 0));
7162 
7163   while (size--)
7164     {
7165 
7166       if (same)
7167         {
7168           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (left), size));
7169         }
7170       else
7171         {
7172           pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (left), size));
7173           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), size));
7174         }
7175     }
7176 
7177   pic16_freeAsmop (left, NULL, ic, TRUE);
7178   pic16_freeAsmop (result, NULL, ic, TRUE);
7179 }
7180 
7181 /*-----------------------------------------------------------------*/
7182 /* genRLC - generate code for rotate left with carry               */
7183 /*-----------------------------------------------------------------*/
7184 static void
genRLC(iCode * ic)7185 genRLC (iCode * ic)
7186 {
7187   operand *left, *result;
7188   int size, offset = 0;
7189   int same;
7190 
7191   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
7192   /* rotate right with carry */
7193   left = IC_LEFT (ic);
7194   result = IC_RESULT (ic);
7195   pic16_aopOp (left, ic, FALSE);
7196   pic16_aopOp (result, ic, TRUE);
7197 
7198   DEBUGpic16_pic16_AopType (__LINE__, left, NULL, result);
7199 
7200   same = pic16_sameRegs (AOP (result), AOP (left));
7201 
7202   /* move it to the result */
7203   size = AOP_SIZE (result);
7204 
7205   /* get the msb and put it into the carry */
7206   pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (left), size - 1));
7207 
7208   offset = 0;
7209 
7210   while (size--)
7211     {
7212 
7213       if (same)
7214         {
7215           pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (left), offset));
7216         }
7217       else
7218         {
7219           pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (left), offset));
7220           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
7221         }
7222 
7223       offset++;
7224     }
7225 
7226 
7227   pic16_freeAsmop (left, NULL, ic, TRUE);
7228   pic16_freeAsmop (result, NULL, ic, TRUE);
7229 }
7230 
7231 
7232 /* gpasm can get the highest order bit with HIGH/UPPER
7233  * so the following probably is not needed -- VR */
7234 
7235 /*-----------------------------------------------------------------*/
7236 /* genGetHbit - generates code get highest order bit               */
7237 /*-----------------------------------------------------------------*/
7238 static void
genGetHbit(iCode * ic)7239 genGetHbit (iCode * ic)
7240 {
7241   operand *left, *result;
7242   left = IC_LEFT (ic);
7243   result = IC_RESULT (ic);
7244   pic16_aopOp (left, ic, FALSE);
7245   pic16_aopOp (result, ic, FALSE);
7246 
7247   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
7248   /* get the highest order byte into a */
7249   MOVA (pic16_aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
7250   if (AOP_TYPE (result) == AOP_CRY)
7251     {
7252       pic16_emitcode ("rlc", "a");
7253       pic16_outBitC (result);
7254     }
7255   else
7256     {
7257       pic16_emitcode ("rl", "a");
7258       pic16_emitcode ("anl", "a,#0x01");
7259       pic16_outAcc (result);
7260     }
7261 
7262 
7263   pic16_freeAsmop (left, NULL, ic, TRUE);
7264   pic16_freeAsmop (result, NULL, ic, TRUE);
7265 }
7266 
7267 static void
genGetABit(iCode * ic)7268 genGetABit (iCode * ic)
7269 {
7270   operand *left, *right, *result;
7271   int shCount;
7272   int offset;
7273   int i;
7274 
7275   left = IC_LEFT (ic);
7276   right = IC_RIGHT (ic);
7277   result = IC_RESULT (ic);
7278 
7279   pic16_aopOp (left, ic, FALSE);
7280   pic16_aopOp (right, ic, FALSE);
7281   pic16_aopOp (result, ic, TRUE);
7282 
7283   shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7284   offset = shCount / 8;
7285   shCount %= 8;
7286 
7287   /* load and mask the source byte */
7288   pic16_mov2w (AOP (left), offset);
7289   pic16_emitpcode (POC_ANDLW, pic16_popGetLit (1 << shCount));
7290 
7291   /* move selected bit to bit 0 */
7292   switch (shCount)
7293     {
7294     case 0:
7295       /* nothing more to do */
7296       break;
7297     case 1:
7298       /* shift bit 1 into bit 0 */
7299       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7300       break;
7301     case 4:
7302       /* shift bit 4 into bit 0 */
7303       pic16_emitpcode (POC_SWAPFW, pic16_popCopyReg (&pic16_pc_wreg));
7304       break;
7305     case 7:
7306       /* shift bit 7 into bit 0 */
7307       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7308       break;
7309     default:
7310       /* keep W==0, force W=0x01 otherwise */
7311       emitSKPZ;
7312       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (1));
7313       break;
7314     }                           // switch
7315 
7316   /* write result */
7317   pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
7318 
7319   for (i = 1; i < AOP_SIZE (result); ++i)
7320     {
7321       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), i));
7322     }                           // for
7323 
7324   pic16_freeAsmop (left, NULL, ic, TRUE);
7325   pic16_freeAsmop (right, NULL, ic, TRUE);
7326   pic16_freeAsmop (result, NULL, ic, TRUE);
7327 }
7328 
7329 #if 0
7330 /*-----------------------------------------------------------------*/
7331 /* AccRol - rotate left accumulator by known count                 */
7332 /*-----------------------------------------------------------------*/
7333 static void
7334 AccRol (int shCount)
7335 {
7336   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
7337   shCount &= 0x0007;            // shCount : 0..7
7338   switch (shCount)
7339     {
7340     case 0:
7341       break;
7342     case 1:
7343       pic16_emitcode ("rl", "a");
7344       break;
7345     case 2:
7346       pic16_emitcode ("rl", "a");
7347       pic16_emitcode ("rl", "a");
7348       break;
7349     case 3:
7350       pic16_emitcode ("swap", "a");
7351       pic16_emitcode ("rr", "a");
7352       break;
7353     case 4:
7354       pic16_emitcode ("swap", "a");
7355       break;
7356     case 5:
7357       pic16_emitcode ("swap", "a");
7358       pic16_emitcode ("rl", "a");
7359       break;
7360     case 6:
7361       pic16_emitcode ("rr", "a");
7362       pic16_emitcode ("rr", "a");
7363       break;
7364     case 7:
7365       pic16_emitcode ("rr", "a");
7366       break;
7367     }
7368 }
7369 #endif
7370 
7371 /*-----------------------------------------------------------------*/
7372 /* AccLsh - left shift accumulator by known count                  */
7373 /*-----------------------------------------------------------------*/
7374 static void
AccLsh(int shCount,int doMask)7375 AccLsh (int shCount, int doMask)
7376 {
7377   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
7378   switch (shCount)
7379     {
7380     case 0:
7381       return;
7382       break;
7383     case 1:
7384       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7385       break;
7386     case 2:
7387       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7388       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7389       break;
7390     case 3:
7391       pic16_emitpcode (POC_SWAPFW, pic16_popCopyReg (&pic16_pc_wreg));
7392       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7393       break;
7394     case 4:
7395       pic16_emitpcode (POC_SWAPFW, pic16_popCopyReg (&pic16_pc_wreg));
7396       break;
7397     case 5:
7398       pic16_emitpcode (POC_SWAPFW, pic16_popCopyReg (&pic16_pc_wreg));
7399       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7400       break;
7401     case 6:
7402       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7403       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7404       break;
7405     case 7:
7406       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7407       break;
7408     }
7409   if (doMask)
7410     {
7411       /* no masking is required in genPackBits */
7412       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (SLMask[shCount]));
7413     }
7414 }
7415 
7416 /*-----------------------------------------------------------------*/
7417 /* AccRsh - right shift accumulator by known count                 */
7418 /*-----------------------------------------------------------------*/
7419 static void
AccRsh(int shCount,int andmask)7420 AccRsh (int shCount, int andmask)
7421 {
7422   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
7423   assert ((shCount >= 0) && (shCount <= 8));
7424   switch (shCount)
7425     {
7426     case 0:
7427       return;
7428       break;
7429     case 1:
7430       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7431       break;
7432     case 2:
7433       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7434       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7435       break;
7436     case 3:
7437       pic16_emitpcode (POC_SWAPFW, pic16_popCopyReg (&pic16_pc_wreg));
7438       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7439       break;
7440     case 4:
7441       pic16_emitpcode (POC_SWAPFW, pic16_popCopyReg (&pic16_pc_wreg));
7442       break;
7443     case 5:
7444       pic16_emitpcode (POC_SWAPFW, pic16_popCopyReg (&pic16_pc_wreg));
7445       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7446       break;
7447     case 6:
7448       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7449       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7450       break;
7451     case 7:
7452       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7453       break;
7454     default:
7455       // Rotating by 8 is a NOP.
7456       break;
7457     }
7458 
7459   if (andmask)
7460     pic16_emitpcode (POC_ANDLW, pic16_popGetLit (SRMask[shCount]));
7461   else
7462     DEBUGpic16_emitcode ("; ***", "%s omitting masking the result", __FUNCTION__);
7463 }
7464 
7465 /*-----------------------------------------------------------------*/
7466 /* shiftR1Left2Result - shift right one byte from left to result   */
7467 /*-----------------------------------------------------------------*/
7468 static void
shiftR1Left2ResultSigned(operand * left,int offl,operand * result,int offr,int shCount)7469 shiftR1Left2ResultSigned (operand * left, int offl, operand * result, int offr, int shCount)
7470 {
7471   int same;
7472 
7473   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
7474   assert ((shCount >= 0) && (shCount <= 8));
7475 
7476   same = ((left == result) || (AOP (left) == AOP (result))) && (offl == offr);
7477 
7478   /* Do NOT use result for intermediate results, it might be an SFR!. */
7479   switch (shCount)
7480     {
7481     case 0:
7482       if (!same)
7483         {
7484           pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offl));
7485           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7486         }
7487       break;
7488 
7489     case 1:
7490       pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (left), offl));
7491       if (same)
7492         pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr));
7493       else
7494         {
7495           pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (left), offl));
7496           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7497         }
7498       break;
7499 
7500     case 2:
7501       pic16_emitpcode (POC_RRNCFW, pic16_popGet (AOP (left), offl));
7502       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7503       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x3f));      // keep sign bit in W<5>
7504       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (PCOP (&pic16_pc_wreg), 5));
7505       pic16_emitpcode (POC_IORLW, pic16_popGetLit (0xc0));      // sign-extend
7506       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7507       break;
7508 
7509     case 3:
7510       pic16_emitpcode (POC_SWAPFW, pic16_popGet (AOP (left), offl));
7511       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7512       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x1f));      // keep sign in W<4>
7513       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (PCOP (&pic16_pc_wreg), 4));
7514       pic16_emitpcode (POC_IORLW, pic16_popGetLit (0xe0));      // sign-extend
7515       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7516       break;
7517 
7518     case 4:
7519       pic16_emitpcode (POC_SWAPFW, pic16_popGet (AOP (left), offl));
7520       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x0f));      // keep sign in W<3>
7521       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (PCOP (&pic16_pc_wreg), 3));
7522       pic16_emitpcode (POC_IORLW, pic16_popGetLit (0xf0));      // sign-extend
7523       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7524       break;
7525 
7526     case 5:
7527       pic16_emitpcode (POC_SWAPFW, pic16_popGet (AOP (left), offl));
7528       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7529       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x07));      // keep sign in W<2>
7530       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (PCOP (&pic16_pc_wreg), 2));
7531       pic16_emitpcode (POC_IORLW, pic16_popGetLit (0xf8));      // sign-extend
7532       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7533       break;
7534 
7535     case 6:
7536       pic16_emitpcode (POC_RLNCFW, pic16_popGet (AOP (left), offl));
7537       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7538       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x03));      // keep sign bit in W<1>
7539       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (PCOP (&pic16_pc_wreg), 1));
7540       pic16_emitpcode (POC_IORLW, pic16_popGetLit (0xfc));      // sign-extend
7541       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7542       break;
7543 
7544     case 7:
7545       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0x00));
7546       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (pic16_popGet (AOP (left), offl), 7));
7547       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xff));
7548       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7549       break;
7550 
7551     default:
7552       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offr));
7553       break;
7554     }
7555 }
7556 
7557 /*-----------------------------------------------------------------*/
7558 /* shiftR1Left2Result - shift right one byte from left to result   */
7559 /*-----------------------------------------------------------------*/
7560 static void
shiftR1Left2Result(operand * left,int offl,operand * result,int offr,int shCount,int sign)7561 shiftR1Left2Result (operand * left, int offl, operand * result, int offr, int shCount, int sign)
7562 {
7563   int same;
7564 
7565   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
7566   assert ((shCount >= 0) && (shCount <= 8));
7567 
7568   same = ((left == result) || (AOP (left) == AOP (result))) && (offl == offr);
7569 
7570   /* Copy the msb into the carry if signed. */
7571   if (sign)
7572     {
7573       shiftR1Left2ResultSigned (left, offl, result, offr, shCount);
7574       return;
7575     }
7576 
7577   /* Do NOT use result for intermediate results, it might be an SFR!. */
7578   switch (shCount)
7579     {
7580     case 0:
7581       if (!same)
7582         {
7583           pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offl));
7584           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7585         }
7586       break;
7587 
7588     case 1:
7589       if (same)
7590         {
7591           emitCLRC;
7592           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr));
7593         }
7594       else
7595         {
7596           pic16_emitpcode (POC_RRNCFW, pic16_popGet (AOP (left), offl));
7597           pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x7f));
7598           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7599         }
7600       break;
7601 
7602     case 2:
7603       pic16_emitpcode (POC_RRNCFW, pic16_popGet (AOP (left), offl));
7604       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7605       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x3f));
7606       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7607       break;
7608 
7609     case 3:
7610       pic16_emitpcode (POC_SWAPFW, pic16_popGet (AOP (left), offl));
7611       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7612       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x1f));
7613       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7614       break;
7615 
7616     case 4:
7617       pic16_emitpcode (POC_SWAPFW, pic16_popGet (AOP (left), offl));
7618       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x0f));
7619       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7620       break;
7621 
7622     case 5:
7623       pic16_emitpcode (POC_SWAPFW, pic16_popGet (AOP (left), offl));
7624       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7625       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x07));
7626       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7627       break;
7628 
7629     case 6:
7630       pic16_emitpcode (POC_RLNCFW, pic16_popGet (AOP (left), offl));
7631       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7632       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x03));
7633       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7634       break;
7635 
7636     case 7:
7637       pic16_emitpcode (POC_RLNCFW, pic16_popGet (AOP (left), offl));
7638       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x01));
7639       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7640       break;
7641 
7642     default:
7643       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offr));
7644       break;
7645     }
7646 }
7647 
7648 /*-----------------------------------------------------------------*/
7649 /* shiftL1Left2Result - shift left one byte from left to result    */
7650 /*-----------------------------------------------------------------*/
7651 static void
shiftL1Left2Result(operand * left,int offl,operand * result,int offr,int shCount)7652 shiftL1Left2Result (operand * left, int offl, operand * result, int offr, int shCount)
7653 {
7654   int same;
7655 
7656   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
7657   assert ((shCount >= 0) && (shCount <= 8));
7658 
7659   same = ((left == result) || (AOP (left) == AOP (result))) && (offl == offr);
7660 
7661   /* Do NOT use result for intermediate results, it might be an SFR!. */
7662   switch (shCount)
7663     {
7664     case 0:
7665       if (!same)
7666         {
7667           pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offl));
7668           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7669         }
7670       break;
7671 
7672     case 1:
7673       if (same)
7674         {
7675           emitCLRC;
7676           pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (left), offl));
7677         }
7678       else
7679         {
7680           pic16_emitpcode (POC_RLNCFW, pic16_popGet (AOP (left), offl));
7681           pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0xfe));
7682           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7683         }
7684       break;
7685 
7686     case 2:
7687     {
7688       if (same)
7689         {
7690           if (AOP_TYPE (left) == AOP_ACC)
7691             {
7692               /* Reduces the number of instructions. */
7693               pic16_emitpcode(POC_ADDFW, pic16_popGet (AOP (left), offl));
7694               pic16_emitpcode(POC_ADDFW, pic16_popGet (AOP (left), offl));
7695             }
7696           else
7697             {
7698               emitCLRC;
7699               pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (left), offl));
7700               emitCLRC;
7701               pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (left), offl));
7702             }
7703         }
7704       else
7705         {
7706           pic16_emitpcode (POC_RLNCFW, pic16_popGet (AOP (left), offl));
7707           pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7708           pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0xfc));
7709           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7710         }
7711 
7712       break;
7713     }
7714 
7715     case 3:
7716       if (same && AOP_TYPE(left) == AOP_ACC)
7717         {
7718           /* Reduces the number of instructions. */
7719           pic16_emitpcode (POC_ADDFW, pic16_popGet (AOP (left), offl));
7720           pic16_emitpcode (POC_ADDFW, pic16_popGet (AOP (left), offl));
7721           pic16_emitpcode (POC_ADDFW, pic16_popGet (AOP (left), offl));
7722         }
7723       else
7724         {
7725           pic16_emitpcode (POC_SWAPFW, pic16_popGet (AOP (left), offl));
7726           pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7727           pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0xf8));
7728           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7729         }
7730       break;
7731 
7732     case 4:
7733       pic16_emitpcode (POC_SWAPFW, pic16_popGet (AOP (left), offl));
7734       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0xf0));
7735       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7736       break;
7737 
7738     case 5:
7739       pic16_emitpcode (POC_SWAPFW, pic16_popGet (AOP (left), offl));
7740       pic16_emitpcode (POC_RLNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7741       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0xe0));
7742       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7743       break;
7744 
7745     case 6:
7746       pic16_emitpcode (POC_RRNCFW, pic16_popGet (AOP (left), offl));
7747       pic16_emitpcode (POC_RRNCFW, pic16_popCopyReg (&pic16_pc_wreg));
7748       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0xc0));
7749       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7750       break;
7751 
7752     case 7:
7753       pic16_emitpcode (POC_RRNCFW, pic16_popGet (AOP (left), offl));
7754       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x80));
7755       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7756       break;
7757 
7758     default:
7759       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offr));
7760       break;
7761     }
7762 }
7763 
7764 /*-----------------------------------------------------------------*/
7765 /* movLeft2Result - move byte from left to result                  */
7766 /*-----------------------------------------------------------------*/
7767 static void
movLeft2Result(operand * left,int offl,operand * result,int offr)7768 movLeft2Result (operand * left, int offl, operand * result, int offr)
7769 {
7770   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
7771   if (!pic16_sameRegs (AOP (left), AOP (result)) || (offl != offr))
7772     {
7773       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offl));
7774       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7775     }
7776 }
7777 
7778 /*-----------------------------------------------------------------*/
7779 /* shiftL2Left2Result - shift left two bytes from left to result   */
7780 /*-----------------------------------------------------------------*/
7781 static void
shiftL2Left2Result(operand * left,int offl,operand * result,int offr,int shCount)7782 shiftL2Left2Result (operand * left, int offl, operand * result, int offr, int shCount)
7783 {
7784   int same = pic16_sameRegs (AOP (result), AOP (left));
7785   int i;
7786 
7787   DEBUGpic16_emitcode ("; ***", "%s  %d shCount:%d same:%d offl:%d offr:%d", __FUNCTION__, __LINE__, shCount, same, offl, offr);
7788 
7789   if (same && (offl != offr))   // shift bytes
7790     {
7791       if (offr > offl)
7792         {
7793           for (i = 1; i > -1; i--)
7794             {
7795               pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (result), offl + i));
7796               pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr + i));
7797             }
7798         }
7799       else                      // just treat as different later on
7800         {
7801           same = 0;
7802         }
7803     }
7804 
7805   if (same)
7806     {
7807       switch (shCount)
7808         {
7809         case 0:
7810           break;
7811         case 1:
7812         case 2:
7813         case 3:
7814 
7815           pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (result), offr));
7816           pic16_emitpcode (POC_ADDWF, pic16_popGet (AOP (result), offr));
7817           pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr + MSB16));
7818 
7819           while (--shCount)
7820             {
7821               emitCLRC;
7822               pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr));
7823               pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr + MSB16));
7824             }
7825 
7826           break;
7827         case 4:
7828         case 5:
7829           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0x0f));
7830           pic16_emitpcode (POC_ANDWF, pic16_popGet (AOP (result), offr + MSB16));
7831           pic16_emitpcode (POC_SWAPF, pic16_popGet (AOP (result), offr + MSB16));
7832           pic16_emitpcode (POC_SWAPF, pic16_popGet (AOP (result), offr));
7833           pic16_emitpcode (POC_ANDFW, pic16_popGet (AOP (result), offr));
7834           pic16_emitpcode (POC_XORWF, pic16_popGet (AOP (result), offr));
7835           pic16_emitpcode (POC_ADDWF, pic16_popGet (AOP (result), offr + MSB16));
7836           if (shCount >= 5)
7837             {
7838               pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr));
7839               pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr + MSB16));
7840             }
7841           break;
7842         case 6:
7843           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr + MSB16));
7844           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr));
7845           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr + MSB16));
7846           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr));
7847           pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (result), offr + MSB16));
7848           pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0xc0));
7849           pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (result), offr));
7850           pic16_emitpcode (POC_XORWF, pic16_popGet (AOP (result), offr));
7851           pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (result), offr));
7852           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr + MSB16));
7853           break;
7854         case 7:
7855           pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (result), offr + MSB16));
7856           pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (result), offr));
7857           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr + MSB16));
7858           pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offr));
7859           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr));
7860         }
7861 
7862     }
7863   else
7864     {
7865       switch (shCount)
7866         {
7867         case 0:
7868           break;
7869         case 1:
7870         case 2:
7871         case 3:
7872           /* note, use a mov/add for the shift since the mov has a
7873              chance of getting optimized out */
7874           pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offl));
7875           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7876           pic16_emitpcode (POC_ADDWF, pic16_popGet (AOP (result), offr));
7877           pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (left), offl + MSB16));
7878           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr + MSB16));
7879 
7880           while (--shCount)
7881             {
7882               emitCLRC;
7883               pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr));
7884               pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr + MSB16));
7885             }
7886           break;
7887 
7888         case 4:
7889         case 5:
7890           pic16_emitpcode (POC_SWAPFW, pic16_popGet (AOP (left), offl + MSB16));
7891           pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0xF0));
7892           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr + MSB16));
7893           pic16_emitpcode (POC_SWAPFW, pic16_popGet (AOP (left), offl));
7894           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7895           pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x0F));
7896           pic16_emitpcode (POC_XORWF, pic16_popGet (AOP (result), offr));
7897           pic16_emitpcode (POC_ADDWF, pic16_popGet (AOP (result), offr + MSB16));
7898 
7899 
7900           if (shCount == 5)
7901             {
7902               pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr));
7903               pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr + MSB16));
7904             }
7905           break;
7906         case 6:
7907           pic16_emitpcode (POC_RRNCFW, pic16_popGet (AOP (left), offl));
7908           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7909           pic16_emitpcode (POC_RRNCF, pic16_popGet (AOP (result), offr));
7910           pic16_emitpcode (POC_RRNCFW, pic16_popGet (AOP (left), offl + MSB16));
7911           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr + MSB16));
7912           pic16_emitpcode (POC_RRNCF, pic16_popGet (AOP (result), offr + MSB16));
7913           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xc0));
7914           pic16_emitpcode (POC_ANDWF, pic16_popGet (AOP (result), offr + MSB16));
7915           pic16_emitpcode (POC_ANDFW, pic16_popGet (AOP (result), offr));
7916           pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (result), offr));
7917           pic16_emitpcode (POC_IORWF, pic16_popGet (AOP (result), offr + MSB16));
7918           pic16_emitpcode (POC_XORWF, pic16_popGet (AOP (result), offr));
7919           break;
7920         case 7:
7921           pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (left), offl + MSB16));
7922           pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (left), offl));
7923           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr + MSB16));
7924           pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offr));
7925           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr));
7926         }
7927     }
7928 
7929 }
7930 
7931 /*-----------------------------------------------------------------*/
7932 /* shiftR2Left2Result - shift right two bytes from left to result  */
7933 /*-----------------------------------------------------------------*/
7934 static void
shiftR2Left2Result(operand * left,int offl,operand * result,int offr,int shCount,int sign)7935 shiftR2Left2Result (operand * left, int offl, operand * result, int offr, int shCount, int sign)
7936 {
7937   int same = pic16_sameRegs (AOP (result), AOP (left));
7938   int i;
7939   DEBUGpic16_emitcode ("; ***", "%s  %d shCount:%d same:%d sign:%d", __FUNCTION__, __LINE__, shCount, same, sign);
7940 
7941   if (same && (offl != offr))   // shift right bytes
7942     {
7943       if (offr < offl)
7944         {
7945           for (i = 0; i < 2; i++)
7946             {
7947               pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (result), offl + i));
7948               pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr + i));
7949             }
7950         }
7951       else                      // just treat as different later on
7952         {
7953           same = 0;
7954         }
7955     }
7956 
7957   switch (shCount)
7958     {
7959     case 0:
7960       break;
7961     case 1:
7962     case 2:
7963     case 3:
7964       /* obtain sign from left operand */
7965       if (sign)
7966         pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (left), offr + MSB16));
7967       else
7968         emitCLRC;
7969 
7970       if (same)
7971         {
7972           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr + MSB16));
7973           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr));
7974         }
7975       else
7976         {
7977           pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (left), offl + MSB16));
7978           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr + MSB16));
7979           pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (left), offl));
7980           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
7981         }
7982 
7983       while (--shCount)
7984         {
7985           if (sign)
7986             /* now get sign from already assigned result (avoid BANKSEL) */
7987             pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (result), offr + MSB16));
7988           else
7989             emitCLRC;
7990           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr + MSB16));
7991           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr));
7992         }
7993       break;
7994     case 4:
7995     case 5:
7996       if (same)
7997         {
7998 
7999           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xf0));
8000           pic16_emitpcode (POC_ANDWF, pic16_popGet (AOP (result), offr));
8001           pic16_emitpcode (POC_SWAPF, pic16_popGet (AOP (result), offr));
8002 
8003           pic16_emitpcode (POC_SWAPF, pic16_popGet (AOP (result), offr + MSB16));
8004           pic16_emitpcode (POC_ANDFW, pic16_popGet (AOP (result), offr + MSB16));
8005           pic16_emitpcode (POC_XORWF, pic16_popGet (AOP (result), offr + MSB16));
8006           pic16_emitpcode (POC_ADDWF, pic16_popGet (AOP (result), offr));
8007         }
8008       else
8009         {
8010           pic16_emitpcode (POC_SWAPFW, pic16_popGet (AOP (left), offl));
8011           pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x0f));
8012           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
8013 
8014           pic16_emitpcode (POC_SWAPFW, pic16_popGet (AOP (left), offl + MSB16));
8015           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr + MSB16));
8016           pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0xf0));
8017           pic16_emitpcode (POC_XORWF, pic16_popGet (AOP (result), offr + MSB16));
8018           pic16_emitpcode (POC_ADDWF, pic16_popGet (AOP (result), offr));
8019         }
8020 
8021       if (shCount >= 5)
8022         {
8023           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr + MSB16));
8024           pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (result), offr));
8025         }
8026 
8027       if (sign)
8028         {
8029           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xf0 + (shCount - 4) * 8));
8030           pic16_emitpcode (POC_BTFSC,
8031                            pic16_newpCodeOpBit (pic16_aopGet (AOP (result), offr + MSB16, FALSE, FALSE), 7 - shCount, 0,
8032                                                 PO_GPR_REGISTER));
8033           pic16_emitpcode (POC_ADDWF, pic16_popGet (AOP (result), offr + MSB16));
8034         }
8035 
8036       break;
8037 
8038     case 6:
8039       if (same)
8040         {
8041 
8042           pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr));
8043           pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr + MSB16));
8044 
8045           pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr));
8046           pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr + MSB16));
8047           pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (result), offr));
8048           pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x03));
8049           if (sign)
8050             {
8051               pic16_emitpcode (POC_BTFSC,
8052                                pic16_newpCodeOpBit (pic16_aopGet (AOP (result), offr, FALSE, FALSE), 0, 0, PO_GPR_REGISTER));
8053               pic16_emitpcode (POC_IORLW, pic16_popGetLit (0xfc));
8054             }
8055           pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (result), offr + MSB16));
8056           pic16_emitpcode (POC_XORWF, pic16_popGet (AOP (result), offr + MSB16));
8057           pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (result), offr + MSB16));
8058           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
8059         }
8060       else
8061         {
8062           pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (left), offl));
8063           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr + MSB16));
8064           pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (left), offl + MSB16));
8065           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
8066           pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr + MSB16));
8067           pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr));
8068           pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (result), offr + MSB16));
8069           pic16_emitpcode (POC_ANDLW, pic16_popGetLit (0x03));
8070           if (sign)
8071             {
8072               pic16_emitpcode (POC_BTFSC,
8073                                pic16_newpCodeOpBit (pic16_aopGet (AOP (result), offr + MSB16, FALSE, FALSE), 0, 0,
8074                                                     PO_GPR_REGISTER));
8075               pic16_emitpcode (POC_IORLW, pic16_popGetLit (0xfc));
8076             }
8077           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr + MSB16));
8078           //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8079 
8080 
8081         }
8082 
8083       break;
8084     case 7:
8085       pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (left), offl));
8086       pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (left), offl + MSB16));
8087       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offr));
8088       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offr + MSB16));
8089       if (sign)
8090         {
8091           emitSKPNC;
8092           pic16_emitpcode (POC_DECF, pic16_popGet (AOP (result), offr + MSB16));
8093         }
8094       else
8095         pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (result), offr + MSB16));
8096     }
8097 }
8098 
8099 
8100 /*-----------------------------------------------------------------*/
8101 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8102 /*-----------------------------------------------------------------*/
8103 static void
shiftLLeftOrResult(operand * left,int offl,operand * result,int offr,int shCount)8104 shiftLLeftOrResult (operand * left, int offl, operand * result, int offr, int shCount)
8105 {
8106   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
8107 
8108   pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offl));
8109   /* shift left accumulator */
8110   AccLsh (shCount, 1);
8111   /* or with result */
8112   /* back to result */
8113   pic16_emitpcode (POC_IORWF, pic16_popGet (AOP (result), offr));
8114 }
8115 
8116 /*-----------------------------------------------------------------*/
8117 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8118 /*-----------------------------------------------------------------*/
8119 static void
shiftRLeftOrResult(operand * left,int offl,operand * result,int offr,int shCount)8120 shiftRLeftOrResult (operand * left, int offl, operand * result, int offr, int shCount)
8121 {
8122   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
8123 
8124   pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offl));
8125   /* shift right accumulator */
8126   AccRsh (shCount, 1);
8127   /* or with result */
8128   /* back to result */
8129   pic16_emitpcode (POC_IORWF, pic16_popGet (AOP (result), offr));
8130 }
8131 
8132 /*-----------------------------------------------------------------*/
8133 /* genlshOne - left shift a one byte quantity by known count       */
8134 /*-----------------------------------------------------------------*/
8135 static void
genlshOne(operand * result,operand * left,int shCount)8136 genlshOne (operand * result, operand * left, int shCount)
8137 {
8138   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
8139   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8140 }
8141 
8142 /*-----------------------------------------------------------------*/
8143 /* genlshTwo - left shift two bytes by known amount != 0           */
8144 /*-----------------------------------------------------------------*/
8145 static void
genlshTwo(operand * result,operand * left,int shCount)8146 genlshTwo (operand * result, operand * left, int shCount)
8147 {
8148   int size;
8149 
8150   DEBUGpic16_emitcode ("; ***", "%s  %d shCount:%d", __FUNCTION__, __LINE__, shCount);
8151   size = pic16_getDataSize (result);
8152 
8153   /* if shCount >= 8 */
8154   if (shCount >= 8)
8155     {
8156       shCount -= 8;
8157 
8158       if (size > 1)
8159         {
8160           if (shCount)
8161             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8162           else
8163             movLeft2Result (left, LSB, result, MSB16);
8164         }
8165       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), LSB));
8166     }
8167 
8168   /*  1 <= shCount <= 7 */
8169   else
8170     {
8171       if (size == 1)
8172         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8173       else
8174         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8175     }
8176 }
8177 
8178 /*-----------------------------------------------------------------*/
8179 /* shiftLLong - shift left one long from left to result            */
8180 /* offr = LSB or MSB16                                             */
8181 /*-----------------------------------------------------------------*/
8182 static void
shiftLLong(operand * left,operand * result,int offr)8183 shiftLLong (operand * left, operand * result, int offr)
8184 {
8185   int size = AOP_SIZE (result);
8186   int same = pic16_sameRegs (AOP (left), AOP (result));
8187   int i;
8188 
8189   DEBUGpic16_emitcode ("; ***", "%s  %d  offr:%d size:%d", __FUNCTION__, __LINE__, offr, size);
8190 
8191   if (same && (offr == MSB16))  //shift one byte
8192     {
8193       for (i = size - 1; i >= MSB16; i--)
8194         {
8195           pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), i - 1));
8196           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (left), i));
8197         }
8198     }
8199   else
8200     {
8201       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), LSB));
8202     }
8203 
8204   if (size > LSB + offr)
8205     {
8206       if (same)
8207         {
8208           pic16_emitpcode (POC_ADDWF, pic16_popGet (AOP (left), LSB + offr));
8209         }
8210       else
8211         {
8212           pic16_emitpcode (POC_ADDFW, pic16_popGet (AOP (left), LSB));
8213           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), LSB + offr));
8214         }
8215     }
8216 
8217   if (size > MSB16 + offr)
8218     {
8219       if (same)
8220         {
8221           pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (left), MSB16 + offr));
8222         }
8223       else
8224         {
8225           pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (left), MSB16));
8226           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), MSB16 + offr));
8227         }
8228     }
8229 
8230   if (size > MSB24 + offr)
8231     {
8232       if (same)
8233         {
8234           pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (left), MSB24 + offr));
8235         }
8236       else
8237         {
8238           pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (left), MSB24));
8239           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), MSB24 + offr));
8240         }
8241     }
8242 
8243   if (size > MSB32 + offr)
8244     {
8245       if (same)
8246         {
8247           pic16_emitpcode (POC_RLCF, pic16_popGet (AOP (left), MSB32 + offr));
8248         }
8249       else
8250         {
8251           pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (left), MSB32));
8252           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), MSB32 + offr));
8253         }
8254     }
8255   if (offr != LSB)
8256     pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), LSB));
8257 
8258 }
8259 
8260 /*-----------------------------------------------------------------*/
8261 /* genlshFour - shift four byte by a known amount != 0             */
8262 /*-----------------------------------------------------------------*/
8263 static void
genlshFour(operand * result,operand * left,int shCount)8264 genlshFour (operand * result, operand * left, int shCount)
8265 {
8266   int size;
8267 
8268   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
8269   size = AOP_SIZE (result);
8270 
8271   /* if shifting more that 3 bytes */
8272   if (shCount >= 24)
8273     {
8274       shCount -= 24;
8275       if (shCount)
8276         /* lowest order of left goes to the highest
8277            order of the destination */
8278         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8279       else
8280         movLeft2Result (left, LSB, result, MSB32);
8281 
8282       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), LSB));
8283       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), MSB16));
8284       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), MSB24));
8285 
8286       return;
8287     }
8288 
8289   /* more than two bytes */
8290   else if (shCount >= 16)
8291     {
8292       /* lower order two bytes goes to higher order two bytes */
8293       shCount -= 16;
8294       /* if some more remaining */
8295       if (shCount)
8296         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8297       else
8298         {
8299           movLeft2Result (left, MSB16, result, MSB32);
8300           movLeft2Result (left, LSB, result, MSB24);
8301         }
8302       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), LSB));
8303       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), MSB16));
8304       return;
8305     }
8306 
8307   /* if more than 1 byte */
8308   else if (shCount >= 8)
8309     {
8310       /* lower order three bytes goes to higher order  three bytes */
8311       shCount -= 8;
8312       if (size == 2)
8313         {
8314           if (shCount)
8315             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8316           else
8317             movLeft2Result (left, LSB, result, MSB16);
8318         }
8319       else                      /* size = 4 */
8320         {
8321           if (shCount == 0)
8322             {
8323               movLeft2Result (left, MSB24, result, MSB32);
8324               movLeft2Result (left, MSB16, result, MSB24);
8325               movLeft2Result (left, LSB, result, MSB16);
8326               pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), LSB));
8327             }
8328           else if (shCount == 1)
8329             shiftLLong (left, result, MSB16);
8330           else
8331             {
8332               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8333               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8334               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8335               pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), LSB));
8336             }
8337         }
8338     }
8339 
8340   /* 1 <= shCount <= 7 */
8341   else if (shCount <= 3)
8342     {
8343       shiftLLong (left, result, LSB);
8344       while (--shCount >= 1)
8345         shiftLLong (result, result, LSB);
8346     }
8347   /* 3 <= shCount <= 7, optimize */
8348   else
8349     {
8350       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8351       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8352       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8353     }
8354 }
8355 
8356 /*-----------------------------------------------------------------*/
8357 /* genLeftShiftLiteral - left shifting by known count              */
8358 /*-----------------------------------------------------------------*/
8359 void
pic16_genLeftShiftLiteral(operand * left,operand * right,operand * result,iCode * ic)8360 pic16_genLeftShiftLiteral (operand * left, operand * right, operand * result, iCode * ic)
8361 {
8362   int shCount = abs ((int) ulFromVal (AOP (right)->aopu.aop_lit));
8363   int size;
8364 
8365   FENTRY;
8366   DEBUGpic16_emitcode ("; ***", "shCount:%d", shCount);
8367   pic16_freeAsmop (right, NULL, ic, TRUE);
8368 
8369   pic16_aopOp (left, ic, FALSE);
8370   pic16_aopOp (result, ic, TRUE);
8371 
8372   size = getSize (operandType (result));
8373 
8374 #if VIEW_SIZE
8375   pic16_emitcode ("; shift left ", "result %d, left %d", size, AOP_SIZE (left));
8376 #endif
8377 
8378   /* I suppose that the left size >= result size */
8379   if (shCount == 0)
8380     {
8381       while (size--)
8382         {
8383           movLeft2Result (left, size, result, size);
8384         }
8385     }
8386 
8387   else if (shCount >= (size * 8))
8388     while (size--)
8389       pic16_aopPut (AOP (result), zero, size);
8390   else
8391     {
8392       switch (size)
8393         {
8394         case 1:
8395           genlshOne (result, left, shCount);
8396           break;
8397 
8398         case 2:
8399         case 3:
8400           genlshTwo (result, left, shCount);
8401           break;
8402 
8403         case 4:
8404           genlshFour (result, left, shCount);
8405           break;
8406         }
8407     }
8408   pic16_freeAsmop (left, NULL, ic, TRUE);
8409   pic16_freeAsmop (result, NULL, ic, TRUE);
8410 }
8411 
8412 /*-----------------------------------------------------------------*
8413  * genMultiAsm - repeat assembly instruction for size of register.
8414  * if endian == 1, then the high byte (i.e base address + size of
8415  * register) is used first else the low byte is used first;
8416  *-----------------------------------------------------------------*/
8417 static void
genMultiAsm(PIC_OPCODE poc,operand * reg,int size,int endian)8418 genMultiAsm (PIC_OPCODE poc, operand * reg, int size, int endian)
8419 {
8420 
8421   int offset = 0;
8422 
8423   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
8424 
8425   if (!reg)
8426     return;
8427 
8428   if (!endian)
8429     {
8430       endian = 1;
8431     }
8432   else
8433     {
8434       endian = -1;
8435       offset = size - 1;
8436     }
8437 
8438   while (size--)
8439     {
8440       pic16_emitpcode (poc, pic16_popGet (AOP (reg), offset));
8441       offset += endian;
8442     }
8443 
8444 }
8445 
8446 /*-----------------------------------------------------------------*/
8447 /* genrshOne - right shift a one byte quantity by known count      */
8448 /*-----------------------------------------------------------------*/
8449 static void
genrshOne(operand * result,operand * left,int shCount,int sign)8450 genrshOne (operand * result, operand * left, int shCount, int sign)
8451 {
8452   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
8453   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8454 }
8455 
8456 /*-----------------------------------------------------------------*/
8457 /* genrshTwo - right shift two bytes by known amount != 0          */
8458 /*-----------------------------------------------------------------*/
8459 static void
genrshTwo(operand * result,operand * left,int shCount,int sign)8460 genrshTwo (operand * result, operand * left, int shCount, int sign)
8461 {
8462   DEBUGpic16_emitcode ("; ***", "%s  %d shCount:%d", __FUNCTION__, __LINE__, shCount);
8463   /* if shCount >= 8 */
8464   if (shCount >= 8)
8465     {
8466       shCount -= 8;
8467       if (shCount)
8468         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
8469       else
8470         movLeft2Result (left, MSB16, result, LSB);
8471 
8472       pic16_addSign (result, 1, sign);
8473     }
8474 
8475   /*  1 <= shCount <= 7 */
8476   else
8477     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8478 }
8479 
8480 /*-----------------------------------------------------------------*/
8481 /* shiftRLong - shift right one long from left to result           */
8482 /* offl = LSB or MSB16                                             */
8483 /*-----------------------------------------------------------------*/
8484 static void
shiftRLong(operand * left,int offl,operand * result,int sign)8485 shiftRLong (operand * left, int offl, operand * result, int sign)
8486 {
8487   int size = AOP_SIZE (result);
8488   int same = pic16_sameRegs (AOP (left), AOP (result));
8489   int i;
8490   DEBUGpic16_emitcode ("; ***", "%s  %d  offl:%d size:%d", __FUNCTION__, __LINE__, offl, size);
8491 
8492   if (same && (offl == MSB16))  //shift one byte right
8493     {
8494       for (i = MSB16; i < size; i++)
8495         {
8496           pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), i));
8497           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (left), i - 1));
8498         }
8499     }
8500 
8501   if (sign)
8502     pic16_emitpcode (POC_RLCFW, pic16_popGet (AOP (left), MSB32));
8503   else
8504     emitCLRC;
8505 
8506   if (same)
8507     {
8508       if (offl == LSB)
8509         pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (left), MSB32));
8510     }
8511   else
8512     {
8513       pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (left), MSB32));
8514       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), MSB32 - offl));
8515     }
8516 
8517   if (offl == MSB16)
8518     {
8519       /* add sign of "a" */
8520       pic16_addSign (result, MSB32, sign);
8521     }
8522 
8523   if (same)
8524     {
8525       pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (left), MSB24));
8526     }
8527   else
8528     {
8529       pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (left), MSB24));
8530       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), MSB24 - offl));
8531     }
8532 
8533   if (same)
8534     {
8535       pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (left), MSB16));
8536     }
8537   else
8538     {
8539       pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (left), MSB16));
8540       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), MSB16 - offl));
8541     }
8542 
8543   if (same)
8544     {
8545       pic16_emitpcode (POC_RRCF, pic16_popGet (AOP (left), LSB));
8546     }
8547   else
8548     {
8549       if (offl == LSB)
8550         {
8551           pic16_emitpcode (POC_RRCFW, pic16_popGet (AOP (left), LSB));
8552           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), LSB));
8553         }
8554     }
8555 }
8556 
8557 /*-----------------------------------------------------------------*/
8558 /* genrshFour - shift four byte by a known amount != 0             */
8559 /*-----------------------------------------------------------------*/
8560 static void
genrshFour(operand * result,operand * left,int shCount,int sign)8561 genrshFour (operand * result, operand * left, int shCount, int sign)
8562 {
8563   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
8564   /* if shifting more that 3 bytes */
8565   if (shCount >= 24)
8566     {
8567       shCount -= 24;
8568       if (shCount)
8569         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8570       else
8571         movLeft2Result (left, MSB32, result, LSB);
8572 
8573       pic16_addSign (result, MSB16, sign);
8574     }
8575   else if (shCount >= 16)
8576     {
8577       shCount -= 16;
8578       if (shCount)
8579         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8580       else
8581         {
8582           movLeft2Result (left, MSB24, result, LSB);
8583           movLeft2Result (left, MSB32, result, MSB16);
8584         }
8585       pic16_addSign (result, MSB24, sign);
8586     }
8587   else if (shCount >= 8)
8588     {
8589       shCount -= 8;
8590       if (shCount == 1)
8591         shiftRLong (left, MSB16, result, sign);
8592       else if (shCount == 0)
8593         {
8594           movLeft2Result (left, MSB16, result, LSB);
8595           movLeft2Result (left, MSB24, result, MSB16);
8596           movLeft2Result (left, MSB32, result, MSB24);
8597           pic16_addSign (result, MSB32, sign);
8598         }
8599       else                      //shcount >= 2
8600         {
8601           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8602           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8603           /* the last shift is signed */
8604           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8605           pic16_addSign (result, MSB32, sign);
8606         }
8607     }
8608   else                          /* 1 <= shCount <= 7 */
8609     {
8610       if (shCount <= 2)
8611         {
8612           shiftRLong (left, LSB, result, sign);
8613           if (shCount == 2)
8614             shiftRLong (result, LSB, result, sign);
8615         }
8616       else
8617         {
8618           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8619           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8620           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8621         }
8622     }
8623 }
8624 
8625 /*-----------------------------------------------------------------*/
8626 /* genRightShiftLiteral - right shifting by known count            */
8627 /*-----------------------------------------------------------------*/
8628 static void
genRightShiftLiteral(operand * left,operand * right,operand * result,iCode * ic,int sign)8629 genRightShiftLiteral (operand * left, operand * right, operand * result, iCode * ic, int sign)
8630 {
8631   int shCount = abs ((int) ulFromVal (AOP (right)->aopu.aop_lit));
8632   int lsize, res_size;
8633 
8634   pic16_freeAsmop (right, NULL, ic, TRUE);
8635 
8636   pic16_aopOp (left, ic, FALSE);
8637   pic16_aopOp (result, ic, TRUE);
8638 
8639   DEBUGpic16_emitcode ("; ***", "%s  %d shCount:%d result:%d left:%d", __FUNCTION__, __LINE__, shCount, AOP_SIZE (result),
8640                        AOP_SIZE (left));
8641 
8642 #if VIEW_SIZE
8643   pic16_emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result), AOP_SIZE (left));
8644 #endif
8645 
8646   lsize = pic16_getDataSize (left);
8647   res_size = pic16_getDataSize (result);
8648   /* test the LEFT size !!! */
8649 
8650   /* I suppose that the left size >= result size */
8651   if (shCount == 0)
8652     {
8653       assert (res_size <= lsize);
8654       while (res_size--)
8655         {
8656           pic16_mov2f (AOP (result), AOP (left), res_size);
8657         }                       // for
8658     }
8659   else if (shCount >= (lsize * 8))
8660     {
8661       if (sign)
8662         {
8663           /*
8664            * Do NOT use
8665            *    CLRF    result
8666            *    BTFSC   left, 7
8667            *    SETF    result
8668            * even for 8-bit operands; result might be an SFR.
8669            */
8670           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0x00));
8671           pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (pic16_popGet (AOP (left), lsize - 1), 7));
8672           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xff));
8673           while (res_size--)
8674             {
8675               pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), res_size));
8676             }
8677         }
8678       else                      // unsigned
8679         {
8680           while (res_size--)
8681             {
8682               pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), res_size));
8683             }
8684         }
8685     }
8686   else                          // 0 < shCount < 8*lsize
8687     {
8688       switch (res_size)
8689         {
8690         case 1:
8691           genrshOne (result, left, shCount, sign);
8692           break;
8693 
8694         case 2:
8695           genrshTwo (result, left, shCount, sign);
8696           break;
8697 
8698         case 4:
8699           genrshFour (result, left, shCount, sign);
8700           break;
8701         default:
8702           break;
8703         }
8704     }
8705 
8706   pic16_freeAsmop (left, NULL, ic, TRUE);
8707   pic16_freeAsmop (result, NULL, ic, TRUE);
8708 }
8709 
8710 /*-----------------------------------------------------------------*/
8711 /* genGenericShift - generates code for left or right shifting     */
8712 /*-----------------------------------------------------------------*/
8713 static void
genGenericShift(iCode * ic,int isShiftLeft)8714 genGenericShift (iCode * ic, int isShiftLeft)
8715 {
8716   operand *left, *right, *result;
8717   int offset;
8718   int sign, signedCount;
8719   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
8720   PIC_OPCODE pos_shift, neg_shift;
8721 
8722   FENTRY;
8723 
8724   right = IC_RIGHT (ic);
8725   left = IC_LEFT (ic);
8726   result = IC_RESULT (ic);
8727 
8728   pic16_aopOp (right, ic, FALSE);
8729   pic16_aopOp (left, ic, FALSE);
8730   pic16_aopOp (result, ic, TRUE);
8731 
8732   sign = !SPEC_USIGN (operandType (left));
8733   signedCount = !SPEC_USIGN (operandType (right));
8734 
8735   /* if the shift count is known then do it
8736      as efficiently as possible */
8737   if (AOP_TYPE (right) == AOP_LIT)
8738     {
8739       long lit = (long) ulFromVal (AOP (right)->aopu.aop_lit);
8740       if (signedCount && lit < 0)
8741         {
8742           lit = -lit;
8743           isShiftLeft = !isShiftLeft;
8744         }
8745       // we should modify right->aopu.aop_lit here!
8746       // Instead we use abs(shCount) in genXXXShiftLiteral()...
8747       // lit > 8*size is handled in pic16_genXXXShiftLiteral()
8748       if (isShiftLeft)
8749         pic16_genLeftShiftLiteral (left, right, result, ic);
8750       else
8751         genRightShiftLiteral (left, right, result, ic, sign);
8752 
8753       goto release;
8754     }                           // if (right is literal)
8755 
8756   /* shift count is unknown then we have to form a loop.
8757    * Note: we take only the lower order byte since shifting
8758    * more than 32 bits make no sense anyway, ( the
8759    * largest size of an object can be only 32 bits )
8760    * Note: we perform arithmetic shifts if the left operand is
8761    * signed and we do an (effective) right shift, i. e. we
8762    * shift in the sign bit from the left. */
8763 
8764   label_complete = newiTempLabel (NULL);
8765   label_loop_pos = newiTempLabel (NULL);
8766   label_loop_neg = NULL;
8767   label_negative = NULL;
8768   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
8769   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
8770 
8771   if (signedCount)
8772     {
8773       // additional labels needed
8774       label_loop_neg = newiTempLabel (NULL);
8775       label_negative = newiTempLabel (NULL);
8776     }                           // if
8777 
8778   /*
8779    * The code below overwrites the shift count for `val = (1 << val)'
8780    * when it assigns LEFT to RESULT (== RIGHT == shift count).
8781    * XXX: This problem should have been/is also addressed in ralloc.c,
8782    *      but the code there seems not to catch this case ...
8783    */
8784   if (pic16_sameRegs (AOP (right), AOP (result)))
8785     {
8786       // We abuse FSR0L as a temporary, pic16_popGetTempReg() is too costly.
8787       pic16_mov2w (AOP (right), 0);
8788       pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_fsr0l));
8789     }                           // if
8790 
8791   // copy source to result -- this will effectively truncate the left operand to the size of result!
8792   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
8793   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
8794   for (offset = 0; offset < min (AOP_SIZE (left), AOP_SIZE (result)); offset++)
8795     {
8796       pic16_mov2f (AOP (result), AOP (left), offset);
8797     }                           // for
8798 
8799   // if result is longer than left, fill with zeros (or sign)
8800   if (AOP_SIZE (left) < AOP_SIZE (result))
8801     {
8802       if (sign && AOP_SIZE (left) > 0)
8803         {
8804           // shift signed operand -- fill with sign
8805           pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
8806           pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (pic16_popGet (AOP (result), AOP_SIZE (left) - 1), 7));
8807           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
8808           for (offset = AOP_SIZE (left); offset < AOP_SIZE (result); offset++)
8809             {
8810               pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
8811             }                   // for
8812         }
8813       else
8814         {
8815           // shift unsigned operand -- fill result with zeros
8816           for (offset = AOP_SIZE (left); offset < AOP_SIZE (result); offset++)
8817             {
8818               pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offset));
8819             }                   // for
8820         }
8821     }                           // if (size mismatch)
8822 
8823   /* load/restore shift count */
8824   if (pic16_sameRegs (AOP (right), AOP (result)))
8825     {
8826       pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (&pic16_pc_fsr0l));
8827     }
8828   else
8829     {
8830       pic16_mov2w (AOP (right), 0);
8831     }                           // if
8832 
8833   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
8834   if (signedCount)
8835     pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
8836 
8837 #if 0
8838   // perform a shift by one (shift count is positive)
8839   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
8840   // 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])
8841   pic16_emitpLabel (label_loop_pos->key);
8842   emitCLRC;
8843   if (sign && (pos_shift == POC_RRCF))
8844     {
8845       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (pic16_popGet (AOP (result), AOP_SIZE (result) - 1), 7));
8846       emitSETC;
8847     }                           // if
8848   genMultiAsm (pos_shift, result, AOP_SIZE (result), pos_shift == POC_RRCF);
8849   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
8850   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
8851 #else
8852   // perform a shift by one (shift count is positive)
8853   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
8854   // 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])
8855   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
8856   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
8857   emitCLRC;
8858   pic16_emitpLabel (label_loop_pos->key);
8859   if (sign && (pos_shift == POC_RRCF))
8860     {
8861       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (pic16_popGet (AOP (result), AOP_SIZE (result) - 1), 7));
8862       emitSETC;
8863     }                           // if
8864   genMultiAsm (pos_shift, result, AOP_SIZE (result), pos_shift == POC_RRCF);
8865   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
8866   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
8867   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
8868 #endif
8869 
8870   if (signedCount)
8871     {
8872       pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
8873 
8874       pic16_emitpLabel (label_negative->key);
8875       // perform a shift by -1 (shift count is negative)
8876       // 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)
8877       emitCLRC;
8878       pic16_emitpLabel (label_loop_neg->key);
8879       if (sign && (neg_shift == POC_RRCF))
8880         {
8881           pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (pic16_popGet (AOP (result), AOP_SIZE (result) - 1), 7));
8882           emitSETC;
8883         }                       // if
8884       genMultiAsm (neg_shift, result, AOP_SIZE (result), neg_shift == POC_RRCF);
8885       //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
8886       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
8887       pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
8888     }                           // if (signedCount)
8889 
8890   pic16_emitpLabel (label_complete->key);
8891 
8892 release:
8893   pic16_freeAsmop (right, NULL, ic, TRUE);
8894   pic16_freeAsmop (left, NULL, ic, TRUE);
8895   pic16_freeAsmop (result, NULL, ic, TRUE);
8896 }
8897 
8898 static void
genLeftShift(iCode * ic)8899 genLeftShift (iCode * ic)
8900 {
8901   genGenericShift (ic, 1);
8902 }
8903 
8904 static void
genRightShift(iCode * ic)8905 genRightShift (iCode * ic)
8906 {
8907   genGenericShift (ic, 0);
8908 }
8909 
8910 
8911 /* load FSR0 with address of/from op according to pic16_isLitOp() or if lit is 1 */
8912 void
pic16_loadFSR0(operand * op,int lit)8913 pic16_loadFSR0 (operand * op, int lit)
8914 {
8915   if ((IS_SYMOP (op) && OP_SYMBOL (op)->remat) || pic16_isLitOp (op))
8916     {
8917       if (AOP_TYPE (op) == AOP_LIT)
8918         {
8919           /* handle 12 bit integers correctly */
8920           unsigned int val = (unsigned int) ulFromVal (AOP (op)->aopu.aop_lit);
8921           if ((val & 0x0fff) != val)
8922             {
8923               fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n", val, (val & 0x0fff));
8924               val &= 0x0fff;
8925             }
8926           pic16_emitpcode (POC_LFSR, pic16_popGetLit2 (0, pic16_popGetLit12 (val)));
8927         }
8928       else
8929         {
8930           pic16_emitpcode (POC_LFSR, pic16_popGetLit2 (0, pic16_popGet (AOP (op), 0)));
8931         }
8932     }
8933   else
8934     {
8935       assert (!IS_SYMOP (op) || !OP_SYMBOL (op)->remat);
8936       // set up FSR0 with address of result
8937       pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popGet (AOP (op), 0), pic16_popCopyReg (&pic16_pc_fsr0l)));
8938       pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popGet (AOP (op), 1), pic16_popCopyReg (&pic16_pc_fsr0h)));
8939     }
8940 }
8941 
8942 /*----------------------------------------------------------------*/
8943 /* pic16_derefPtr - move one byte from the location ptr points to */
8944 /*                  to WREG (doWrite == 0) or one byte from WREG   */
8945 /*                  to the location ptr points to (doWrite != 0)   */
8946 /*----------------------------------------------------------------*/
8947 static void
pic16_derefPtr(operand * ptr,int p_type,int doWrite,int * fsr0_setup)8948 pic16_derefPtr (operand * ptr, int p_type, int doWrite, int *fsr0_setup)
8949 {
8950   if (!IS_PTR (operandType (ptr)))
8951     {
8952       if (doWrite)
8953         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (ptr), 0));
8954       else
8955         pic16_mov2w (AOP (ptr), 0);
8956       return;
8957     }
8958 
8959   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
8960   /* We might determine pointer type right here: */
8961   p_type = DCL_TYPE (operandType (ptr));
8962 
8963   switch (p_type)
8964     {
8965     case POINTER:
8966     case FPOINTER:
8967     case IPOINTER:
8968     case PPOINTER:
8969       if (!fsr0_setup || !*fsr0_setup)
8970         {
8971           pic16_loadFSR0 (ptr, 0);
8972           if (fsr0_setup)
8973             *fsr0_setup = 1;
8974         }
8975       if (doWrite)
8976         pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_indf0));
8977       else
8978         pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (&pic16_pc_indf0));
8979       break;
8980 
8981     case GPOINTER:
8982       if (AOP (ptr)->aopu.aop_reg[2])
8983         {
8984           if (doWrite)
8985             pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec));
8986           // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
8987           mov2fp (pic16_popCopyReg (&pic16_pc_fsr0l), AOP (ptr), 0);
8988           mov2fp (pic16_popCopyReg (&pic16_pc_prodl), AOP (ptr), 1);
8989           pic16_mov2w (AOP (ptr), 2);
8990           pic16_callGenericPointerRW (doWrite, 1);
8991         }
8992       else
8993         {
8994           // data pointer (just 2 byte given)
8995           if (!fsr0_setup || !*fsr0_setup)
8996             {
8997               pic16_loadFSR0 (ptr, 0);
8998               if (fsr0_setup)
8999                 *fsr0_setup = 1;
9000             }
9001           if (doWrite)
9002             pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_indf0));
9003           else
9004             pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (&pic16_pc_indf0));
9005         }
9006       break;
9007 
9008     case CPOINTER:
9009       /* XXX: Writing to CPOINTERs not (yet) implemented. */
9010       assert (!doWrite && "Cannot write into __code space!");
9011       if ((AOP_TYPE (ptr) == AOP_PCODE)
9012           && ((AOP (ptr)->aopu.pcop->type == PO_IMMEDIATE) || (AOP (ptr)->aopu.pcop->type == PO_DIR)))
9013         {
9014           pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (ptr), 0));
9015           pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptrl));
9016           pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (ptr), 1));
9017           pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptrh));
9018           pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (ptr), 2));
9019           pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptru));
9020         }
9021       else
9022         {
9023           mov2fp (pic16_popCopyReg (&pic16_pc_tblptrl), AOP (ptr), 0);
9024           mov2fp (pic16_popCopyReg (&pic16_pc_tblptrh), AOP (ptr), 1);
9025           mov2fp (pic16_popCopyReg (&pic16_pc_tblptru), AOP (ptr), 2);
9026         }                       // if
9027 
9028       pic16_emitpcodeNULLop (POC_TBLRD_POSTINC);
9029       pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (&pic16_pc_tablat));
9030       break;
9031 
9032     default:
9033       assert (0 && "invalid pointer type specified");
9034       break;
9035     }
9036 }
9037 
9038 /*-----------------------------------------------------------------*/
9039 /* genUnpackBits - generates code for unpacking bits               */
9040 /*-----------------------------------------------------------------*/
9041 static void
genUnpackBits(operand * result,operand * left,char * rname,int ptype)9042 genUnpackBits (operand * result, operand * left, char *rname, int ptype)
9043 {
9044   int shCnt;
9045   sym_link *etype;
9046   unsigned blen = 0, bstr = 0;
9047   int same;
9048   pCodeOp *op;
9049 
9050   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9051   etype = getSpec (operandType (result));
9052 
9053   //    if(IS_BITFIELD(etype)) {
9054   blen = SPEC_BLEN (etype);
9055   bstr = SPEC_BSTR (etype);
9056   //    }
9057 
9058   DEBUGpic16_emitcode ("; ***", "%s  %d - reading %s bitfield int %s destination", __FUNCTION__, __LINE__,
9059                        SPEC_USIGN (OP_SYM_ETYPE (left)) ? "an unsigned" : "a signed",
9060                        SPEC_USIGN (OP_SYM_TYPE (result)) ? "an unsigned" : "a signed");
9061 
9062 #if 1
9063   if ((blen == 1) && (bstr < 8) && (!IS_PTR (operandType (left)) || IS_DIRECT (left) || PIC_IS_DATA_PTR (operandType (left))))
9064     {
9065       /* it is a single bit, so use the appropriate bit instructions */
9066       DEBUGpic16_emitcode (";", "%s %d optimize bit read", __FUNCTION__, __LINE__);
9067 
9068       same = pic16_sameRegs (AOP (left), AOP (result));
9069       op = (same ? pic16_popCopyReg (&pic16_pc_wreg) : pic16_popGet (AOP (result), 0));
9070       pic16_emitpcode (POC_CLRF, op);
9071 
9072       if (!IS_PTR (operandType (left)) || IS_DIRECT (left))
9073         {
9074           /* workaround to reduce the extra lfsr instruction */
9075           pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (pic16_popGet (AOP (left), 0), bstr));
9076         }
9077       else
9078         {
9079           assert (PIC_IS_DATA_PTR (operandType (left)));
9080           pic16_loadFSR0 (left, 0);
9081           pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (pic16_popCopyReg (&pic16_pc_indf0), bstr));
9082         }
9083 
9084       if (SPEC_USIGN (OP_SYM_ETYPE (left)))
9085         {
9086           /* unsigned bitfields result in either 0 or 1 */
9087           pic16_emitpcode (POC_INCF, op);
9088         }
9089       else
9090         {
9091           /* signed bitfields result in either 0 or -1 */
9092           pic16_emitpcode (POC_DECF, op);
9093         }
9094       if (same)
9095         {
9096           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
9097         }
9098 
9099       pic16_addSign (result, 1, !SPEC_USIGN (OP_SYM_TYPE (result)));
9100       return;
9101     }
9102 
9103 #endif
9104 
9105   if (!IS_PTR (operandType (left)) || IS_DIRECT (left))
9106     {
9107       // access symbol directly
9108       pic16_mov2w (AOP (left), 0);
9109     }
9110   else
9111     {
9112       pic16_derefPtr (left, ptype, 0, NULL);
9113     }
9114 
9115   /* if we have bitdisplacement then it fits   */
9116   /* into this byte completely or if length is */
9117   /* less than a byte                          */
9118   if ((shCnt = SPEC_BSTR (etype)) || (SPEC_BLEN (etype) <= 8))
9119     {
9120 
9121       /* shift right acc */
9122       AccRsh (shCnt, 0);
9123 
9124       pic16_emitpcode (POC_ANDLW, pic16_popGetLit ((((unsigned char) - 1) >> (8 - SPEC_BLEN (etype))) & SRMask[shCnt]));
9125 
9126       /* VR -- normally I would use the following, but since we use the hack,
9127        * to avoid the masking from AccRsh, why not mask it right now? */
9128 
9129       /*
9130          pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9131        */
9132 
9133       /* extend signed bitfields to 8 bits */
9134       if (!SPEC_USIGN (OP_SYM_ETYPE (left)) && (bstr + blen < 8))
9135         {
9136           assert (blen + bstr > 0);
9137           pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (pic16_popCopyReg (&pic16_pc_wreg), bstr + blen - 1));
9138           pic16_emitpcode (POC_IORLW, pic16_popGetLit (0xFF << (bstr + blen)));
9139         }
9140 
9141       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
9142 
9143       pic16_addSign (result, 1, !SPEC_USIGN (OP_SYM_TYPE (result)));
9144       return;
9145     }
9146 
9147   fprintf (stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
9148   fprintf (stderr, "bitfields of size >=8. Instead of generating wrong code, bailing out...\n");
9149   exit (EXIT_FAILURE);
9150 }
9151 
9152 
9153 static void
genDataPointerGet(operand * left,operand * result,iCode * ic)9154 genDataPointerGet (operand * left, operand * result, iCode * ic)
9155 {
9156   int size, offset = 0, leoffset = 0;
9157 
9158   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9159   pic16_aopOp (result, ic, TRUE);
9160 
9161   FENTRY;
9162 
9163   size = AOP_SIZE (result);
9164 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9165 
9166 
9167 #if 1
9168   if (!strcmp (pic16_aopGet (AOP (result), 0, TRUE, FALSE), pic16_aopGet (AOP (left), 0, TRUE, FALSE)))
9169     {
9170       DEBUGpic16_emitcode ("; ***", "left and result names are same, skipping moving");
9171       goto release;
9172     }
9173 #endif
9174 
9175   if (AOP (left)->aopu.pcop->type == PO_DIR)
9176     leoffset = PCOR (AOP (left)->aopu.pcop)->instance;
9177 
9178   DEBUGpic16_pic16_AopType (__LINE__, left, NULL, result);
9179 
9180   while (size--)
9181     {
9182       DEBUGpic16_emitcode ("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9183 
9184 //              pic16_DumpOp("(result)",result);
9185       if (pic16_isLitAop (AOP (result)))
9186         {
9187           pic16_mov2w (AOP (left), offset);     // patch 8
9188           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
9189         }
9190       else
9191         {
9192           pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popGet (AOP (left), offset),        //patch 8
9193                            pic16_popGet (AOP (result), offset)));
9194         }
9195 
9196       offset++;
9197       leoffset++;
9198     }
9199 
9200 release:
9201   pic16_freeAsmop (result, NULL, ic, TRUE);
9202 }
9203 
9204 
9205 
9206 /*-----------------------------------------------------------------*/
9207 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9208 /*-----------------------------------------------------------------*/
9209 static void
genNearPointerGet(operand * left,operand * result,iCode * ic)9210 genNearPointerGet (operand * left, operand * result, iCode * ic)
9211 {
9212 //  asmop *aop = NULL;
9213   //regs *preg = NULL ;
9214   sym_link *rtype, *retype;
9215   sym_link *ltype, *letype;
9216 
9217   FENTRY;
9218 
9219   rtype = operandType (result);
9220   retype = getSpec (rtype);
9221   ltype = operandType (left);
9222   letype = getSpec (ltype);
9223 
9224   pic16_aopOp (left, ic, FALSE);
9225 
9226 //    pic16_DumpOp("(left)",left);
9227 //    pic16_DumpOp("(result)",result);
9228 
9229   /* if left is rematerialisable and
9230    * result is not bit variable type and
9231    * the left is pointer to data space i.e
9232    * lower 128 bytes of space */
9233 
9234   if (AOP_TYPE (left) == AOP_PCODE && !IS_BITFIELD (retype) && DCL_TYPE (ltype) == POINTER)
9235     {
9236 
9237       genDataPointerGet (left, result, ic);
9238       pic16_freeAsmop (left, NULL, ic, TRUE);
9239       return;
9240     }
9241 
9242   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9243   pic16_aopOp (result, ic, TRUE);
9244 
9245   DEBUGpic16_pic16_AopType (__LINE__, left, NULL, result);
9246 
9247 #if 1
9248   if (IS_BITFIELD (retype) && (SPEC_BLEN (retype) == 1))
9249     {
9250       iCode *nextic;
9251       pCodeOp *jop;
9252       int bitstrt;
9253 
9254       /* if this is bitfield of size 1, see if we are checking the value
9255        * of a single bit in an if-statement,
9256        * if yes, then don't generate usual code, but execute the
9257        * genIfx directly -- VR */
9258 
9259       nextic = ic->next;
9260 
9261       /* CHECK: if next iCode is IFX
9262        * and current result operand is nextic's conditional operand
9263        * and current result operand live ranges ends at nextic's key number
9264        */
9265       if ((nextic->op == IFX) && (result == IC_COND (nextic)) && (OP_LIVETO (result) == nextic->seq) && (OP_SYMBOL (left)->remat)       // below fails for "if (p->bitfield)"
9266          )
9267         {
9268           /* everything is ok then */
9269           /* find a way to optimize the genIfx iCode */
9270 
9271           bitstrt = SPEC_BSTR (retype) % 8;
9272 
9273           jop = pic16_popCopyGPR2Bit (pic16_popGet (AOP (left), 0), bitstrt);
9274 
9275           genIfxpCOpJump (nextic, jop);
9276 
9277           pic16_freeAsmop (left, NULL, ic, TRUE);
9278           pic16_freeAsmop (result, NULL, ic, TRUE);
9279           return;
9280         }
9281     }
9282 #endif
9283 
9284   /* if bitfield then unpack the bits */
9285   if (IS_BITFIELD (letype))
9286     genUnpackBits (result, left, NULL, POINTER);
9287   else
9288     {
9289       /* we have can just get the values */
9290       int size = AOP_SIZE (result);
9291       int offset = 0;
9292 
9293       DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9294 
9295       pic16_loadFSR0 (left, 0);
9296 
9297       while (size--)
9298         {
9299           if (size)
9300             {
9301               pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg (&pic16_pc_postinc0),
9302                                pic16_popGet (AOP (result), offset++)));
9303             }
9304           else
9305             {
9306               pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg (&pic16_pc_indf0),
9307                                pic16_popGet (AOP (result), offset++)));
9308             }
9309         }
9310     }
9311 
9312 #if 0
9313   /* now some housekeeping stuff */
9314   if (aop)
9315     {
9316       /* we had to allocate for this iCode */
9317       DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9318       pic16_freeAsmop (NULL, aop, ic, TRUE);
9319     }
9320   else
9321     {
9322       /* we did not allocate which means left
9323        * already in a pointer register, then
9324        * if size > 0 && this could be used again
9325        * we have to point it back to where it
9326        * belongs */
9327       DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9328       if (AOP_SIZE (result) > 1 && !OP_SYMBOL (left)->remat && (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth))
9329         {
9330 //        int size = AOP_SIZE(result) - 1;
9331 //        while (size--)
9332 //          pic16_emitcode("dec","%s",rname);
9333         }
9334     }
9335 #endif
9336 
9337   /* done */
9338   pic16_freeAsmop (left, NULL, ic, TRUE);
9339   pic16_freeAsmop (result, NULL, ic, TRUE);
9340 }
9341 
9342 /*-----------------------------------------------------------------*/
9343 /* genGenPointerGet - gget value from generic pointer space        */
9344 /*-----------------------------------------------------------------*/
9345 static void
genGenPointerGet(operand * left,operand * result,iCode * ic)9346 genGenPointerGet (operand * left, operand * result, iCode * ic)
9347 {
9348   int size;
9349   sym_link *letype = getSpec (operandType (left));
9350 
9351   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9352   pic16_aopOp (left, ic, FALSE);
9353   pic16_aopOp (result, ic, TRUE);
9354   size = AOP_SIZE (result);
9355 
9356   DEBUGpic16_pic16_AopType (__LINE__, left, NULL, result);
9357 
9358   /* if bit then unpack */
9359   if (IS_BITFIELD (letype))
9360     {
9361       genUnpackBits (result, left, "BAD", GPOINTER);
9362       goto release;
9363     }
9364 
9365   /* set up WREG:PRODL:FSR0L with address from left */
9366   mov2fp (pic16_popCopyReg (&pic16_pc_fsr0l), AOP (left), 0);
9367   mov2fp (pic16_popCopyReg (&pic16_pc_prodl), AOP (left), 1);
9368   pic16_mov2w (AOP (left), 2);
9369   pic16_callGenericPointerRW (0, size);
9370 
9371   assignResultValue (result, size, 1);
9372 
9373 release:
9374   pic16_freeAsmop (left, NULL, ic, TRUE);
9375   pic16_freeAsmop (result, NULL, ic, TRUE);
9376 }
9377 
9378 /*-----------------------------------------------------------------*/
9379 /* genConstPointerGet - get value from const generic pointer space */
9380 /*-----------------------------------------------------------------*/
9381 static void
genConstPointerGet(operand * left,operand * result,iCode * ic)9382 genConstPointerGet (operand * left, operand * result, iCode * ic)
9383 {
9384   //sym_link *retype = getSpec(operandType(result));
9385   // symbol *albl = newiTempLabel(NULL);        // patch 15
9386   // symbol *blbl = newiTempLabel(NULL);        //
9387   // PIC_OPCODE poc;                            // patch 15
9388   int size;
9389   int offset = 0;
9390 
9391   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9392   pic16_aopOp (left, ic, FALSE);
9393   pic16_aopOp (result, ic, TRUE);
9394   size = AOP_SIZE (result);
9395 
9396   /* if bit then unpack */
9397   if (IS_BITFIELD (getSpec (operandType (left))))
9398     {
9399       genUnpackBits (result, left, "BAD", GPOINTER);
9400       goto release;
9401     }                           // if
9402 
9403   DEBUGpic16_pic16_AopType (__LINE__, left, NULL, result);
9404 
9405   DEBUGpic16_emitcode ("; ", " %d getting const pointer", __LINE__);
9406 
9407   // set up table pointer
9408   if ((AOP_TYPE (left) == AOP_PCODE)
9409       && ((AOP (left)->aopu.pcop->type == PO_IMMEDIATE) || (AOP (left)->aopu.pcop->type == PO_DIR)))
9410     {
9411       pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (left), 0));
9412       pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptrl));
9413       pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (left), 1));
9414       pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptrh));
9415       pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (left), 2));
9416       pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptru));
9417     }
9418   else
9419     {
9420       mov2fp (pic16_popCopyReg (&pic16_pc_tblptrl), AOP (left), 0);
9421       mov2fp (pic16_popCopyReg (&pic16_pc_tblptrh), AOP (left), 1);
9422       mov2fp (pic16_popCopyReg (&pic16_pc_tblptru), AOP (left), 2);
9423     }
9424 
9425   while (size--)
9426     {
9427       pic16_emitpcodeNULLop (POC_TBLRD_POSTINC);
9428       pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg (&pic16_pc_tablat), pic16_popGet (AOP (result), offset)));
9429       offset++;
9430     }
9431 
9432 release:
9433   pic16_freeAsmop (left, NULL, ic, TRUE);
9434   pic16_freeAsmop (result, NULL, ic, TRUE);
9435 }
9436 
9437 
9438 /*-----------------------------------------------------------------*/
9439 /* genPointerGet - generate code for pointer get                   */
9440 /*-----------------------------------------------------------------*/
9441 static void
genPointerGet(iCode * ic)9442 genPointerGet (iCode * ic)
9443 {
9444   operand *left, *result;
9445   sym_link *type, *etype;
9446   int p_type;
9447 
9448   FENTRY;
9449 
9450   left = IC_LEFT (ic);
9451   result = IC_RESULT (ic);
9452 
9453   /* depending on the type of pointer we need to
9454      move it to the correct pointer register */
9455   type = operandType (left);
9456   etype = getSpec (type);
9457 
9458 #if 0
9459   if (IS_PTR_CONST (type))
9460 #else
9461   if (IS_CODEPTR (type))
9462 #endif
9463     DEBUGpic16_emitcode ("; ***", "%d - const pointer", __LINE__);
9464 
9465   /* if left is of type of pointer then it is simple */
9466   if (IS_PTR (type) && !IS_FUNC (type->next))
9467     p_type = DCL_TYPE (type);
9468   else
9469     {
9470       /* we have to go by the storage class */
9471       p_type = PTR_TYPE (SPEC_OCLS (etype));
9472 
9473       DEBUGpic16_emitcode ("; ***", "%d - resolve pointer by storage class", __LINE__);
9474 
9475       if (SPEC_OCLS (etype)->codesp)
9476         {
9477           DEBUGpic16_emitcode ("; ***", "%d - cpointer", __LINE__);
9478           //p_type = CPOINTER ;
9479         }
9480       else if (SPEC_OCLS (etype)->fmap && !SPEC_OCLS (etype)->paged)
9481         {
9482           DEBUGpic16_emitcode ("; ***", "%d - fpointer", __LINE__);
9483           /*p_type = FPOINTER ; */
9484         }
9485       else if (SPEC_OCLS (etype)->fmap && SPEC_OCLS (etype)->paged)
9486         {
9487           DEBUGpic16_emitcode ("; ***", "%d - ppointer", __LINE__);
9488           /* p_type = PPOINTER; */
9489         }
9490       else if (SPEC_OCLS (etype) == idata)
9491         {
9492           DEBUGpic16_emitcode ("; ***", "%d - ipointer", __LINE__);
9493           /* p_type = IPOINTER; */
9494         }
9495       else
9496         {
9497           DEBUGpic16_emitcode ("; ***", "%d - pointer", __LINE__);
9498           /* p_type = POINTER ; */
9499         }
9500     }
9501 
9502   /* now that we have the pointer type we assign
9503      the pointer values */
9504   switch (p_type)
9505     {
9506     case POINTER:
9507     case FPOINTER:
9508     case IPOINTER:
9509     case PPOINTER:
9510       genNearPointerGet (left, result, ic);
9511       break;
9512 
9513     case CPOINTER:
9514       genConstPointerGet (left, result, ic);
9515       //pic16_emitcodePointerGet (left,result,ic);
9516       break;
9517 
9518     case GPOINTER:
9519 #if 0
9520       if (IS_PTR_CONST (type))
9521         genConstPointerGet (left, result, ic);
9522       else
9523 #endif
9524         genGenPointerGet (left, result, ic);
9525       break;
9526 
9527     default:
9528       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "genPointerGet: illegal pointer type");
9529 
9530     }
9531 }
9532 
9533 /*-----------------------------------------------------------------*/
9534 /* genPackBits - generates code for packed bit storage             */
9535 /*-----------------------------------------------------------------*/
9536 static void
genPackBits(sym_link * etype,operand * result,operand * right,char * rname,int p_type)9537 genPackBits (sym_link * etype, operand * result, operand * right, char *rname, int p_type)
9538 {
9539   unsigned shCnt = 0;
9540   int offset = 0;
9541   int rLen = 0;
9542   unsigned blen, bstr;
9543   int shifted_and_masked = 0;
9544   unsigned long lit = (unsigned long) - 1;
9545   sym_link *retype;
9546 
9547   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9548   blen = SPEC_BLEN (etype);
9549   bstr = SPEC_BSTR (etype);
9550 
9551   retype = getSpec (operandType (right));
9552 
9553   if (AOP_TYPE (right) == AOP_LIT)
9554     {
9555       lit = ulFromVal (AOP (right)->aopu.aop_lit);
9556 
9557       if ((blen == 1) && (bstr < 8))
9558         {
9559           /* it is a single bit, so use the appropriate bit instructions */
9560 
9561           DEBUGpic16_emitcode (";", "%s %d optimize bit assignment", __FUNCTION__, __LINE__);
9562 
9563           if (!IS_PTR (operandType (result)) || IS_DIRECT (result))
9564             {
9565               /* workaround to reduce the extra lfsr instruction */
9566               if (lit)
9567                 {
9568                   pic16_emitpcode (POC_BSF, pic16_popCopyGPR2Bit (pic16_popGet (AOP (result), 0), bstr));
9569                 }
9570               else
9571                 {
9572                   pic16_emitpcode (POC_BCF, pic16_popCopyGPR2Bit (pic16_popGet (AOP (result), 0), bstr));
9573                 }
9574             }
9575           else
9576             {
9577               if (PIC_IS_DATA_PTR (operandType (result)))
9578                 {
9579                   pic16_loadFSR0 (result, 0);
9580                   pic16_emitpcode (lit ? POC_BSF : POC_BCF, pic16_popCopyGPR2Bit (pic16_popCopyReg (&pic16_pc_indf0), bstr));
9581                 }
9582               else
9583                 {
9584                   /* get old value */
9585                   pic16_derefPtr (result, p_type, 0, NULL);
9586                   pic16_emitpcode (lit ? POC_BSF : POC_BCF, pic16_popCopyGPR2Bit (pic16_popCopyReg (&pic16_pc_wreg), bstr));
9587                   /* write back new value */
9588                   pic16_derefPtr (result, p_type, 1, NULL);
9589                 }
9590             }
9591 
9592           return;
9593         }
9594       /* IORLW below is more efficient */
9595       //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
9596       lit = (lit & ((1UL << blen) - 1)) << bstr;
9597       shifted_and_masked = 1;
9598       offset++;
9599     }
9600   else if (IS_DIRECT (result) && !IS_PTR (operandType (result))
9601            && IS_BITFIELD (retype) && (AOP_TYPE (right) == AOP_REG || AOP_TYPE (right) == AOP_DIR) && (blen == 1))
9602     {
9603       int rbstr;
9604 
9605       rbstr = SPEC_BSTR (retype);
9606 
9607       if (IS_BITFIELD (etype))
9608         {
9609           pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (result), 0));
9610           pic16_emitpcode (POC_BCF, pic16_popCopyGPR2Bit (pic16_popCopyReg (&pic16_pc_wreg), bstr));
9611         }
9612       else
9613         {
9614           pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
9615         }
9616 
9617       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit (pic16_popGet (AOP (right), 0), rbstr));
9618 
9619       if (IS_BITFIELD (etype))
9620         {
9621           pic16_emitpcode (POC_BSF, pic16_popCopyGPR2Bit (pic16_popCopyReg (&pic16_pc_wreg), bstr));
9622         }
9623       else
9624         {
9625           pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg));
9626         }
9627 
9628       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
9629 
9630       return;
9631     }
9632   else
9633     {
9634       /* move right to W */
9635       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (right), offset++));
9636     }
9637 
9638   /* if the bit length is less than or   */
9639   /* it exactly fits a byte then         */
9640   if ((shCnt = SPEC_BSTR (etype)) || SPEC_BLEN (etype) <= 8)
9641     {
9642       int fsr0_setup = 0;
9643 
9644       if (blen != 8 || (bstr % 8) != 0)
9645         {
9646           // we need to combine the value with the old value
9647           if (!shifted_and_masked)
9648             {
9649               pic16_emitpcode (POC_ANDLW, pic16_popGetLit ((1U << blen) - 1));
9650 
9651               DEBUGpic16_emitcode (";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt, SPEC_BSTR (etype), SPEC_BLEN (etype));
9652 
9653               /* shift left acc, do NOT mask the result again */
9654               AccLsh (shCnt, 0);
9655 
9656               /* using PRODH as a temporary register here */
9657               pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_prodh));
9658             }
9659 
9660           if ((IS_SYMOP (result) && !IS_PTR (operandType (result))) || IS_DIRECT (result))
9661             {
9662               /* access symbol directly */
9663               pic16_mov2w (AOP (result), 0);
9664             }
9665           else
9666             {
9667               /* get old value */
9668               pic16_derefPtr (result, p_type, 0, &fsr0_setup);
9669             }
9670 #if 1
9671           pic16_emitpcode (POC_ANDLW, pic16_popGetLit ((unsigned char) ((unsigned char) (0xff << (blen + bstr)) |
9672                            (unsigned char) (0xff >> (8 - bstr)))));
9673           if (!shifted_and_masked)
9674             {
9675               pic16_emitpcode (POC_IORFW, pic16_popCopyReg (&pic16_pc_prodh));
9676             }
9677           else
9678             {
9679               /* We have the shifted and masked (literal) right value in `lit' */
9680               if (lit != 0)
9681                 pic16_emitpcode (POC_IORLW, pic16_popGetLit (lit));
9682             }
9683         }
9684       else                      // if (blen == 8 && (bstr % 8) == 0)
9685         {
9686           if (shifted_and_masked)
9687             {
9688               // move right (literal) to WREG (only case where right is not yet in WREG)
9689               pic16_mov2w (AOP (right), (bstr / 8));
9690             }
9691         }
9692 
9693       /* write new value back */
9694       if ((IS_SYMOP (result) && !IS_PTR (operandType (result))) || IS_DIRECT (result))
9695         {
9696           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
9697         }
9698       else
9699         {
9700           pic16_derefPtr (result, p_type, 1, &fsr0_setup);
9701         }
9702 #endif
9703 
9704       return;
9705     }
9706 
9707 
9708 #if 0
9709   fprintf (stderr, "SDCC pic16 port error: the port currently does not support\n");
9710   fprintf (stderr, "bitfields of size >=8. Instead of generating wrong code, bailing out...\n");
9711   exit (EXIT_FAILURE);
9712 #endif
9713 
9714 
9715   pic16_loadFSR0 (result, 0);   // load FSR0 with address of result
9716   rLen = SPEC_BLEN (etype) - 8;
9717 
9718   /* now generate for lengths greater than one byte */
9719   while (1)
9720     {
9721       rLen -= 8;
9722       if (rLen <= 0)
9723         {
9724           mov2fp (pic16_popCopyReg (&pic16_pc_prodh), AOP (right), offset);
9725           break;
9726         }
9727 
9728       switch (p_type)
9729         {
9730         case POINTER:
9731           pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_postinc0));
9732           break;
9733 
9734           /*
9735              case FPOINTER:
9736              MOVA(l);
9737              pic16_emitcode("movx","@dptr,a");
9738              break;
9739 
9740              case GPOINTER:
9741              MOVA(l);
9742              DEBUGpic16_emitcode(";lcall","__gptrput");
9743              break;
9744            */
9745         default:
9746           assert (0);
9747         }
9748 
9749 
9750       pic16_mov2w (AOP (right), offset++);
9751     }
9752 
9753   /* last last was not complete */
9754   if (rLen)
9755     {
9756       /* save the byte & read byte */
9757       switch (p_type)
9758         {
9759         case POINTER:
9760           //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9761           pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (&pic16_pc_indf0));
9762           break;
9763 
9764           /*
9765              case FPOINTER:
9766              pic16_emitcode ("mov","b,a");
9767              pic16_emitcode("movx","a,@dptr");
9768              break;
9769 
9770              case GPOINTER:
9771              pic16_emitcode ("push","b");
9772              pic16_emitcode ("push","acc");
9773              pic16_emitcode ("lcall","__gptrget");
9774              pic16_emitcode ("pop","b");
9775              break;
9776            */
9777         default:
9778           assert (0);
9779         }
9780       DEBUGpic16_emitcode (";", "rLen = %i", rLen);
9781       pic16_emitpcode (POC_ANDLW, pic16_popGetLit ((unsigned char) - 1 << -rLen));
9782       pic16_emitpcode (POC_IORFW, pic16_popCopyReg (&pic16_pc_prodh));
9783       //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9784       //        pic16_emitcode ("orl","a,b");
9785     }
9786 
9787   //    if (p_type == GPOINTER)
9788   //        pic16_emitcode("pop","b");
9789 
9790   switch (p_type)
9791     {
9792 
9793     case POINTER:
9794       pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_indf0));
9795       //        pic16_emitcode("mov","@%s,a",rname);
9796       break;
9797       /*
9798          case FPOINTER:
9799          pic16_emitcode("movx","@dptr,a");
9800          break;
9801 
9802          case GPOINTER:
9803          DEBUGpic16_emitcode(";lcall","__gptrput");
9804          break;
9805        */
9806     default:
9807       assert (0);
9808     }
9809 
9810   //    pic16_freeAsmop(right, NULL, ic, TRUE);
9811 }
9812 
9813 /*-----------------------------------------------------------------*/
9814 /* genDataPointerSet - remat pointer to data space                 */
9815 /*-----------------------------------------------------------------*/
9816 static void
genDataPointerSet(operand * right,operand * result,iCode * ic)9817 genDataPointerSet (operand * right, operand * result, iCode * ic)
9818 {
9819   int size, offset = 0, resoffset = 0;
9820 
9821   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9822   pic16_aopOp (right, ic, FALSE);
9823 
9824   size = AOP_SIZE (right);
9825 
9826 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9827 
9828 #if 0
9829   if (AOP_TYPE (result) == AOP_PCODE)
9830     {
9831       fprintf (stderr, "genDataPointerSet   %s, %d\n",
9832                AOP (result)->aopu.pcop->name,
9833                (AOP (result)->aopu.pcop->type == PO_DIR) ?
9834                PCOR (AOP (result)->aopu.pcop)->instance : PCOI (AOP (result)->aopu.pcop)->offset);
9835     }
9836 #endif
9837 
9838   if (AOP (result)->aopu.pcop->type == PO_DIR)
9839     resoffset = PCOR (AOP (result)->aopu.pcop)->instance;
9840 
9841   while (size--)
9842     {
9843       if (AOP_TYPE (right) == AOP_LIT)
9844         {
9845           unsigned int lit = pic16aopLiteral (AOP (IC_RIGHT (ic))->aopu.aop_lit, offset);
9846           pic16_movLit2f (pic16_popGet (AOP (result), offset), lit);
9847         }
9848       else
9849         {
9850           pic16_mov2w (AOP (right), offset);
9851           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));     // patch 8
9852         }
9853       offset++;
9854       resoffset++;
9855     }
9856 
9857   pic16_freeAsmop (right, NULL, ic, TRUE);
9858 }
9859 
9860 
9861 
9862 /*-----------------------------------------------------------------*/
9863 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9864 /*-----------------------------------------------------------------*/
9865 static void
genNearPointerSet(operand * right,operand * result,iCode * ic)9866 genNearPointerSet (operand * right, operand * result, iCode * ic)
9867 {
9868   asmop *aop = NULL;
9869   sym_link *retype;
9870   sym_link *ptype = operandType (result);
9871   sym_link *resetype;
9872 
9873   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9874   retype = getSpec (operandType (right));
9875   resetype = getSpec (operandType (result));
9876 
9877   pic16_aopOp (result, ic, FALSE);
9878 
9879   /* if the result is rematerializable &
9880    * in data space & not a bit variable */
9881 
9882   /* and result is not a bit variable */
9883   if (AOP_TYPE (result) == AOP_PCODE && DCL_TYPE (ptype) == POINTER && !IS_BITFIELD (retype) && !IS_BITFIELD (resetype))
9884     {
9885 
9886       genDataPointerSet (right, result, ic);
9887       pic16_freeAsmop (result, NULL, ic, TRUE);
9888       return;
9889     }
9890 
9891   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9892   pic16_aopOp (right, ic, FALSE);
9893   DEBUGpic16_pic16_AopType (__LINE__, NULL, right, result);
9894 
9895   /* if bitfield then unpack the bits */
9896   if (IS_BITFIELD (resetype))
9897     {
9898       genPackBits (resetype, result, right, NULL, POINTER);
9899     }
9900   else
9901     {
9902       /* we have can just get the values */
9903       int size = AOP_SIZE (right);
9904       int offset = 0;
9905 
9906       pic16_loadFSR0 (result, 0);
9907 
9908       DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9909       while (size--)
9910         {
9911           if (pic16_isLitOp (right))
9912             {
9913               pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (right), offset));
9914               if (size)
9915                 {
9916                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_postinc0));
9917                 }
9918               else
9919                 {
9920                   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_indf0));
9921                 }
9922             }
9923           else                  // no literal
9924             {
9925               if (size)
9926                 {
9927                   pic16_emitpcode (POC_MOVFF,
9928                                    pic16_popGet2p (pic16_popGet (AOP (right), offset), pic16_popCopyReg (&pic16_pc_postinc0)));
9929                 }
9930               else
9931                 {
9932                   pic16_emitpcode (POC_MOVFF,
9933                                    pic16_popGet2p (pic16_popGet (AOP (right), offset), pic16_popCopyReg (&pic16_pc_indf0)));
9934                 }
9935             }
9936 
9937           offset++;
9938         }
9939     }
9940 
9941   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9942   /* now some housekeeping stuff */
9943   if (aop)
9944     {
9945       /* we had to allocate for this iCode */
9946       pic16_freeAsmop (NULL, aop, ic, TRUE);
9947     }
9948   else
9949     {
9950       /* we did not allocate which means left
9951        * already in a pointer register, then
9952        * if size > 0 && this could be used again
9953        * we have to point it back to where it
9954        * belongs */
9955       DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9956       if (AOP_SIZE (right) > 1 && !OP_SYMBOL (result)->remat && (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth))
9957         {
9958 
9959           int size = AOP_SIZE (right) - 1;
9960 
9961           while (size--)
9962             pic16_emitcode ("decf", "fsr0,f");
9963           //pic16_emitcode("dec","%s",rname);
9964         }
9965     }
9966 
9967   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9968   /* done */
9969 //release:
9970   pic16_freeAsmop (right, NULL, ic, TRUE);
9971   pic16_freeAsmop (result, NULL, ic, TRUE);
9972 }
9973 
9974 /*-----------------------------------------------------------------*/
9975 /* genGenPointerSet - set value from generic pointer space         */
9976 /*-----------------------------------------------------------------*/
9977 static void
genGenPointerSet(operand * right,operand * result,iCode * ic)9978 genGenPointerSet (operand * right, operand * result, iCode * ic)
9979 {
9980   int size;
9981   sym_link *retype = getSpec (operandType (result));
9982 
9983   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
9984 
9985   pic16_aopOp (result, ic, FALSE);
9986   pic16_aopOp (right, ic, FALSE);
9987   size = AOP_SIZE (right);
9988 
9989   DEBUGpic16_pic16_AopType (__LINE__, NULL, right, result);
9990 
9991 
9992   /* if bit then unpack */
9993   if (IS_BITFIELD (retype))
9994     {
9995 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9996       genPackBits (retype, result, right, "dptr", GPOINTER);
9997       goto release;
9998     }
9999 
10000   size = AOP_SIZE (right);
10001 
10002   DEBUGpic16_emitcode ("; ***", "%s  %d size=%d", __FUNCTION__, __LINE__, size);
10003 
10004 
10005   /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
10006 
10007   /* value of right+0 is placed on stack, which will be retrieved
10008    * by the support function thus restoring the stack. The important
10009    * thing is that there is no need to manually restore stack pointer
10010    * here */
10011   pushaop (AOP (right), 0);
10012 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
10013   if (size > 1)
10014     mov2fp (pic16_popCopyReg (&pic16_pc_prodh), AOP (right), 1);
10015   if (size > 2)
10016     mov2fp (pic16_popCopyReg (&pic16_pc_tblptrl), AOP (right), 2);
10017   if (size > 3)
10018     mov2fp (pic16_popCopyReg (&pic16_pc_tblptrh), AOP (right), 3);
10019 
10020   /* load address to write to in WREG:FSR0H:FSR0L */
10021   pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popGet (AOP (result), 0), pic16_popCopyReg (&pic16_pc_fsr0l)));
10022   pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popGet (AOP (result), 1), pic16_popCopyReg (&pic16_pc_prodl)));
10023   pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (result), 2));
10024 
10025   pic16_callGenericPointerRW (1, size);
10026 
10027 release:
10028   pic16_freeAsmop (right, NULL, ic, TRUE);
10029   pic16_freeAsmop (result, NULL, ic, TRUE);
10030 }
10031 
10032 /*-----------------------------------------------------------------*/
10033 /* genPointerSet - stores the value into a pointer location        */
10034 /*-----------------------------------------------------------------*/
10035 static void
genPointerSet(iCode * ic)10036 genPointerSet (iCode * ic)
10037 {
10038   operand *right, *result;
10039   sym_link *type, *etype;
10040   int p_type;
10041 
10042   FENTRY;
10043 
10044   right = IC_RIGHT (ic);
10045   result = IC_RESULT (ic);
10046 
10047   /* depending on the type of pointer we need to
10048      move it to the correct pointer register */
10049   type = operandType (result);
10050   etype = getSpec (type);
10051 
10052   /* if left is of type of pointer then it is simple */
10053   if (IS_PTR (type) && !IS_FUNC (type->next))
10054     {
10055       p_type = DCL_TYPE (type);
10056     }
10057   else
10058     {
10059       /* we have to go by the storage class */
10060       p_type = PTR_TYPE (SPEC_OCLS (etype));
10061 
10062       /*      if (SPEC_OCLS(etype)->codesp ) { */
10063       /*          p_type = CPOINTER ;  */
10064       /*      } */
10065       /*      else */
10066       /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10067       /*              p_type = FPOINTER ; */
10068       /*          else */
10069       /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10070       /*                  p_type = PPOINTER ; */
10071       /*              else */
10072       /*                  if (SPEC_OCLS(etype) == idata ) */
10073       /*                      p_type = IPOINTER ; */
10074       /*                  else */
10075       /*                      p_type = POINTER ; */
10076     }
10077 
10078   /* now that we have the pointer type we assign
10079      the pointer values */
10080   switch (p_type)
10081     {
10082     case POINTER:
10083     case FPOINTER:
10084     case IPOINTER:
10085     case PPOINTER:
10086       genNearPointerSet (right, result, ic);
10087       break;
10088 
10089     case GPOINTER:
10090       genGenPointerSet (right, result, ic);
10091       break;
10092 
10093     default:
10094       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "genPointerSet: illegal pointer type");
10095     }
10096 }
10097 
10098 /*-----------------------------------------------------------------*/
10099 /* genIfx - generate code for Ifx statement                        */
10100 /*-----------------------------------------------------------------*/
10101 static void
genIfx(iCode * ic,iCode * popIc)10102 genIfx (iCode * ic, iCode * popIc)
10103 {
10104   operand *cond = IC_COND (ic);
10105   int isbit = 0;
10106 
10107   FENTRY;
10108 
10109   pic16_aopOp (cond, ic, FALSE);
10110 
10111   /* get the value into acc */
10112   if (AOP_TYPE (cond) != AOP_CRY)
10113     pic16_toBoolean (cond);
10114   else
10115     isbit = 1;
10116   /* the result is now in the accumulator */
10117   pic16_freeAsmop (cond, NULL, ic, TRUE);
10118 
10119   /* if there was something to be popped then do it */
10120   if (popIc)
10121     genIpop (popIc);
10122 
10123   /* if the condition is  a bit variable */
10124   if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10125     {
10126       genIfxJump (ic, "c");
10127       DEBUGpic16_emitcode ("; isbit  SPIL_LOC", "%s", SPIL_LOC (cond)->rname);
10128     }
10129   else
10130     {
10131       if (isbit && !IS_ITEMP (cond))
10132         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10133       else
10134         genIfxJump (ic, "a");
10135     }
10136   ic->generated = 1;
10137 }
10138 
10139 /*-----------------------------------------------------------------*/
10140 /* genAddrOf - generates code for address of                       */
10141 /*-----------------------------------------------------------------*/
10142 static void
genAddrOf(iCode * ic)10143 genAddrOf (iCode * ic)
10144 {
10145   operand *result, *left;
10146   int size;
10147   symbol *sym;                  // = OP_SYMBOL(IC_LEFT(ic));
10148   pCodeOp *pcop0, *pcop1, *pcop2;
10149 
10150   FENTRY;
10151 
10152   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
10153 
10154   sym = OP_SYMBOL (IC_LEFT (ic));
10155 
10156   if (sym->onStack)
10157     {
10158       /* get address of symbol on stack */
10159       DEBUGpic16_emitcode (";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
10160 #if 0
10161       fprintf (stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
10162                OP_SYMBOL (IC_LEFT (ic))->name, OP_SYMBOL (IC_LEFT (ic))->stack);
10163 #endif
10164 
10165       // operands on stack are accessible via "FSR2 + index" with index
10166       // starting at 2 for arguments and growing from 0 downwards for
10167       // local variables (index == 0 is not assigned so we add one here)
10168       {
10169         int soffs = OP_SYMBOL (IC_LEFT (ic))->stack;
10170 
10171         if (soffs <= 0)
10172           {
10173             assert (soffs < 0);
10174             soffs++;
10175           }                     // if
10176 
10177         DEBUGpic16_emitcode ("*!*", "accessing stack symbol at offset=%d", soffs);
10178         pic16_emitpcode (POC_MOVLW, pic16_popGetLit (soffs & 0x00FF));
10179         pic16_emitpcode (POC_ADDFW, pic16_popCopyReg (pic16_framepnt_lo));
10180         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
10181         pic16_emitpcode (POC_MOVLW, pic16_popGetLit ((soffs >> 8) & 0x00FF));
10182         pic16_emitpcode (POC_ADDFWC, pic16_popCopyReg (pic16_framepnt_hi));
10183         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 1));
10184       }
10185 
10186       goto release;
10187     }
10188 
10189 //      if(pic16_debug_verbose) {
10190 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10191 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10192 //      }
10193 
10194   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
10195   size = AOP_SIZE (IC_RESULT (ic));
10196 
10197   pcop0 = PCOP (pic16_newpCodeOpImmd (sym->rname, 0, 0, IN_CODESPACE (SPEC_OCLS (sym->etype))));
10198   pcop1 = PCOP (pic16_newpCodeOpImmd (sym->rname, 1, 0, IN_CODESPACE (SPEC_OCLS (sym->etype))));
10199   pcop2 = PCOP (pic16_newpCodeOpImmd (sym->rname, 2, 0, IN_CODESPACE (SPEC_OCLS (sym->etype))));
10200 
10201   if (size == 3)
10202     {
10203       pic16_emitpcode (POC_MOVLW, pcop0);
10204       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
10205       pic16_emitpcode (POC_MOVLW, pcop1);
10206       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 1));
10207       pic16_emitpcode (POC_MOVLW, pcop2);
10208       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 2));
10209     }
10210   else if (size == 2)
10211     {
10212       pic16_emitpcode (POC_MOVLW, pcop0);
10213       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
10214       pic16_emitpcode (POC_MOVLW, pcop1);
10215       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 1));
10216     }
10217   else
10218     {
10219       pic16_emitpcode (POC_MOVLW, pcop0);
10220       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
10221     }
10222 
10223   pic16_freeAsmop (left, NULL, ic, FALSE);
10224 release:
10225   pic16_freeAsmop (result, NULL, ic, TRUE);
10226 }
10227 
10228 
10229 /*-----------------------------------------------------------------*/
10230 /* genAssign - generate code for assignment                        */
10231 /*-----------------------------------------------------------------*/
10232 static void
genAssign(iCode * ic)10233 genAssign (iCode * ic)
10234 {
10235   operand *result, *right;
10236   sym_link *restype, *rtype;
10237   int size, offset, know_W;
10238   unsigned long lit = 0L;
10239 
10240   result = IC_RESULT (ic);
10241   right = IC_RIGHT (ic);
10242 
10243   FENTRY;
10244 
10245   /* if they are the same */
10246   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10247     return;
10248 
10249   /* reversed order operands are aopOp'ed so that result operand
10250    * is effective in case right is a stack symbol. This maneauver
10251    * allows to use the _G.resDirect flag later */
10252   pic16_aopOp (result, ic, TRUE);
10253   pic16_aopOp (right, ic, FALSE);
10254 
10255   DEBUGpic16_pic16_AopType (__LINE__, NULL, right, result);
10256 
10257   /* if they are the same registers */
10258   if (pic16_sameRegs (AOP (right), AOP (result)))
10259     goto release;
10260 
10261   /* if the result is a bit */
10262   if (AOP_TYPE (result) == AOP_CRY)
10263     {
10264       /* if the right size is a literal then
10265          we know what the value is */
10266       if (AOP_TYPE (right) == AOP_LIT)
10267         {
10268 
10269           pic16_emitpcode ((((int) operandLitValue (right)) ? POC_BSF : POC_BCF), pic16_popGet (AOP (result), 0));
10270 
10271           if (((int) operandLitValue (right)))
10272             pic16_emitcode ("bsf", "(%s >> 3),(%s & 7)", AOP (result)->aopu.aop_dir, AOP (result)->aopu.aop_dir);
10273           else
10274             pic16_emitcode ("bcf", "(%s >> 3),(%s & 7)", AOP (result)->aopu.aop_dir, AOP (result)->aopu.aop_dir);
10275 
10276           goto release;
10277         }
10278 
10279       /* the right is also a bit variable */
10280       if (AOP_TYPE (right) == AOP_CRY)
10281         {
10282           pic16_emitpcode (POC_BCF, pic16_popGet (AOP (result), 0));
10283           pic16_emitpcode (POC_BTFSC, pic16_popGet (AOP (right), 0));
10284           pic16_emitpcode (POC_BSF, pic16_popGet (AOP (result), 0));
10285 
10286           goto release;
10287         }
10288 
10289       /* we need to or */
10290       pic16_emitpcode (POC_BCF, pic16_popGet (AOP (result), 0));
10291       pic16_toBoolean (right);
10292       emitSKPZ;
10293       pic16_emitpcode (POC_BSF, pic16_popGet (AOP (result), 0));
10294       //pic16_aopPut(AOP(result),"a",0);
10295       goto release;
10296     }
10297 
10298   /* bit variables done */
10299   /* general case */
10300   size = AOP_SIZE (result);
10301   offset = 0;
10302 
10303   /* bit variables done */
10304   /* general case */
10305   size = AOP_SIZE (result);
10306   restype = operandType (result);
10307   rtype = operandType (right);
10308   offset = 0;
10309 
10310   if (AOP_TYPE (right) == AOP_LIT)
10311     {
10312       if (!(IS_FLOAT (operandType (right)) || IS_FIXED (operandType (right))))
10313         {
10314           lit = ulFromVal (AOP (right)->aopu.aop_lit);
10315 
10316           /* patch tag for literals that are cast to pointers */
10317           if (IS_CODEPTR (restype))
10318             {
10319               //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
10320               lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
10321             }
10322           else
10323             {
10324               if (IS_GENPTR (restype))
10325                 {
10326                   if (IS_CODEPTR (rtype))
10327                     {
10328                       //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
10329                       lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
10330                     }
10331                   else if (PIC_IS_DATA_PTR (rtype))
10332                     {
10333                       //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
10334                       lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
10335                     }
10336                   else if (!IS_PTR (rtype) || IS_GENPTR (rtype))
10337                     {
10338                       //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
10339                     }
10340                   else if (IS_PTR (rtype))
10341                     {
10342                       fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename,
10343                                ic->lineno);
10344                       lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
10345                     }
10346                 }
10347             }
10348         }
10349       else
10350         {
10351           union
10352           {
10353             unsigned long lit_int;
10354             float lit_float;
10355           } info;
10356 
10357 
10358           if (IS_FIXED16X16 (operandType (right)))
10359             {
10360               lit = (unsigned long) fixed16x16FromDouble (floatFromVal (AOP (right)->aopu.aop_lit));
10361             }
10362           else
10363             {
10364               /* take care if literal is a float */
10365               info.lit_float = (float)floatFromVal (AOP (right)->aopu.aop_lit);
10366               lit = info.lit_int;
10367             }
10368         }
10369     }
10370 
10371 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10372 //                      sizeof(unsigned long int), sizeof(float));
10373 
10374 
10375   if (AOP_TYPE (right) == AOP_REG)
10376     {
10377       DEBUGpic16_emitcode (";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
10378       while (size--)
10379         {
10380           pic16_emitpcode (POC_MOVFF, pic16_popGet2 (AOP (right), AOP (result), offset++));
10381         }                       // while
10382       goto release;
10383     }
10384 
10385   /* when do we have to read the program memory?
10386    * - if right itself is a symbol in code space
10387    *   (we don't care what it points to if it's a pointer)
10388    * - AND right is not a function (we would want its address)
10389    */
10390   if (AOP_TYPE (right) != AOP_LIT
10391       && IN_CODESPACE (SPEC_OCLS (OP_SYM_ETYPE (right))) && !IS_FUNC (OP_SYM_TYPE (right)) && !IS_ITEMP (right))
10392     {
10393 
10394       DEBUGpic16_emitcode (";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10395       //fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
10396 
10397       // set up table pointer
10398       if (pic16_isLitOp (right))
10399         {
10400 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
10401           pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (right), 0));
10402           pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptrl));
10403           pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (right), 1));
10404           pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptrh));
10405           pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (right), 2));
10406           pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptru));
10407         }
10408       else
10409         {
10410 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
10411           pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popGet (AOP (right), 0), pic16_popCopyReg (&pic16_pc_tblptrl)));
10412           pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popGet (AOP (right), 1), pic16_popCopyReg (&pic16_pc_tblptrh)));
10413           pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popGet (AOP (right), 2), pic16_popCopyReg (&pic16_pc_tblptru)));
10414         }
10415 
10416       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
10417       size = min ((int)getSize (OP_SYM_TYPE (right)), AOP_SIZE (result));
10418       while (size--)
10419         {
10420           pic16_emitpcodeNULLop (POC_TBLRD_POSTINC);
10421           pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg (&pic16_pc_tablat),
10422                            pic16_popGet (AOP (result), offset)));
10423           offset++;
10424         }
10425 
10426       /* FIXME: for pointers we need to extend differently (according
10427        * to pointer type DATA/CODE/EEPROM/... :*/
10428       size = getSize (OP_SYM_TYPE (right));
10429       if (AOP_SIZE (result) > size)
10430         {
10431           size = AOP_SIZE (result) - size;
10432           while (size--)
10433             {
10434               pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offset));
10435               offset++;
10436             }
10437         }
10438       goto release;
10439     }
10440 
10441 #if 0
10442   /* VR - What is this?! */
10443   if (AOP_TYPE (right) == AOP_DIR && (AOP_TYPE (result) == AOP_REG) && size == 1)
10444     {
10445       DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
10446 
10447       if (aopIdx (AOP (result), 0) == 4)
10448         {
10449           /* this is a workaround to save value of right into wreg too,
10450            * value of wreg is going to be used later */
10451           DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
10452           pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (right), offset));
10453           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
10454           goto release;
10455         }
10456       else
10457 //      assert(0);
10458         DEBUGpic16_emitcode ("; WARNING", "%s  %d ignoring register storage", __FUNCTION__, __LINE__);
10459     }
10460 #endif
10461 
10462   size = AOP_SIZE (right);
10463   if (size > AOP_SIZE (result))
10464     size = AOP_SIZE (result);
10465   know_W = -1;
10466   while (size--)
10467     {
10468       DEBUGpic16_emitcode ("; ***", "%s  %d size %d", __FUNCTION__, __LINE__, size);
10469       if (AOP_TYPE (right) == AOP_LIT)
10470         {
10471           if (lit & 0xff)
10472             {
10473               if (know_W != (lit & 0xff))
10474                 pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0xff));
10475               know_W = lit & 0xff;
10476 
10477               if (AOP_TYPE (result) != AOP_ACC)
10478                 {
10479                   pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
10480                 }
10481             }
10482           else
10483             pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offset));
10484 
10485           lit >>= 8;
10486 
10487         }
10488       else if (AOP_TYPE (right) == AOP_CRY)
10489         {
10490           pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offset));
10491           if (offset == 0)
10492             {
10493               //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
10494               pic16_emitpcode (POC_BTFSC, pic16_popGet (AOP (right), 0));
10495               pic16_emitpcode (POC_INCF, pic16_popGet (AOP (result), 0));
10496             }
10497         }
10498       else if ((AOP_TYPE (right) == AOP_PCODE) && (AOP (right)->aopu.pcop->type == PO_IMMEDIATE))
10499         {
10500           pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (right), offset));
10501           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
10502         }
10503       else
10504         {
10505           DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
10506 
10507           if (!_G.resDirect)    /* use this aopForSym feature */
10508             {
10509               if (AOP_TYPE (result) == AOP_ACC)
10510                 {
10511                   pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (right), offset));
10512                 }
10513               else if (AOP_TYPE (right) == AOP_ACC)
10514                 {
10515                   pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
10516                 }
10517               else
10518                 {
10519                   pic16_emitpcode (POC_MOVFF, pic16_popGet2 (AOP (right), AOP (result), offset));
10520                 }
10521             }
10522         }
10523 
10524       offset++;
10525     }
10526   pic16_addSign (result, AOP_SIZE (right), !IS_UNSIGNED (operandType (right)));
10527 
10528 release:
10529   pic16_freeAsmop (result, NULL, ic, TRUE);
10530   pic16_freeAsmop (right, NULL, ic, FALSE);
10531 }
10532 
10533 /*-----------------------------------------------------------------*/
10534 /* genJumpTab - generates code for jump table                       */
10535 /*-----------------------------------------------------------------*/
10536 static void
genJumpTab(iCode * ic)10537 genJumpTab (iCode * ic)
10538 {
10539   symbol *jtab;
10540   char *l;
10541   pCodeOp *jt_label;
10542 
10543   FENTRY;
10544 
10545   pic16_aopOp (IC_JTCOND (ic), ic, FALSE);
10546   /* get the condition into accumulator */
10547   l = pic16_aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
10548   MOVA (l);
10549   /* multiply by three */
10550   pic16_emitcode ("add", "a,acc");
10551   pic16_emitcode ("add", "a,%s", pic16_aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
10552 
10553   jtab = newiTempLabel (NULL);
10554   pic16_emitcode ("mov", "dptr,#%05d_DS_", labelKey2num (jtab->key));
10555   pic16_emitcode ("jmp", "@a+dptr");
10556   pic16_emitcode ("", "%05d_DS_:", labelKey2num (jtab->key));
10557 
10558 #if 0
10559   pic16_emitpcode (POC_MOVLW, pic16_popGetLabel (jtab->key));
10560   pic16_emitpcode (POC_ADDFW, pic16_popGet (AOP (IC_JTCOND (ic)), 0));
10561   emitSKPNC;
10562   pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_pclath));
10563   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_pcl));
10564   pic16_emitpLabel (jtab->key);
10565 
10566 #else
10567 
10568   jt_label = pic16_popGetLabel (jtab->key);
10569   //fprintf (stderr, "Creating jump table...\n");
10570 
10571   // calculate offset into jump table (idx * sizeof(GOTO))
10572   // This solution does not use temporary registers and the code is shorter.
10573   pic16_emitpcode (POC_CLRF  , pic16_popCopyReg (&pic16_pc_pclath));
10574   pic16_emitpcode (POC_CLRF  , pic16_popCopyReg (&pic16_pc_pclatu));
10575   pic16_emitpcode (POC_RLCFW , pic16_popGet (AOP (IC_JTCOND (ic)), 0));
10576   pic16_emitpcode (POC_RLCF  , pic16_popCopyReg (&pic16_pc_pclath));
10577   pic16_emitpcode (POC_RLCFW , pic16_popCopyReg (&pic16_pc_wreg));
10578   pic16_emitpcode (POC_RLCF  , pic16_popCopyReg (&pic16_pc_pclath));
10579   pic16_emitpcode (POC_ANDLW , pic16_popGetLit (0xFC));
10580   pic16_emitpcode (POC_ADDLW , pic16_popGetImmd (jt_label->name, 0, 0));
10581   pic16_emitpcode (POC_MOVWF , pic16_popCopyReg (pic16_stack_postdec));
10582   pic16_emitpcode (POC_MOVLW , pic16_popGetImmd (jt_label->name, 1, 0));
10583   pic16_emitpcode (POC_ADDWFC, pic16_popCopyReg (&pic16_pc_pclath));
10584   pic16_emitpcode (POC_MOVLW , pic16_popGetImmd (jt_label->name, 2, 0));
10585   pic16_emitpcode (POC_ADDWFC, pic16_popCopyReg (&pic16_pc_pclatu));
10586 
10587   // jump into the table
10588   pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (pic16_stack_preinc));
10589   pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (&pic16_pc_pcl));
10590 
10591   pic16_emitpLabelFORCE (jtab->key);
10592 #endif
10593 
10594   pic16_freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10595 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
10596 
10597   pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
10598   /* now generate the jump labels */
10599   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab; jtab = setNextItem (IC_JTLABELS (ic)))
10600     {
10601 //        pic16_emitcode("ljmp","%05d_DS_",labelKey2num (jtab->key));
10602       pic16_emitpcode (POC_GOTO, pic16_popGetLabel (jtab->key));
10603 
10604     }
10605   pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
10606 
10607 }
10608 
10609 /*-----------------------------------------------------------------*/
10610 /* genMixedOperation - gen code for operators between mixed types  */
10611 /*-----------------------------------------------------------------*/
10612 /*
10613   TSD - Written for the PIC port - but this unfortunately is buggy.
10614   This routine is good in that it is able to efficiently promote
10615   types to different (larger) sizes. Unfortunately, the temporary
10616   variables that are optimized out by this routine are sometimes
10617   used in other places. So until I know how to really parse the
10618   iCode tree, I'm going to not be using this routine :(.
10619 */
10620 static int
genMixedOperation(iCode * ic)10621 genMixedOperation (iCode * ic)
10622 {
10623 #if 0
10624   operand *result = IC_RESULT (ic);
10625   sym_link *ctype = operandType (IC_LEFT (ic));
10626   operand *right = IC_RIGHT (ic);
10627   int ret = 0;
10628   int big, small;
10629   int offset;
10630 
10631   iCode *nextic;
10632   operand *nextright = NULL, *nextleft = NULL, *nextresult = NULL;
10633 
10634   pic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
10635 
10636   nextic = ic->next;
10637   if (!nextic)
10638     return 0;
10639 
10640   nextright = IC_RIGHT (nextic);
10641   nextleft = IC_LEFT (nextic);
10642   nextresult = IC_RESULT (nextic);
10643 
10644   pic16_aopOp (right, ic, FALSE);
10645   pic16_aopOp (result, ic, FALSE);
10646   pic16_aopOp (nextright, nextic, FALSE);
10647   pic16_aopOp (nextleft, nextic, FALSE);
10648   pic16_aopOp (nextresult, nextic, FALSE);
10649 
10650   if (pic16_sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (nextic))))
10651     {
10652 
10653       operand *t = right;
10654       right = nextright;
10655       nextright = t;
10656 
10657       pic16_emitcode (";remove right +", "");
10658 
10659     }
10660   else if (pic16_sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (nextic))))
10661     {
10662       /*
10663          operand *t = right;
10664          right = nextleft;
10665          nextleft = t;
10666        */
10667       pic16_emitcode (";remove left +", "");
10668     }
10669   else
10670     return 0;
10671 
10672   big = AOP_SIZE (nextleft);
10673   small = AOP_SIZE (nextright);
10674 
10675   switch (nextic->op)
10676     {
10677 
10678     case '+':
10679       pic16_emitcode (";optimize a +", "");
10680       /* if unsigned or not an integral type */
10681       if (AOP_TYPE (IC_LEFT (nextic)) == AOP_CRY)
10682         {
10683           pic16_emitcode (";add a bit to something", "");
10684         }
10685       else
10686         {
10687 
10688           pic16_emitcode ("movf", "%s,w", AOP (nextright)->aopu.aop_dir);
10689 
10690           if (!pic16_sameRegs (AOP (IC_LEFT (nextic)), AOP (IC_RESULT (nextic))))
10691             {
10692               pic16_emitcode ("addwf", "%s,w", AOP (nextleft)->aopu.aop_dir);
10693               pic16_emitcode ("movwf", "%s", pic16_aopGet (AOP (IC_RESULT (nextic)), 0, FALSE, FALSE));
10694             }
10695           else
10696             pic16_emitcode ("addwf", "%s,f", AOP (nextleft)->aopu.aop_dir);
10697 
10698           offset = 0;
10699           while (--big)
10700             {
10701 
10702               offset++;
10703 
10704               if (--small)
10705                 {
10706                   if (!pic16_sameRegs (AOP (IC_LEFT (nextic)), AOP (IC_RESULT (nextic))))
10707                     {
10708                       pic16_emitcode ("movf", "%s,w", pic16_aopGet (AOP (IC_LEFT (nextic)), offset, FALSE, FALSE));
10709                       pic16_emitcode ("movwf", "%s,f", pic16_aopGet (AOP (IC_RESULT (nextic)), offset, FALSE, FALSE));
10710                     }
10711 
10712                   pic16_emitcode ("movf", "%s,w", pic16_aopGet (AOP (IC_LEFT (nextic)), offset, FALSE, FALSE));
10713                   emitSKPNC;
10714                   pic16_emitcode ("btfsc", "(%s >> 3), (%s & 7)",
10715                                   AOP (IC_RIGHT (nextic))->aopu.aop_dir, AOP (IC_RIGHT (nextic))->aopu.aop_dir);
10716                   pic16_emitcode (" incf", "%s,w", pic16_aopGet (AOP (IC_LEFT (nextic)), offset, FALSE, FALSE));
10717                   pic16_emitcode ("movwf", "%s", pic16_aopGet (AOP (IC_RESULT (nextic)), offset, FALSE, FALSE));
10718 
10719                 }
10720               else
10721                 {
10722                   pic16_emitcode ("rlf", "known_zero,w");
10723 
10724                   /*
10725                      if right is signed
10726                      btfsc  right,7
10727                      addlw ff
10728                    */
10729                   if (!pic16_sameRegs (AOP (IC_LEFT (nextic)), AOP (IC_RESULT (nextic))))
10730                     {
10731                       pic16_emitcode ("addwf", "%s,w", pic16_aopGet (AOP (IC_LEFT (nextic)), offset, FALSE, FALSE));
10732                       pic16_emitcode ("movwf", "%s,f", pic16_aopGet (AOP (IC_RESULT (nextic)), offset, FALSE, FALSE));
10733                     }
10734                   else
10735                     {
10736                       pic16_emitcode ("addwf", "%s,f", pic16_aopGet (AOP (IC_RESULT (nextic)), offset, FALSE, FALSE));
10737                     }
10738                 }
10739             }
10740           ret = 1;
10741         }
10742     }
10743   ret = 1;
10744 
10745 release:
10746   pic16_freeAsmop (right, NULL, ic, TRUE);
10747   pic16_freeAsmop (result, NULL, ic, TRUE);
10748   pic16_freeAsmop (nextright, NULL, ic, TRUE);
10749   pic16_freeAsmop (nextleft, NULL, ic, TRUE);
10750   if (ret)
10751     nextic->generated = 1;
10752 
10753   return ret;
10754 #else
10755   return 0;
10756 #endif
10757 }
10758 
10759 /*-----------------------------------------------------------------*/
10760 /* genCast - gen code for casting                                  */
10761 /*-----------------------------------------------------------------*/
10762 static void
genCast(iCode * ic)10763 genCast (iCode * ic)
10764 {
10765   operand *result = IC_RESULT (ic);
10766   sym_link *ctype = operandType (IC_LEFT (ic));
10767   sym_link *rtype = operandType (IC_RIGHT (ic));
10768   sym_link *restype = operandType (IC_RESULT (ic));
10769   operand *right = IC_RIGHT (ic);
10770   int size, offset;
10771 
10772 
10773   FENTRY;
10774 
10775   /* if they are equivalent then do nothing */
10776 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10777 //              return ;
10778 
10779   pic16_aopOp (result, ic, FALSE);
10780   pic16_aopOp (right, ic, FALSE);
10781 
10782   DEBUGpic16_pic16_AopType (__LINE__, NULL, right, result);
10783 
10784 
10785   /* if the result is a bit */
10786   if (AOP_TYPE (result) == AOP_CRY)
10787     {
10788 
10789       /* if the right size is a literal then
10790        * we know what the value is */
10791       DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
10792 
10793       if (AOP_TYPE (right) == AOP_LIT)
10794         {
10795           pic16_emitpcode ((((int) operandLitValue (right)) ? POC_BSF : POC_BCF), pic16_popGet (AOP (result), 0));
10796 
10797           if (((int) operandLitValue (right)))
10798             pic16_emitcode ("bsf", "(%s >> 3), (%s & 7)", AOP (result)->aopu.aop_dir, AOP (result)->aopu.aop_dir);
10799           else
10800             pic16_emitcode ("bcf", "(%s >> 3), (%s & 7)", AOP (result)->aopu.aop_dir, AOP (result)->aopu.aop_dir);
10801           goto release;
10802         }
10803 
10804       /* the right is also a bit variable */
10805       if (AOP_TYPE (right) == AOP_CRY)
10806         {
10807           emitCLRC;
10808           pic16_emitpcode (POC_BTFSC, pic16_popGet (AOP (right), 0));
10809 
10810           pic16_emitcode ("clrc", "");
10811           pic16_emitcode ("btfsc", "(%s >> 3), (%s & 7)", AOP (right)->aopu.aop_dir, AOP (right)->aopu.aop_dir);
10812           pic16_aopPut (AOP (result), "c", 0);
10813           goto release;
10814         }
10815 
10816       /* we need to or */
10817       if (AOP_TYPE (right) == AOP_REG)
10818         {
10819           pic16_emitpcode (POC_BCF, pic16_popGet (AOP (result), 0));
10820           pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit (pic16_aopGet (AOP (right), 0, FALSE, FALSE), 0, 0, PO_GPR_REGISTER));
10821           pic16_emitpcode (POC_BSF, pic16_popGet (AOP (result), 0));
10822         }
10823       pic16_toBoolean (right);
10824       pic16_aopPut (AOP (result), "a", 0);
10825       goto release;
10826     }
10827 
10828   if ((AOP_TYPE (right) == AOP_CRY) && (AOP_TYPE (result) == AOP_REG))
10829     {
10830       int offset = 1;
10831 
10832       size = AOP_SIZE (result);
10833 
10834       DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
10835 
10836       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), 0));
10837       pic16_emitpcode (POC_BTFSC, pic16_popGet (AOP (right), 0));
10838       pic16_emitpcode (POC_INCF, pic16_popGet (AOP (result), 0));
10839 
10840       while (size--)
10841         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offset++));
10842 
10843       goto release;
10844     }
10845 
10846   if (IS_BOOL (operandType (result)))
10847     {
10848       pic16_toBoolean (right);
10849       emitSKPNZ;
10850       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (1));
10851       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
10852       goto release;
10853     }
10854 
10855   if (IS_BITFIELD (getSpec (restype)) && IS_BITFIELD (getSpec (rtype)))
10856     {
10857       DEBUGpic16_emitcode ("***", "%d casting a bit to another bit", __LINE__);
10858     }
10859 
10860   /* port from pic14 to cope with generic pointers */
10861   if (PIC_IS_TAGGED (restype))
10862     {
10863       operand *result = IC_RESULT (ic);
10864       //operand *left = IC_LEFT(ic);
10865       operand *right = IC_RIGHT (ic);
10866       int tag = 0xff;
10867 
10868       /* copy common part */
10869       int max, size = AOP_SIZE (result);
10870       if (size > AOP_SIZE (right))
10871         size = AOP_SIZE (right);
10872       DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
10873 
10874       max = size;
10875       while (size--)
10876         {
10877           pic16_mov2w (AOP (right), size);
10878           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), size));
10879         }                       // while
10880 
10881       /* upcast into generic pointer type? */
10882       if (IS_GENPTR (restype) && !PIC_IS_TAGGED (rtype) && (AOP_SIZE (result) > max))
10883         {
10884           /* determine appropriate tag for right */
10885           if (PIC_IS_DATA_PTR (rtype))
10886             tag = GPTR_TAG_DATA;
10887           else if (IS_CODEPTR (rtype))
10888             tag = GPTR_TAG_CODE;
10889           else if (PIC_IS_DATA_PTR (ctype))
10890             {
10891               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
10892               tag = GPTR_TAG_DATA;
10893             }
10894           else if (IS_CODEPTR (ctype))
10895             {
10896               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
10897               tag = GPTR_TAG_CODE;
10898             }
10899           else if (IS_PTR (rtype))
10900             {
10901               PERFORM_ONCE (weirdcast,
10902                             fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n",
10903                                      ic->filename, ic->lineno););
10904               tag = GPTR_TAG_DATA;
10905             }
10906           else
10907             {
10908               PERFORM_ONCE (weirdcast,
10909                             fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n",
10910                                      ic->filename, ic->lineno););
10911               tag = GPTR_TAG_DATA;
10912             }
10913 
10914           assert (AOP_SIZE (result) == 3);
10915           /* zero-extend address... */
10916           for (size = max; size < AOP_SIZE (result) - 1; size++)
10917             pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), size));
10918           /* ...and add tag */
10919           pic16_movLit2f (pic16_popGet (AOP (result), AOP_SIZE (result) - 1), tag);
10920         }
10921       else if (IS_CODEPTR (restype) && AOP_SIZE (result) > max)
10922         {
10923           //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
10924           for (size = max; size < AOP_SIZE (result) - 1; size++)
10925             pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), size));
10926           /* add __code tag */
10927           pic16_movLit2f (pic16_popGet (AOP (result), AOP_SIZE (result) - 1), GPTR_TAG_CODE);
10928         }
10929       else if (AOP_SIZE (result) > max)
10930         {
10931           /* extend non-pointers */
10932           //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
10933           pic16_addSign (result, max, 0);
10934         }                       // if
10935       goto release;
10936     }
10937 
10938   /* if they are the same size : or less */
10939   if (AOP_SIZE (result) <= AOP_SIZE (right))
10940     {
10941 
10942       /* if they are in the same place */
10943       if (pic16_sameRegs (AOP (right), AOP (result)))
10944         goto release;
10945 
10946       DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
10947 #if 0
10948       if (IS_PTR_CONST (rtype))
10949 #else
10950       if (IS_CODEPTR (rtype))
10951 #endif
10952         DEBUGpic16_emitcode ("; ***", "%d - right is const pointer", __LINE__);
10953 
10954 #if 0
10955       if (IS_PTR_CONST (operandType (IC_RESULT (ic))))
10956 #else
10957       if (IS_CODEPTR (operandType (IC_RESULT (ic))))
10958 #endif
10959         DEBUGpic16_emitcode ("; ***", "%d - result is const pointer", __LINE__);
10960 
10961       if ((AOP_TYPE (right) == AOP_PCODE) && AOP (right)->aopu.pcop->type == PO_IMMEDIATE)
10962         {
10963           pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (right), 0));
10964           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 0));
10965 
10966           if (AOP_SIZE (result) < 2)
10967             {
10968               fprintf (stderr, "%d -- casting a ptr to a char\n", __LINE__);
10969             }
10970           else
10971             {
10972               pic16_emitpcode (POC_MOVLW, pic16_popGet (AOP (right), 1));
10973               pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 1));
10974             }
10975         }
10976       else
10977         {
10978           /* if they in different places then copy */
10979           size = AOP_SIZE (result);
10980           offset = 0;
10981           while (size--)
10982             {
10983               pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (right), offset));
10984               pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset));
10985               offset++;
10986             }
10987         }
10988       goto release;
10989     }
10990 
10991   /* if the result is of type pointer */
10992   if (IS_PTR (ctype))
10993     {
10994       int p_type;
10995       sym_link *type = operandType (right);
10996       sym_link *etype = getSpec (type);
10997 
10998       DEBUGpic16_emitcode ("; ***", "%s  %d - pointer cast", __FUNCTION__, __LINE__);
10999 
11000       /* pointer to generic pointer */
11001       if (IS_GENPTR (ctype))
11002         {
11003 
11004           if (IS_PTR (type))
11005             p_type = DCL_TYPE (type);
11006           else
11007             {
11008               /* we have to go by the storage class */
11009               p_type = PTR_TYPE (SPEC_OCLS (etype));
11010 
11011               /*              if (SPEC_OCLS(etype)->codesp )  */
11012               /*                  p_type = CPOINTER ;  */
11013               /*              else */
11014               /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11015               /*                      p_type = FPOINTER ; */
11016               /*                  else */
11017               /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11018               /*                          p_type = PPOINTER; */
11019               /*                      else */
11020               /*                          if (SPEC_OCLS(etype) == idata ) */
11021               /*                              p_type = IPOINTER ; */
11022               /*                          else */
11023               /*                              p_type = POINTER ; */
11024             }
11025 
11026           /* the first two bytes are known */
11027           DEBUGpic16_emitcode ("; ***", "%s  %d - pointer cast2", __FUNCTION__, __LINE__);
11028           size = GPTRSIZE - 1;
11029           offset = 0;
11030           while (size--)
11031             {
11032               if (offset < AOP_SIZE (right))
11033                 {
11034                   DEBUGpic16_emitcode ("; ***", "%s  %d - pointer cast3 ptype = 0x%x", __FUNCTION__, __LINE__, p_type);
11035                   pic16_mov2f (AOP (result), AOP (right), offset);
11036                   /*
11037                      if ((AOP_TYPE(right) == AOP_PCODE) &&
11038                      AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11039                      pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11040                      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11041                      } else {
11042 
11043                      pic16_aopPut(AOP(result),
11044                      pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11045                      offset);
11046                      }
11047                    */
11048                 }
11049               else
11050                 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offset));
11051               offset++;
11052             }
11053           /* the last byte depending on type */
11054           switch (p_type)
11055             {
11056             case POINTER:
11057             case FPOINTER:
11058             case IPOINTER:
11059             case PPOINTER:
11060               pic16_movLit2f (pic16_popGet (AOP (result), GPTRSIZE - 1), GPTR_TAG_DATA);
11061               break;
11062 
11063             case CPOINTER:
11064               pic16_emitpcode (POC_MOVFF, pic16_popGet2 (AOP (right), AOP (result), GPTRSIZE - 1));
11065               break;
11066 
11067             case GPOINTER:
11068               if (GPTRSIZE > AOP_SIZE (right))
11069                 {
11070                   // assume __data pointer... THIS MIGHT BE WRONG!
11071                   pic16_movLit2f (pic16_popGet (AOP (result), GPTRSIZE - 1), GPTR_TAG_DATA);
11072                 }
11073               else
11074                 {
11075                   pic16_emitpcode (POC_MOVFF, pic16_popGet2 (AOP (right), AOP (result), GPTRSIZE - 1));
11076                 }
11077               break;
11078 
11079             default:
11080               /* this should never happen */
11081               werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "got unknown pointer type");
11082               exit (1);
11083             }
11084           //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
11085           goto release;
11086         }
11087 
11088 
11089       assert (0);
11090       /* just copy the pointers */
11091       size = AOP_SIZE (result);
11092       offset = 0;
11093       while (size--)
11094         {
11095           pic16_aopPut (AOP (result), pic16_aopGet (AOP (right), offset, FALSE, FALSE), offset);
11096           offset++;
11097         }
11098       goto release;
11099     }
11100 
11101 
11102 
11103   /* so we now know that the size of destination is greater
11104      than the size of the source.
11105      Now, if the next iCode is an operator then we might be
11106      able to optimize the operation without performing a cast.
11107    */
11108   if (genMixedOperation (ic))
11109     goto release;
11110 
11111   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
11112 
11113   /* we move to result for the size of source */
11114   size = AOP_SIZE (right);
11115   offset = 0;
11116 
11117   while (size--)
11118     {
11119       if (!_G.resDirect)
11120         pic16_mov2f (AOP (result), AOP (right), offset);
11121       offset++;
11122     }
11123 
11124   /* now depending on the sign of the destination */
11125   size = AOP_SIZE (result) - AOP_SIZE (right);
11126   /* if unsigned or not an integral type */
11127   if (SPEC_USIGN (getSpec (rtype)) || !IS_SPEC (rtype))
11128     {
11129       while (size--)
11130         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offset++));
11131     }
11132   else
11133     {
11134       /* we need to extend the sign :( */
11135 
11136       if (size == 1)
11137         {
11138           /* Save one instruction of casting char to int */
11139           pic16_emitpcode (POC_CLRF, pic16_popGet (AOP (result), offset));
11140           pic16_emitpcode (POC_BTFSC,
11141                            pic16_newpCodeOpBit (pic16_aopGet (AOP (right), offset - 1, FALSE, FALSE), 7, 0, PO_GPR_REGISTER));
11142           pic16_emitpcode (POC_SETF, pic16_popGet (AOP (result), offset));
11143         }
11144       else
11145         {
11146           pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
11147 
11148           if (offset)
11149             pic16_emitpcode (POC_BTFSC,
11150                              pic16_newpCodeOpBit (pic16_aopGet (AOP (right), offset - 1, FALSE, FALSE), 7, 0, PO_GPR_REGISTER));
11151           else
11152             pic16_emitpcode (POC_BTFSC,
11153                              pic16_newpCodeOpBit (pic16_aopGet (AOP (right), offset, FALSE, FALSE), 7, 0, PO_GPR_REGISTER));
11154 
11155           pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xff));
11156 
11157           while (size--)
11158             pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), offset++));
11159         }
11160     }
11161 
11162 release:
11163   pic16_freeAsmop (right, NULL, ic, TRUE);
11164   pic16_freeAsmop (result, NULL, ic, TRUE);
11165 
11166 }
11167 
11168 /*-----------------------------------------------------------------*/
11169 /* genDjnz - generate decrement & jump if not zero instrucion      */
11170 /*-----------------------------------------------------------------*/
11171 static int
genDjnz(iCode * ic,iCode * ifx)11172 genDjnz (iCode * ic, iCode * ifx)
11173 {
11174   DEBUGpic16_emitcode ("; ***", "%s  %d", __FUNCTION__, __LINE__);
11175 
11176   if (!ifx)
11177     return 0;
11178 
11179   /* if the if condition has a false label
11180      then we cannot save */
11181   if (IC_FALSE (ifx))
11182     return 0;
11183 
11184   /* if the minus is not of the form
11185      a = a - 1 */
11186   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) || !IS_OP_LITERAL (IC_RIGHT (ic)))
11187     return 0;
11188 
11189   if (operandLitValue (IC_RIGHT (ic)) != 1)
11190     return 0;
11191 
11192   /* if the size of this greater than one then no
11193      saving */
11194   if (getSize (operandType (IC_RESULT (ic))) > 1)
11195     return 0;
11196 
11197   /* otherwise we can save BIG */
11198   pic16_aopOp (IC_RESULT (ic), ic, FALSE);
11199 
11200   pic16_emitpcode (POC_DECFSZ, pic16_popGet (AOP (IC_RESULT (ic)), 0));
11201   pic16_emitpcode (POC_GOTO, pic16_popGetLabel (IC_TRUE (ifx)->key));
11202 
11203   pic16_freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11204   ifx->generated = 1;
11205   return 1;
11206 }
11207 
11208 /*-----------------------------------------------------------------*/
11209 /* genReceive - generate code for a receive iCode                  */
11210 /*-----------------------------------------------------------------*/
11211 static void
genReceive(iCode * ic)11212 genReceive (iCode * ic)
11213 {
11214 
11215   FENTRY;
11216 
11217 #if 0
11218   fprintf (stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11219            OP_SYMBOL (IC_RESULT (ic))->rname, OP_SYMBOL (IC_RESULT (ic))->onStack);
11220 #endif
11221 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11222 
11223   if (isOperandInFarSpace (IC_RESULT (ic)) && (OP_SYMBOL (IC_RESULT (ic))->isspilt || IS_TRUE_SYMOP (IC_RESULT (ic))))
11224     {
11225 
11226       int size = getSize (operandType (IC_RESULT (ic)));
11227       int offset = pic16_fReturnSizePic - size;
11228 
11229       assert (0);
11230       while (size--)
11231         {
11232           pic16_emitcode ("push", "%s", (strcmp (fReturn[pic16_fReturnSizePic - offset - 1], "a") ?
11233                                          fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11234           offset++;
11235         }
11236 
11237       DEBUGpic16_emitcode ("; ***", "1 %s  %d", __FUNCTION__, __LINE__);
11238 
11239       pic16_aopOp (IC_RESULT (ic), ic, FALSE);
11240       size = AOP_SIZE (IC_RESULT (ic));
11241       offset = 0;
11242       while (size--)
11243         {
11244           pic16_emitcode ("pop", "acc");
11245           pic16_aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11246         }
11247     }
11248   else
11249     {
11250       DEBUGpic16_emitcode ("; ***", "2 %s  %d argreg = %d", __FUNCTION__, __LINE__,
11251                            SPEC_ARGREG (OP_SYM_ETYPE (IC_RESULT (ic))));
11252       _G.accInUse++;
11253       pic16_aopOp (IC_RESULT (ic), ic, FALSE);
11254       _G.accInUse--;
11255 
11256       /* set pseudo stack pointer to where it should be - dw */
11257       GpseudoStkPtr = ic->parmBytes;
11258 
11259       /* setting GpseudoStkPtr has side effects here: */
11260       /* FIXME: What's the correct size of the return(ed) value?
11261        *        For now, assuming '4' as before... */
11262       assignResultValue (IC_RESULT (ic), 4, 0);
11263     }
11264 
11265   pic16_freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11266 }
11267 
11268 /*-----------------------------------------------------------------*/
11269 /* genDummyRead - generate code for dummy read of volatiles        */
11270 /*-----------------------------------------------------------------*/
11271 static void
genDummyRead(iCode * ic)11272 genDummyRead (iCode * ic)
11273 {
11274   operand *op;
11275 
11276   op = IC_RIGHT (ic);
11277   if (op && IS_SYMOP (op))
11278     {
11279       if (IN_CODESPACE (SPEC_OCLS (OP_SYM_ETYPE (op))))
11280         {
11281           fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
11282           return;
11283         }
11284       pic16_aopOp (op, ic, FALSE);
11285       pic16_mov2w_volatile (AOP (op));
11286       pic16_freeAsmop (op, NULL, ic, TRUE);
11287     }
11288   else if (op)
11289     {
11290       fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
11291     }                           // if
11292 }
11293 
11294 /*-----------------------------------------------------------------*/
11295 /* genpic16Code - generate code for pic16 based controllers        */
11296 /*-----------------------------------------------------------------*/
11297 /*
11298  * At this point, ralloc.c has gone through the iCode and attempted
11299  * to optimize in a way suitable for a PIC. Now we've got to generate
11300  * PIC instructions that correspond to the iCode.
11301  *
11302  * Once the instructions are generated, we'll pass through both the
11303  * peep hole optimizer and the pCode optimizer.
11304  *-----------------------------------------------------------------*/
11305 
11306 void
genpic16Code(iCode * lic)11307 genpic16Code (iCode * lic)
11308 {
11309   iCode *ic;
11310   int cln = 0;
11311 
11312   pb = pic16_newpCodeChain (GcurMemmap, 0, pic16_newpCodeCharP ("; Starting pCode block"));
11313   pic16_addpBlock (pb);
11314 
11315 #if 0
11316   /* if debug information required */
11317   if (options.debug && currFunc)
11318     {
11319       if (currFunc)
11320         {
11321           cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11322         }
11323     }
11324 #endif
11325 
11326   for (ic = lic; ic; ic = ic->next)
11327     {
11328       initGenLineElement ();
11329 
11330       DEBUGpic16_emitcode (";ic ", "\t%c 0x%x\t(%s)", ic->op, ic->op, pic16_decodeOp (ic->op));
11331       if (cln != ic->lineno)
11332         {
11333           if (options.debug)
11334             {
11335               debugFile->writeCLine (ic);
11336             }
11337 
11338           if (!options.noCcodeInAsm)
11339             {
11340               pic16_addpCode2pBlock (pb, pic16_newpCodeCSource (ic->lineno, ic->filename,
11341                                      printCLine (ic->filename, ic->lineno)));
11342             }
11343 
11344           cln = ic->lineno;
11345         }
11346 
11347       if (options.iCodeInAsm)
11348         {
11349           const char *iLine;
11350 
11351           /* insert here code to print iCode as comment */
11352           iLine = printILine (ic);
11353           pic16_emitpcomment ("ic:%d: %s", ic->seq, iLine);
11354           dbuf_free (iLine);
11355         }
11356 
11357       /* if the result is marked as
11358        * spilt and rematerializable or code for
11359        * this has already been generated then
11360        * do nothing */
11361       if (resultRemat (ic) || ic->generated)
11362         continue;
11363 
11364       /* depending on the operation */
11365       switch (ic->op)
11366         {
11367         case '!':
11368           pic16_genNot (ic);
11369           break;
11370 
11371         case '~':
11372           pic16_genCpl (ic);
11373           break;
11374 
11375         case UNARYMINUS:
11376           genUminus (ic);
11377           break;
11378 
11379         case IPUSH:
11380           genIpush (ic);
11381           break;
11382 
11383         case IPOP:
11384           /* IPOP happens only when trying to restore a
11385            * spilt live range, if there is an ifx statement
11386            * following this pop then the if statement might
11387            * be using some of the registers being popped which
11388            * would destroy the contents of the register so
11389            * we need to check for this condition and handle it */
11390           if (ic->next && ic->next->op == IFX && regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11391             genIfx (ic->next, ic);
11392           else
11393             genIpop (ic);
11394           break;
11395 
11396         case CALL:
11397           genCall (ic);
11398           break;
11399 
11400         case PCALL:
11401           genPcall (ic);
11402           break;
11403 
11404         case FUNCTION:
11405           genFunction (ic);
11406           break;
11407 
11408         case ENDFUNCTION:
11409           genEndFunction (ic);
11410           break;
11411 
11412         case RETURN:
11413           genRet (ic);
11414           break;
11415 
11416         case LABEL:
11417           genLabel (ic);
11418           break;
11419 
11420         case GOTO:
11421           genGoto (ic);
11422           break;
11423 
11424         case '+':
11425           pic16_genPlus (ic);
11426           break;
11427 
11428         case '-':
11429           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11430             pic16_genMinus (ic);
11431           break;
11432 
11433         case '*':
11434           genMult (ic);
11435           break;
11436 
11437         case '/':
11438           genDiv (ic);
11439           break;
11440 
11441         case '%':
11442           genMod (ic);
11443           break;
11444 
11445         case '>':
11446           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11447           break;
11448 
11449         case '<':
11450           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11451           break;
11452 
11453         case LE_OP:
11454         case GE_OP:
11455         case NE_OP:
11456           /* note these two are xlated by algebraic equivalence
11457            * during parsing SDCC.y */
11458           werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "got '>=' or '<=' shouldn't have come here");
11459           break;
11460 
11461         case EQ_OP:
11462           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11463           break;
11464 
11465         case AND_OP:
11466           genAndOp (ic);
11467           break;
11468 
11469         case OR_OP:
11470           genOrOp (ic);
11471           break;
11472 
11473         case '^':
11474           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11475           break;
11476 
11477         case '|':
11478           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11479           break;
11480 
11481         case BITWISEAND:
11482           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11483           break;
11484 
11485         case INLINEASM:
11486           pic16_genInline (ic);
11487           break;
11488 
11489         case RRC:
11490           genRRC (ic);
11491           break;
11492 
11493         case RLC:
11494           genRLC (ic);
11495           break;
11496 
11497         case GETABIT:
11498           genGetABit (ic);
11499           break;
11500 
11501         case GETHBIT:
11502           genGetHbit (ic);
11503           break;
11504 
11505         case LEFT_OP:
11506           genLeftShift (ic);
11507           break;
11508 
11509         case RIGHT_OP:
11510           genRightShift (ic);
11511           break;
11512 
11513         case GET_VALUE_AT_ADDRESS:
11514           genPointerGet (ic);
11515           break;
11516 
11517         case '=':
11518           if (POINTER_SET (ic))
11519             genPointerSet (ic);
11520           else
11521             genAssign (ic);
11522           break;
11523 
11524         case IFX:
11525           genIfx (ic, NULL);
11526           break;
11527 
11528         case ADDRESS_OF:
11529           genAddrOf (ic);
11530           break;
11531 
11532         case JUMPTABLE:
11533           genJumpTab (ic);
11534           break;
11535 
11536         case CAST:
11537           genCast (ic);
11538           break;
11539 
11540         case RECEIVE:
11541           genReceive (ic);
11542           break;
11543 
11544         case SEND:
11545           addSet (&_G.sendSet, ic);
11546           break;
11547 
11548         case DUMMY_READ_VOLATILE:
11549           genDummyRead (ic);
11550           break;
11551 
11552         case CRITICAL:
11553           genCritical (ic);
11554           break;
11555 
11556         case ENDCRITICAL:
11557           genEndCritical (ic);
11558           break;
11559 
11560         default:
11561           fprintf (stderr, "UNHANDLED iCode: ");
11562           piCode (ic, stderr);
11563           ic = ic;
11564         }
11565     }
11566 
11567 
11568   /* now we are ready to call the
11569      peep hole optimizer */
11570   if (!options.nopeep)
11571     peepHole (&genLine.lineHead);
11572 
11573   /* now do the actual printing */
11574   printLine (genLine.lineHead, codeOutBuf);
11575 
11576 #ifdef PCODE_DEBUG
11577   DFPRINTF ((stderr, "printing pBlock\n\n"));
11578   pic16_printpBlock (stdout, pb);
11579 #endif
11580 
11581   /* destroy the line list */
11582   destroy_line_list ();
11583 }
11584