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