Update svn merge history.
[sdcc.git] / sdcc / src / pic14 / gen.c
blobb540d9342193ff8cf462c86dd7afe43dbac1f37c
1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for pic
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 Copyright (C) 2005, Raphael Neider <rneider AT web.de>
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
14 later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 -------------------------------------------------------------------------*/
26 Notes:
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
32 * This is the down and dirty file with all kinds of
33 * kludgy & hacky stuff. This is what it is all about
34 * CODE GENERATION for a specific MCU . some of the
35 * routines may be reusable, will have to see.
38 #include "device.h"
39 #include "gen.h"
40 #include "glue.h"
41 #include "dbuf_string.h"
44 * Imports
46 extern struct dbuf_s *codeOutBuf;
47 extern set *externs;
49 static PIC_device *pic = NULL;
51 static pCodeOp *popGetImmd (const char *name, unsigned int offset, int index, int is_func);
52 static pCodeOp *popRegFromString (const char *str, int size, int offset);
53 static int aop_isLitLike (asmop * aop);
54 static void genCritical (iCode * ic);
55 static void genEndCritical (iCode * ic);
57 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
58 #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
60 /* special case: assign from __code */
61 #define OP_IN_CODE_SPACE(op) \
62 (!IS_ITEMP (op) /* --> iTemps never reside in __code */ \
63 && IS_SYMOP (op) /* --> must be an immediate (otherwise we would be in genConstPointerGet) */ \
64 && !IS_FUNC (OP_SYM_TYPE (op)) /* --> we would want its address instead of the first instruction */ \
65 && !IS_CODEPTR (OP_SYM_TYPE (op)) /* --> get symbols address instread */ \
66 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE (op)))))
69 * max_key keeps track of the largest label number used in
70 * a function. This is then used to adjust the label offset
71 * for the next function.
73 static int max_key = 0;
74 static int labelOffset = 0;
75 static int GpseudoStkPtr = 0;
76 static int pic14_inISR = 0;
78 static char *zero = "0x00";
79 static char *one = "0x01";
80 static char *spname = "sp";
82 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
83 static char *fReturnpic14[] = { "temp1", "temp2", "temp3", "temp4" };
85 static char **fReturn = fReturnpic14;
87 static struct
89 short accInUse;
90 short nRegsSaved;
91 set *sendSet;
92 } _G;
95 * Resolved ifx structure. This structure stores information
96 * about an iCode ifx that makes it easier to generate code.
98 typedef struct resolvedIfx
100 symbol *lbl; /* pointer to a label */
101 int condition; /* true or false ifx */
102 int generated; /* set true when the code associated with the ifx
103 * is generated */
104 } resolvedIfx;
106 static pBlock *pb;
108 /*-----------------------------------------------------------------*/
109 /* my_powof2(n) - If `n' is an integer power of 2, then the */
110 /* exponent of 2 is returned, otherwise -1 is */
111 /* returned. */
112 /* note that this is similar to the function `powof2' in SDCCsymt */
113 /* if(n == 2^y) */
114 /* return y; */
115 /* return -1; */
116 /*-----------------------------------------------------------------*/
117 static int
118 my_powof2 (unsigned long num)
120 if (num)
122 if ((num & (num - 1)) == 0)
124 int nshifts = -1;
125 while (num)
127 num >>= 1;
128 nshifts++;
130 return nshifts;
134 return -1;
137 void
138 DEBUGpic14_AopType (int line_no, operand * left, operand * right, operand * result)
141 DEBUGpic14_emitcode ("; ", "line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
142 line_no,
143 ((result) ? AopType (AOP_TYPE (result)) : "-"),
144 ((result) ? aopGet (AOP (result), 0, TRUE, FALSE) : "-"),
145 ((result) ? AOP_SIZE (result) : 0),
146 ((left) ? AopType (AOP_TYPE (left)) : "-"),
147 ((left) ? aopGet (AOP (left), 0, TRUE, FALSE) : "-"),
148 ((left) ? AOP_SIZE (left) : 0),
149 ((right) ? AopType (AOP_TYPE (right)) : "-"),
150 ((right) ? aopGet (AOP (right), 0, FALSE, FALSE) : "-"), ((right) ? AOP_SIZE (right) : 0));
154 static void
155 DEBUGpic14_AopTypeSign (int line_no, operand * left, operand * right, operand * result)
158 DEBUGpic14_emitcode ("; ", "line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
159 line_no,
160 ((result) ? AopType (AOP_TYPE (result)) : "-"),
161 ((result) ? (SPEC_USIGN (operandType (result)) ? 'u' : 's') : '-'),
162 ((left) ? AopType (AOP_TYPE (left)) : "-"),
163 ((left) ? (SPEC_USIGN (operandType (left)) ? 'u' : 's') : '-'),
164 ((right) ? AopType (AOP_TYPE (right)) : "-"),
165 ((right) ? (SPEC_USIGN (operandType (right)) ? 'u' : 's') : '-'));
169 void
170 DEBUGpic14_emitcode (const char *inst, const char *fmt, ...)
172 va_list ap;
174 if (!debug_verbose && !options.debug)
175 return;
177 va_start (ap, fmt);
178 va_emitcode (inst, fmt, ap);
179 va_end (ap);
181 addpCode2pBlock (pb, newpCodeCharP (genLine.lineCurr->line));
184 void
185 emitpComment (const char *fmt, ...)
187 va_list ap;
188 struct dbuf_s dbuf;
189 const char *line;
191 dbuf_init (&dbuf, INITIAL_INLINEASM);
193 dbuf_append_char (&dbuf, ';');
194 va_start (ap, fmt);
195 dbuf_vprintf (&dbuf, fmt, ap);
196 va_end (ap);
198 line = dbuf_detach_c_str (&dbuf);
199 emit_raw (line);
200 dbuf_free (line);
202 addpCode2pBlock (pb, newpCodeCharP (genLine.lineCurr->line));
205 void
206 emitpLabel (int key)
208 addpCode2pBlock (pb, newpCodeLabel (NULL, labelKey2num (key + labelOffset)));
211 /* gen.h defines a macro emitpcode that should be used to call emitpcode
212 * as this allows for easy debugging (ever asked the question: where was
213 * this instruction geenrated? Here is the answer... */
214 void
215 emitpcode_real (PIC_OPCODE poc, pCodeOp * pcop)
217 if (pcop)
218 addpCode2pBlock (pb, newpCode (poc, pcop));
219 else
221 static int has_warned = FALSE;
223 DEBUGpic14_emitcode (";", "%s ignoring NULL pcop", __FUNCTION__);
224 if (!has_warned)
226 has_warned = TRUE;
227 fprintf (stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n");
232 static void
233 emitpcodeNULLop (PIC_OPCODE poc)
235 addpCode2pBlock (pb, newpCode (poc, NULL));
238 /*-----------------------------------------------------------------*/
239 /* pic14_emitcode - writes the code into a file : for now it is simple */
240 /*-----------------------------------------------------------------*/
241 void
242 pic14_emitcode (const char *inst, const char *fmt, ...)
244 va_list ap;
246 va_start (ap, fmt);
247 va_emitcode (inst, fmt, ap);
248 va_end (ap);
250 if (debug_verbose)
251 addpCode2pBlock (pb, newpCodeCharP (genLine.lineCurr->line));
254 /*-----------------------------------------------------------------*/
255 /* pic14_emitDebuggerSymbol - associate the current code location */
256 /* with a debugger symbol */
257 /*-----------------------------------------------------------------*/
258 void
259 pic14_emitDebuggerSymbol (const char *debugSym)
261 genLine.lineElement.isDebug = TRUE;
262 pic14_emitcode ("", ";%s ==.", debugSym);
263 genLine.lineElement.isDebug = FALSE;
266 /*-----------------------------------------------------------------*/
267 /* newAsmop - creates a new asmOp */
268 /*-----------------------------------------------------------------*/
269 static asmop *
270 newAsmop (short type)
272 asmop *aop;
274 aop = Safe_alloc(sizeof(asmop));
275 aop->type = type;
276 return aop;
279 /*-----------------------------------------------------------------*/
280 /* resolveIfx - converts an iCode ifx into a form more useful for */
281 /* generating code */
282 /*-----------------------------------------------------------------*/
283 static void
284 resolveIfx (resolvedIfx * resIfx, iCode * ifx)
286 if (!resIfx)
287 return;
289 // DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
291 resIfx->condition = TRUE; /* assume that the ifx is true */
292 resIfx->generated = FALSE; /* indicate that the ifx has not been used */
294 if (!ifx)
296 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
298 else
300 if (IC_TRUE (ifx))
302 resIfx->lbl = IC_TRUE (ifx);
304 else
306 resIfx->lbl = IC_FALSE (ifx);
307 resIfx->condition = FALSE;
311 // DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
315 /*-----------------------------------------------------------------*/
316 /* aopForSym - for a true symbol */
317 /*-----------------------------------------------------------------*/
318 static asmop *
319 aopForSym (iCode * ic, symbol * sym, bool result)
321 asmop *aop;
322 memmap *space = SPEC_OCLS (sym->etype);
324 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
325 /* if already has one */
326 if (sym->aop)
327 return sym->aop;
329 //DEBUGpic14_emitcode(";","%d",__LINE__);
330 /* if it is in direct space */
331 if (IN_DIRSPACE (space))
333 sym->aop = aop = newAsmop (AOP_DIR);
334 aop->aopu.aop_dir = sym->rname;
335 aop->size = getSize (sym->type);
336 DEBUGpic14_emitcode (";", "%d sym->rname = %s, size = %d", __LINE__, sym->rname, aop->size);
337 return aop;
340 /* special case for a function */
341 if (IS_FUNC (sym->type))
344 sym->aop = aop = newAsmop (AOP_PCODE);
345 aop->aopu.pcop = popGetImmd (sym->rname, 0, 0, 1);
346 PCOI (aop->aopu.pcop)->_const = IN_CODESPACE (space);
347 PCOI (aop->aopu.pcop)->_function = TRUE;
348 PCOI (aop->aopu.pcop)->index = 0;
349 aop->size = FARPTRSIZE;
350 /* if it is in code space */
351 if (IN_CODESPACE (space))
352 aop->code = TRUE;
353 DEBUGpic14_emitcode (";", "%d size = %d, name =%s", __LINE__, aop->size, sym->rname);
354 return aop;
357 if (IS_ARRAY (sym->type))
359 sym->aop = aop = newAsmop (AOP_PCODE);
360 aop->aopu.pcop = popGetImmd (sym->rname, 0, 0, 1);
361 PCOI (aop->aopu.pcop)->_const = IN_CODESPACE (space);
362 PCOI (aop->aopu.pcop)->_function = FALSE;
363 PCOI (aop->aopu.pcop)->index = 0;
364 aop->size = getSize (sym->etype) * DCL_ELEM (sym->type);
365 /* if it is in code space */
366 if (IN_CODESPACE (space))
367 aop->code = TRUE;
368 DEBUGpic14_emitcode (";", "%d size = %d, name =%s", __LINE__, aop->size, sym->rname);
369 return aop;
372 /* only remaining is far space */
373 /* in which case DPTR gets the address */
374 sym->aop = aop = newAsmop (AOP_PCODE);
376 aop->aopu.pcop = popGetImmd (sym->rname, 0, 0, 0);
377 PCOI (aop->aopu.pcop)->_const = IN_CODESPACE (space);
378 PCOI (aop->aopu.pcop)->index = 0;
380 DEBUGpic14_emitcode (";", "%d: rname %s, val %d, const = %d", __LINE__, sym->rname, 0, PCOI (aop->aopu.pcop)->_const);
382 allocDirReg (IC_LEFT (ic));
384 aop->size = getSize(sym->type);
386 /* if it is in code space */
387 if (IN_CODESPACE (space))
388 aop->code = TRUE;
390 return aop;
393 /*-----------------------------------------------------------------*/
394 /* aopForRemat - rematerialzes an object */
395 /*-----------------------------------------------------------------*/
396 static asmop *
397 aopForRemat (operand * op) // x symbol *sym)
399 symbol *sym = OP_SYMBOL (op);
400 iCode *ic = NULL;
401 asmop *aop = newAsmop (AOP_PCODE);
402 int val = 0;
404 ic = sym->rematiCode;
406 DEBUGpic14_emitcode (";", "%s %d", __FUNCTION__, __LINE__);
407 if (IS_OP_POINTER (op))
409 DEBUGpic14_emitcode (";", "%s %d IS_OP_POINTER", __FUNCTION__, __LINE__);
411 for (;;)
413 if (ic->op == '+')
415 val += (int) operandLitValue (IC_RIGHT (ic));
417 else if (ic->op == '-')
419 val -= (int) operandLitValue (IC_RIGHT (ic));
421 else
422 break;
424 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
427 aop->aopu.pcop = popGetImmd (OP_SYMBOL (IC_LEFT (ic))->rname, 0, val, 0);
428 PCOI (aop->aopu.pcop)->_const = IS_PTR_CONST (operandType (op));
429 PCOI (aop->aopu.pcop)->index = val;
431 DEBUGpic14_emitcode (";", "%d: rname %s, val %d, const = %d",
432 __LINE__, OP_SYMBOL (IC_LEFT (ic))->rname, val, IS_PTR_CONST (operandType (op)));
434 // DEBUGpic14_emitcode(";","aop type %s",AopType(AOP_TYPE(IC_LEFT(ic))));
436 allocDirReg (IC_LEFT (ic));
438 return aop;
441 static int
442 aopIdx (asmop * aop, int offset)
444 if (!aop)
445 return -1;
447 if (aop->type != AOP_REG)
448 return -2;
450 return aop->aopu.aop_reg[offset]->rIdx;
454 /*-----------------------------------------------------------------*/
455 /* regsInCommon - two operands have some registers in common */
456 /*-----------------------------------------------------------------*/
457 static bool
458 regsInCommon (operand * op1, operand * op2)
460 symbol *sym1, *sym2;
461 int i;
463 /* if they have registers in common */
464 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
465 return FALSE;
467 sym1 = OP_SYMBOL (op1);
468 sym2 = OP_SYMBOL (op2);
470 if (sym1->nRegs == 0 || sym2->nRegs == 0)
471 return FALSE;
473 for (i = 0; i < sym1->nRegs; i++)
475 int j;
476 if (!sym1->regs[i])
477 continue;
479 for (j = 0; j < sym2->nRegs; j++)
481 if (!sym2->regs[j])
482 continue;
484 if (sym2->regs[j] == sym1->regs[i])
485 return TRUE;
489 return FALSE;
492 /*-----------------------------------------------------------------*/
493 /* operandsEqu - equivalent */
494 /*-----------------------------------------------------------------*/
495 static bool
496 operandsEqu (operand * op1, operand * op2)
498 symbol *sym1, *sym2;
500 /* if they not symbols */
501 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
502 return FALSE;
504 sym1 = OP_SYMBOL (op1);
505 sym2 = OP_SYMBOL (op2);
507 /* if both are itemps & one is spilt
508 and the other is not then false */
509 if (IS_ITEMP (op1) && IS_ITEMP (op2) && sym1->isspilt != sym2->isspilt)
510 return FALSE;
512 /* if they are the same */
513 if (sym1 == sym2)
514 return TRUE;
516 if (sym1->rname[0] && sym2->rname[0] && strcmp (sym1->rname, sym2->rname) == 0)
517 return TRUE;
520 /* if left is a tmp & right is not */
521 if (IS_ITEMP (op1) && !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
522 return TRUE;
524 if (IS_ITEMP (op2) && !IS_ITEMP (op1) && sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
525 return TRUE;
527 return FALSE;
530 /*-----------------------------------------------------------------*/
531 /* pic14_sameRegs - two asmops have the same registers */
532 /*-----------------------------------------------------------------*/
533 bool
534 pic14_sameRegs (asmop * aop1, asmop * aop2)
536 int i;
538 if (aop1 == aop2)
539 return TRUE;
541 if (aop1->type != AOP_REG || aop2->type != AOP_REG)
542 return FALSE;
544 if (aop1->size != aop2->size)
545 return FALSE;
547 for (i = 0; i < aop1->size; i++)
548 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
549 return FALSE;
551 return TRUE;
554 /*-----------------------------------------------------------------*/
555 /* aopOp - allocates an asmop for an operand : */
556 /*-----------------------------------------------------------------*/
557 void
558 aopOp (operand * op, iCode * ic, bool result)
560 asmop *aop;
561 symbol *sym;
562 int i;
564 if (!op)
565 return;
567 /* if this a literal */
568 if (IS_OP_LITERAL (op))
570 op->aop = aop = newAsmop (AOP_LIT);
571 aop->aopu.aop_lit = OP_VALUE (op);
572 aop->size = getSize (operandType (op));
573 return;
577 sym_link *type = operandType (op);
578 if (IS_PTR_CONST (type))
579 DEBUGpic14_emitcode (";", "%d aop type is const pointer", __LINE__);
582 /* if already has a asmop then continue */
583 if (op->aop)
584 return;
586 /* if the underlying symbol has a aop */
587 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
589 DEBUGpic14_emitcode (";", "%d", __LINE__);
590 op->aop = OP_SYMBOL (op)->aop;
591 return;
594 /* if this is a true symbol */
595 if (IS_TRUE_SYMOP (op))
597 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
598 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
599 return;
602 /* this is a temporary : this has
603 only four choices :
604 a) register
605 b) spillocation
606 c) rematerialize
607 d) conditional
608 e) can be a return use only */
610 sym = OP_SYMBOL (op);
613 /* if the type is a conditional */
614 if (sym->regType == REG_CND)
616 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
617 aop->size = 0;
618 return;
621 /* if it is spilt then two situations
622 a) is rematerialize
623 b) has a spill location */
624 if (sym->isspilt || sym->nRegs == 0)
627 DEBUGpic14_emitcode (";", "%d", __LINE__);
628 /* rematerialize it NOW */
629 if (sym->remat)
632 sym->aop = op->aop = aop = aopForRemat (op);
633 aop->size = getSize (sym->type);
634 //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
635 return;
638 if (sym->ruonly)
640 if (sym->isptr) // && sym->uptr
642 aop = op->aop = sym->aop = newAsmop (AOP_PCODE);
643 aop->aopu.pcop = newpCodeOp (NULL, PO_GPR_POINTER); //popCopyReg(&pc_fsr);
645 //PCOI(aop->aopu.pcop)->_const = 0;
646 //PCOI(aop->aopu.pcop)->index = 0;
648 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
649 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
651 //allocDirReg (IC_LEFT(ic));
653 aop->size = getSize (sym->type);
654 DEBUGpic14_emitcode (";", "%d", __LINE__);
655 return;
658 else
661 unsigned i;
663 aop = op->aop = sym->aop = newAsmop (AOP_STR);
664 aop->size = getSize (sym->type);
665 for (i = 0; i < fReturnSizePic; i++)
666 aop->aopu.aop_str[i] = fReturn[i];
668 DEBUGpic14_emitcode (";", "%d", __LINE__);
669 return;
673 /* else spill location */
674 if (sym->isspilt && sym->usl.spillLoc)
676 asmop *oldAsmOp = NULL;
678 if (getSize (sym->type) != getSize (sym->usl.spillLoc->type))
680 /* force a new aop if sizes differ */
681 oldAsmOp = sym->usl.spillLoc->aop;
682 sym->usl.spillLoc->aop = NULL;
684 DEBUGpic14_emitcode (";", "%s %d %s sym->rname = %s, offset %d",
685 __FUNCTION__, __LINE__, sym->usl.spillLoc->rname, sym->rname, sym->usl.spillLoc->offset);
687 sym->aop = op->aop = aop = newAsmop (AOP_PCODE);
688 if (getSize (sym->type) != getSize (sym->usl.spillLoc->type))
690 /* Don't reuse the new aop, go with the last one */
691 sym->usl.spillLoc->aop = oldAsmOp;
693 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
694 aop->aopu.pcop = popRegFromString (sym->usl.spillLoc->rname, getSize (sym->type), sym->usl.spillLoc->offset);
695 aop->size = getSize (sym->type);
697 return;
702 sym_link *type = operandType (op);
703 if (IS_PTR_CONST (type))
704 DEBUGpic14_emitcode (";", "%d aop type is const pointer", __LINE__);
707 /* must be in a register */
708 DEBUGpic14_emitcode (";", "%d register type nRegs=%d", __LINE__, sym->nRegs);
709 sym->aop = op->aop = aop = newAsmop (AOP_REG);
710 aop->size = sym->nRegs;
711 for (i = 0; i < sym->nRegs; i++)
712 aop->aopu.aop_reg[i] = sym->regs[i];
715 /*-----------------------------------------------------------------*/
716 /* freeAsmop - free up the asmop given to an operand */
717 /*----------------------------------------------------------------*/
718 void
719 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
721 asmop *aop;
723 if (!op)
724 aop = aaop;
725 else
726 aop = op->aop;
728 if (!aop)
729 return;
731 aop->freed = TRUE;
733 /* all other cases just dealloc */
734 if (op)
736 op->aop = NULL;
737 if (IS_SYMOP (op))
739 OP_SYMBOL (op)->aop = NULL;
740 /* if the symbol has a spill */
741 if (SPIL_LOC (op))
742 SPIL_LOC (op)->aop = NULL;
747 /*-----------------------------------------------------------------*/
748 /* pic14aopLiteral - string from a literal value */
749 /*-----------------------------------------------------------------*/
750 static unsigned int
751 pic14aopLiteral (value * val, int offset)
753 union
755 float f;
756 unsigned char c[4];
757 } fl;
759 /* if it is a float then it gets tricky */
760 /* otherwise it is fairly simple */
761 if (!IS_FLOAT (val->type))
763 unsigned long v = ulFromVal (val);
765 return ((v >> (offset * 8)) & 0xff);
768 /* it is type float */
769 fl.f = (float) floatFromVal (val);
770 #ifdef WORDS_BIGENDIAN
771 return fl.c[3 - offset];
772 #else
773 return fl.c[offset];
774 #endif
777 /*-----------------------------------------------------------------*/
778 /* aopGet - for fetching value of the aop */
779 /*-----------------------------------------------------------------*/
780 char *
781 aopGet (asmop * aop, int offset, bool bit16, bool dname)
783 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
784 /* offset is greater than
785 size then zero */
786 assert (aop);
787 if (offset > (aop->size - 1) && aop->type != AOP_LIT)
788 return zero;
790 /* depending on type */
791 switch (aop->type)
793 case AOP_IMMD:
794 if (bit16)
795 SNPRINTF(buffer, sizeof(buffer), "%s", aop->aopu.aop_immd);
796 else if (offset)
797 SNPRINTF(buffer, sizeof(buffer), "(%s >> %d)", aop->aopu.aop_immd, offset * 8);
798 else
799 SNPRINTF(buffer, sizeof(buffer), "%s", aop->aopu.aop_immd);
800 DEBUGpic14_emitcode (";", "%d immd %s", __LINE__, buffer);
801 return Safe_strdup(buffer);
803 case AOP_DIR:
804 if (offset)
806 SNPRINTF(buffer, sizeof(buffer), "(%s + %d)", aop->aopu.aop_dir, offset);
807 DEBUGpic14_emitcode (";", "oops AOP_DIR did this %s\n", buffer);
809 else
810 SNPRINTF(buffer, sizeof(buffer), "%s", aop->aopu.aop_dir);
811 return Safe_strdup(buffer);
813 case AOP_REG:
814 //if (dname)
815 // return aop->aopu.aop_reg[offset]->dname;
816 //else
817 return aop->aopu.aop_reg[offset]->name;
819 case AOP_CRY:
820 //pic14_emitcode(";","%d",__LINE__);
821 return aop->aopu.aop_dir;
823 case AOP_LIT:
824 SNPRINTF(buffer, sizeof(buffer), "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
825 return Safe_strdup(buffer);
827 case AOP_STR:
828 aop->coff = offset;
829 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 && dname)
830 return "acc";
831 DEBUGpic14_emitcode (";", "%d - %s", __LINE__, aop->aopu.aop_str[offset]);
832 return aop->aopu.aop_str[offset];
834 case AOP_PCODE:
836 pCodeOp *pcop = aop->aopu.pcop;
837 DEBUGpic14_emitcode (";", "%d: aopGet AOP_PCODE type %s", __LINE__, pCodeOpType (pcop));
838 if (pcop->name)
840 if (pcop->type == PO_IMMEDIATE)
842 offset += PCOI (pcop)->index;
845 if (offset)
847 DEBUGpic14_emitcode (";", "%s offset %d", pcop->name, offset);
848 SNPRINTF(buffer, sizeof(buffer), "(%s+%d)", pcop->name, offset);
850 else
852 DEBUGpic14_emitcode (";", "%s", pcop->name);
853 SNPRINTF(buffer, sizeof(buffer), "%s", pcop->name);
856 else
857 SNPRINTF(buffer, sizeof(buffer), "0x%02x", PCOI (aop->aopu.pcop)->offset);
860 return Safe_strdup(buffer);
863 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "aopGet got unsupported aop->type");
864 exit (1);
867 /*-----------------------------------------------------------------*/
868 /* popGetTempReg - create a new temporary pCodeOp */
869 /*-----------------------------------------------------------------*/
870 static pCodeOp *
871 popGetTempReg (void)
874 pCodeOp *pcop;
876 pcop = newpCodeOp (NULL, PO_GPR_TEMP);
877 if (pcop && pcop->type == PO_GPR_TEMP && PCOR (pcop)->r)
879 PCOR (pcop)->r->wasUsed = TRUE;
880 PCOR (pcop)->r->isFree = FALSE;
883 return pcop;
886 /*-----------------------------------------------------------------*/
887 /* popReleaseTempReg - create a new temporary pCodeOp */
888 /*-----------------------------------------------------------------*/
889 static void
890 popReleaseTempReg (pCodeOp * pcop)
893 if (pcop && pcop->type == PO_GPR_TEMP && PCOR (pcop)->r)
894 PCOR (pcop)->r->isFree = TRUE;
898 /*-----------------------------------------------------------------*/
899 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
900 /*-----------------------------------------------------------------*/
901 pCodeOp *
902 popGetLabel (unsigned int key)
905 DEBUGpic14_emitcode ("; ***", "%s key=%d, label offset %d", __FUNCTION__, key, labelOffset);
907 if (key > (unsigned int) max_key)
908 max_key = key;
910 return newpCodeOpLabel (NULL, labelKey2num (key + labelOffset));
913 /*-------------------------------------------------------------------*/
914 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
915 /*-------------------------------------------------------------------*/
916 static pCodeOp *
917 popGetHighLabel (unsigned int key)
919 pCodeOp *pcop;
920 pcop = popGetLabel (key);
921 PCOLAB (pcop)->offset = 1;
922 return pcop;
925 /*-----------------------------------------------------------------*/
926 /* popGetLit - asm operator to pcode operator conversion */
927 /*-----------------------------------------------------------------*/
928 pCodeOp *
929 popGetLit (unsigned int lit)
932 return newpCodeOpLit ((unsigned char) lit);
935 /*-----------------------------------------------------------------*/
936 /* popGetImmd - asm operator to pcode immediate conversion */
937 /*-----------------------------------------------------------------*/
938 static pCodeOp *
939 popGetImmd (const char *name, unsigned int offset, int index, int is_func)
942 return newpCodeOpImmd (name, offset, index, 0, is_func);
945 /*-----------------------------------------------------------------*/
946 /* popGetWithString - asm operator to pcode operator conversion */
947 /*-----------------------------------------------------------------*/
948 static pCodeOp *
949 popGetWithString (const char *str, int isExtern)
951 pCodeOp *pcop;
953 if (!str)
955 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "NULL string");
956 exit (1);
959 pcop = newpCodeOp (str, PO_STR);
960 PCOS (pcop)->isPublic = isExtern ? 1 : 0;
962 return pcop;
965 pCodeOp *
966 popGetExternal (const char *str, int isReg)
968 pCodeOp *pcop;
969 symbol *sym;
971 if (!str)
973 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "NULL string");
974 exit (1);
977 if (isReg)
979 pcop = newpCodeOpRegFromStr (str);
981 else
983 pcop = popGetWithString (str, 1);
986 /* create symbol, mark it as `extern' */
987 sym = findSym (SymbolTab, NULL, str+1);
988 if (!sym)
990 DEBUGpic14_emitcode (";", "%s %d added symbol %s", __FUNCTION__, __LINE__, str);
991 sym = newSymbol (str+1, 0);
992 strncpy (sym->rname, str, SDCC_NAME_MAX);
993 addSym (SymbolTab, sym, sym->rname, 0, 0, 0);
996 /* registers are NOT external */
997 if (!isReg)
999 symbol *esym;
1000 for (esym = setFirstItem (externs); esym; esym = setNextItem (externs))
1002 if (!strcmp (str, esym->rname))
1003 break;
1006 if (!esym)
1008 DEBUGpic14_emitcode (";", "%s %d added extern %s", __FUNCTION__, __LINE__, str);
1009 addSet (&externs, sym);
1012 sym->used++;
1014 return pcop;
1017 /*-----------------------------------------------------------------*/
1018 /* popRegFromString - */
1019 /*-----------------------------------------------------------------*/
1020 static pCodeOp *
1021 popRegFromString (const char *str, int size, int offset)
1024 pCodeOp *pcop = Safe_alloc(sizeof(pCodeOpReg));
1025 pcop->type = PO_DIR;
1027 DEBUGpic14_emitcode (";", "%d", __LINE__);
1029 if (!str)
1030 str = "BAD_STRING";
1032 pcop->name = Safe_strdup(str);
1034 //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1036 PCOR (pcop)->r = dirregWithName (pcop->name);
1037 if (PCOR (pcop)->r == NULL)
1039 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1040 PCOR (pcop)->r = allocRegByName (pcop->name, size);
1041 DEBUGpic14_emitcode (";", "%d %s offset=%d - had to alloc by reg name", __LINE__, pcop->name, offset);
1043 else
1045 DEBUGpic14_emitcode (";", "%d %s offset=%d", __LINE__, pcop->name, offset);
1047 PCOR (pcop)->instance = offset;
1049 return pcop;
1052 /*-----------------------------------------------------------------*/
1053 /*-----------------------------------------------------------------*/
1054 static pCodeOp *
1055 popRegFromIdx (int rIdx)
1057 pCodeOp *pcop;
1059 DEBUGpic14_emitcode ("; ***", "%s,%d , rIdx=0x%x", __FUNCTION__, __LINE__, rIdx);
1061 pcop = Safe_alloc(sizeof(pCodeOpReg));
1063 PCOR (pcop)->rIdx = rIdx;
1064 PCOR (pcop)->r = typeRegWithIdx (rIdx, REG_STK, 1);
1065 PCOR (pcop)->r->isFree = FALSE;
1066 PCOR (pcop)->r->wasUsed = TRUE;
1068 pcop->type = PCOR (pcop)->r->pc_type;
1071 return pcop;
1074 /*-----------------------------------------------------------------*/
1075 /* popGet - asm operator to pcode operator conversion */
1076 /*-----------------------------------------------------------------*/
1077 pCodeOp *
1078 popGet (asmop * aop, int offset) //, bool bit16, bool dname)
1080 //char *s = buffer ;
1081 //char *rs;
1083 pCodeOp *pcop;
1085 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1086 /* offset is greater than
1087 size then zero */
1089 assert (aop);
1092 /* XXX: still needed for BIT operands (AOP_CRY) */
1093 if ((offset >= aop->size) && (aop->type != AOP_LIT) && (aop->type != AOP_PCODE))
1095 printf ("%s: (offset[%d] >= AOP_SIZE(op)[%d]) && (AOP_TYPE(op)[%d] != { AOP_LIT, AOP_PCODE })\n",
1096 __FUNCTION__, offset, aop->size, aop->type);
1097 return NULL; //zero;
1100 /* depending on type */
1101 switch (aop->type)
1104 case AOP_IMMD:
1105 DEBUGpic14_emitcode (";", "%d", __LINE__);
1106 return popGetImmd (aop->aopu.aop_immd, offset, 0, 0);
1108 case AOP_DIR:
1109 return popRegFromString (aop->aopu.aop_dir, aop->size, offset);
1111 case AOP_REG:
1113 int rIdx;
1114 assert (offset < aop->size);
1115 rIdx = aop->aopu.aop_reg[offset]->rIdx;
1117 pcop = Safe_alloc(sizeof(pCodeOpReg));
1118 PCOR (pcop)->rIdx = rIdx;
1119 PCOR (pcop)->r = pic14_regWithIdx (rIdx);
1120 PCOR (pcop)->r->wasUsed = TRUE;
1121 PCOR (pcop)->r->isFree = FALSE;
1123 PCOR (pcop)->instance = offset;
1124 pcop->type = PCOR (pcop)->r->pc_type;
1125 //rs = aop->aopu.aop_reg[offset]->name;
1126 DEBUGpic14_emitcode (";", "%d rIdx = r0x%X ", __LINE__, rIdx);
1127 return pcop;
1130 case AOP_CRY:
1131 pcop = newpCodeOpBit (aop->aopu.aop_dir, -1, 1);
1132 PCOR (pcop)->r = dirregWithName (aop->aopu.aop_dir);
1133 //if(PCOR(pcop)->r == NULL)
1134 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1135 return pcop;
1137 case AOP_LIT:
1138 return newpCodeOpLit (pic14aopLiteral (aop->aopu.aop_lit, offset));
1140 case AOP_STR:
1141 DEBUGpic14_emitcode (";", "%d %s", __LINE__, aop->aopu.aop_str[offset]);
1142 return newpCodeOpRegFromStr (aop->aopu.aop_str[offset]);
1144 case AOP_PCODE:
1145 pcop = NULL;
1146 DEBUGpic14_emitcode (";", "popGet AOP_PCODE (%s + %i) %d %s", pCodeOpType (aop->aopu.pcop), offset,
1147 __LINE__, ((aop->aopu.pcop->name) ? (aop->aopu.pcop->name) : "no name"));
1148 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1149 switch (aop->aopu.pcop->type)
1151 case PO_IMMEDIATE:
1152 pcop = pCodeOpCopy (aop->aopu.pcop);
1153 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1154 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1155 PCOI (pcop)->index += offset;
1156 //PCOI(pcop)->offset = 0;
1157 break;
1158 case PO_DIR:
1159 pcop = pCodeOpCopy (aop->aopu.pcop);
1160 PCOR (pcop)->instance = offset;
1161 break;
1162 default:
1163 assert (!"unhandled pCode type");
1164 break;
1165 } // switch
1166 return pcop;
1169 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "popGet got unsupported aop->type");
1170 exit (1);
1173 /*-----------------------------------------------------------------*/
1174 /* popGetAddr - access the low/high word of a symbol (immediate) */
1175 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1176 /*-----------------------------------------------------------------*/
1177 pCodeOp *
1178 popGetAddr (asmop * aop, int offset, int index)
1180 if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1182 pCodeOp *pcop = aop->aopu.pcop;
1183 assert (offset <= GPTRSIZE);
1185 /* special case: index >= 2 should return GPOINTER-style values */
1186 if (offset == 2)
1188 pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1189 return pcop;
1192 pcop = pCodeOpCopy (pcop);
1193 /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1194 * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1195 PCOI (pcop)->offset += offset;
1196 PCOI (pcop)->index += index;
1197 //fprintf (stderr, "is PO_IMMEDIATE: %s+o%d+i%d (new o%d,i%d)\n", pcop->name,PCOI(pcop)->offset,PCOI(pcop)->index, offset, index);
1198 return pcop;
1200 else
1202 return popGet (aop, offset + index);
1206 /*-----------------------------------------------------------------*/
1207 /* aopPut - puts a string for a aop */
1208 /*-----------------------------------------------------------------*/
1209 void
1210 aopPut (asmop * aop, const char *s, int offset)
1212 symbol *lbl;
1214 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
1216 if (aop->size && offset > (aop->size - 1))
1218 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "aopPut got offset > aop->size");
1219 exit (1);
1222 /* will assign value to value */
1223 /* depending on where it is ofcourse */
1224 switch (aop->type)
1226 case AOP_DIR:
1227 if (offset)
1229 SNPRINTF(buffer, sizeof(buffer), "(%s + %d)", aop->aopu.aop_dir, offset);
1230 fprintf (stderr, "oops aopPut:AOP_DIR did this %s\n", s);
1232 else
1233 SNPRINTF(buffer, sizeof(buffer), "%s", aop->aopu.aop_dir);
1235 if (strcmp (buffer, s))
1237 DEBUGpic14_emitcode (";", "%d", __LINE__);
1238 if (strcmp (s, "W"))
1239 pic14_emitcode ("movf", "%s,w", s);
1241 pic14_emitcode ("movwf", "%s", buffer);
1243 if (strcmp (s, "W"))
1245 pic14_emitcode (";BUG!? should have this:movf", "%s,w %d", s, __LINE__);
1246 if (offset >= aop->size)
1248 emitpcode (POC_CLRF, popGet (aop, offset));
1249 break;
1251 else
1253 emitpcode (POC_MOVFW, popGetImmd (s, 0, offset, 0));
1256 emitpcode (POC_MOVWF, popGet (aop, offset));
1258 break;
1260 case AOP_REG:
1261 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0)
1263 if (strcmp (s, "W") == 0)
1264 pic14_emitcode ("movf", "%s,w ; %d", s, __LINE__);
1266 pic14_emitcode ("movwf", "%s", aop->aopu.aop_reg[offset]->name);
1268 if (strcmp (s, zero) == 0)
1270 emitpcode (POC_CLRF, popGet (aop, offset));
1273 else if (strcmp (s, "W") == 0)
1275 pCodeOp *pcop = Safe_alloc(sizeof(pCodeOpReg));
1276 pcop->type = PO_GPR_REGISTER;
1278 PCOR (pcop)->rIdx = -1;
1279 PCOR (pcop)->r = NULL;
1281 DEBUGpic14_emitcode (";", "%d", __LINE__);
1282 pcop->name = Safe_strdup (s);
1283 emitpcode (POC_MOVFW, pcop);
1284 emitpcode (POC_MOVWF, popGet (aop, offset));
1286 else if (strcmp (s, one) == 0)
1288 emitpcode (POC_CLRF, popGet (aop, offset));
1289 emitpcode (POC_INCF, popGet (aop, offset));
1291 else
1293 emitpcode (POC_MOVWF, popGet (aop, offset));
1296 break;
1298 case AOP_STK:
1299 if (strcmp (s, "a") == 0)
1300 pic14_emitcode ("push", "acc");
1301 else
1302 pic14_emitcode ("push", "%s", s);
1303 break;
1305 case AOP_CRY:
1306 /* if bit variable */
1307 if (!aop->aopu.aop_dir)
1309 pic14_emitcode ("clr", "a");
1310 pic14_emitcode ("rlc", "a");
1312 else
1314 if (s == zero)
1315 pic14_emitcode ("clr", "%s", aop->aopu.aop_dir);
1316 else if (s == one)
1317 pic14_emitcode ("setb", "%s", aop->aopu.aop_dir);
1318 else if (!strcmp (s, "c"))
1319 pic14_emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1320 else
1322 lbl = newiTempLabel (NULL);
1324 if (strcmp (s, "a"))
1326 MOVA (s);
1329 pic14_emitcode ("clr", "c");
1330 pic14_emitcode ("jz", "%05d_DS_", labelKey2num (lbl->key));
1331 pic14_emitcode ("cpl", "c");
1332 pic14_emitcode ("", "%05d_DS_:", labelKey2num (lbl->key));
1333 pic14_emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1336 break;
1338 case AOP_STR:
1339 aop->coff = offset;
1340 if (strcmp (aop->aopu.aop_str[offset], s))
1341 pic14_emitcode ("mov", "%s,%s ; %d", aop->aopu.aop_str[offset], s, __LINE__);
1342 break;
1344 default:
1345 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "aopPut got unsupported aop->type");
1346 exit(1);
1350 /*-----------------------------------------------------------------*/
1351 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1352 /*-----------------------------------------------------------------*/
1353 void
1354 mov2w_op (operand * op, int offset)
1356 assert (op);
1357 FENTRY;
1359 /* for PO_IMMEDIATEs: use address or value? */
1360 if (op_isLitLike (op))
1362 /* access address of op */
1363 if (AOP_TYPE (op) != AOP_LIT)
1365 assert (offset < 3);
1367 if (IS_SYMOP (op) && IS_GENPTR (OP_SYM_TYPE (op)) && AOP_SIZE (op) < offset)
1369 if (offset == GPTRSIZE - 1)
1370 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1371 else
1372 emitpcode (POC_MOVLW, popGetLit (0));
1374 else
1375 emitpcode (POC_MOVLW, popGetAddr (AOP (op), offset, 0));
1377 else
1379 /* access value stored in op */
1380 mov2w (AOP (op), offset);
1385 /*-----------------------------------------------------------------*/
1386 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1387 /*-----------------------------------------------------------------*/
1388 void
1389 mov2w (asmop * aop, int offset)
1392 if (!aop)
1393 return;
1395 DEBUGpic14_emitcode ("; ***", "%s %d offset=%d", __FUNCTION__, __LINE__, offset);
1397 if (aop_isLitLike (aop))
1398 emitpcode (POC_MOVLW, popGetAddr (aop, offset, 0));
1399 else
1400 emitpcode (POC_MOVFW, popGet (aop, offset));
1404 static void
1405 movwf (asmop * op, int offset)
1407 emitpcode (POC_MOVWF, popGet (op, offset));
1410 static pCodeOp *
1411 get_argument_pcop (int idx)
1413 assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1414 return popRegFromIdx (Gstack_base_addr - (idx - 1));
1417 static pCodeOp *
1418 get_return_val_pcop (int offset)
1420 assert (offset > 0 && "the most significant byte is returned via WREG");
1421 return popRegFromIdx (Gstack_base_addr - (offset - 1));
1424 static void
1425 pass_argument (operand * op, int offset, int idx)
1427 if (op)
1428 mov2w_op (op, offset);
1429 if (idx != 0)
1430 emitpcode (POC_MOVWF, get_argument_pcop (idx));
1433 static void
1434 get_returnvalue (operand * op, int offset, int idx)
1436 if (idx != 0)
1437 emitpcode (POC_MOVFW, get_return_val_pcop (idx));
1438 movwf (AOP (op), offset);
1441 static void
1442 call_libraryfunc (char *name)
1444 /* library code might reside in different page... */
1445 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1446 /* call the library function */
1447 emitpcode (POC_CALL, popGetExternal (name, 0));
1448 /* might return from different page... */
1449 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1452 /*-----------------------------------------------------------------*/
1453 /* pic14_getDataSize - get the operand data size */
1454 /*-----------------------------------------------------------------*/
1456 pic14_getDataSize (operand * op)
1458 int size;
1460 size = AOP_SIZE (op);
1461 return size;
1464 /*-----------------------------------------------------------------*/
1465 /* pic14_outAcc - output Acc */
1466 /*-----------------------------------------------------------------*/
1467 void
1468 pic14_outAcc (operand * result)
1470 int size, offset;
1471 DEBUGpic14_emitcode ("; ***", "%s %d - ", __FUNCTION__, __LINE__);
1472 DEBUGpic14_AopType (__LINE__, NULL, NULL, result);
1475 size = pic14_getDataSize (result);
1476 if (size)
1478 emitpcode (POC_MOVWF, popGet (AOP (result), 0));
1479 size--;
1480 offset = 1;
1481 /* unsigned or positive */
1482 while (size--)
1483 emitpcode (POC_CLRF, popGet (AOP (result), offset++));
1488 /*-----------------------------------------------------------------*/
1489 /* pic14_outBitC - output a bit C */
1490 /*-----------------------------------------------------------------*/
1491 static void
1492 pic14_outBitC (operand * result)
1495 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
1496 /* if the result is bit */
1497 if (AOP_TYPE (result) == AOP_CRY)
1498 aopPut (AOP (result), "c", 0);
1499 else
1501 pic14_emitcode ("clr", "a ; %d", __LINE__);
1502 pic14_emitcode ("rlc", "a");
1503 pic14_outAcc (result);
1507 /*-----------------------------------------------------------------*/
1508 /* pic14_toBoolean - emit code for orl a,operator(sizeop) */
1509 /*-----------------------------------------------------------------*/
1510 static void
1511 pic14_toBoolean (operand * oper)
1513 int size = AOP_SIZE (oper);
1515 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
1517 assert (size > 0);
1519 /* for generic pointers ignore the TAG, so we get (gptr != NULL) */
1520 if (IS_GENPTR(operandType(oper)))
1521 size = GPTRSIZE - 1;
1523 /* proceed MSB to LSB so we can clear the sign bit for floats */
1524 mov2w (AOP (oper), --size);
1525 if (IS_FLOAT(operandType(oper)))
1526 emitpcode (POC_ANDLW, popGetLit (0x7f));
1528 while (size--)
1530 if (op_isLitLike (oper))
1531 emitpcode (POC_IORLW, popGetAddr (AOP (oper), size, 0));
1532 else
1533 emitpcode (POC_IORFW, popGet (AOP (oper), size));
1535 /* Z is set iff (oper == 0) */
1539 /*-----------------------------------------------------------------*/
1540 /* genNot - generate code for ! operation */
1541 /*-----------------------------------------------------------------*/
1542 static void
1543 genNot (iCode * ic)
1545 //symbol *tlbl;
1546 int size;
1548 FENTRY;
1550 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
1551 /* assign asmOps to operand & result */
1552 aopOp (IC_LEFT (ic), ic, FALSE);
1553 aopOp (IC_RESULT (ic), ic, TRUE);
1555 DEBUGpic14_AopType (__LINE__, IC_LEFT (ic), NULL, IC_RESULT (ic));
1556 /* if in bit space then a special case */
1557 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1559 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1561 emitpcode (POC_MOVLW, popGet (AOP (IC_LEFT (ic)), 0));
1562 emitpcode (POC_XORWF, popGet (AOP (IC_RESULT (ic)), 0));
1564 else
1566 emitpcode (POC_CLRF, popGet (AOP (IC_RESULT (ic)), 0));
1567 emitpcode (POC_BTFSS, popGet (AOP (IC_LEFT (ic)), 0));
1568 emitpcode (POC_INCF, popGet (AOP (IC_RESULT (ic)), 0));
1570 goto release;
1573 size = AOP_SIZE (IC_LEFT (ic));
1574 mov2w (AOP (IC_LEFT (ic)), 0);
1575 while (--size > 0)
1577 if (op_isLitLike (IC_LEFT (ic)))
1578 emitpcode (POC_IORLW, popGetAddr (AOP (IC_LEFT (ic)), size, 0));
1579 else
1580 emitpcode (POC_IORFW, popGet (AOP (IC_LEFT (ic)), size));
1582 emitpcode (POC_MOVLW, popGetLit (0));
1583 emitSKPNZ;
1584 emitpcode (POC_MOVLW, popGetLit (1));
1585 movwf (AOP (IC_RESULT (ic)), 0);
1587 for (size = 1; size < AOP_SIZE (IC_RESULT (ic)); size++)
1589 emitpcode (POC_CLRF, popGet (AOP (IC_RESULT (ic)), size));
1591 goto release;
1593 release:
1594 /* release the aops */
1595 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1596 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1600 /*-----------------------------------------------------------------*/
1601 /* genCpl - generate code for complement */
1602 /*-----------------------------------------------------------------*/
1603 static void
1604 genCpl (iCode * ic)
1606 operand *left, *result;
1607 int size, offset = 0;
1609 FENTRY;
1611 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
1612 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
1613 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
1615 /* if both are in bit space then
1616 a special case */
1617 if (AOP_TYPE (result) == AOP_CRY && AOP_TYPE (left) == AOP_CRY)
1620 pic14_emitcode ("mov", "c,%s", left->aop->aopu.aop_dir);
1621 pic14_emitcode ("cpl", "c");
1622 pic14_emitcode ("mov", "%s,c", result->aop->aopu.aop_dir);
1623 goto release;
1626 size = AOP_SIZE (result);
1627 if (AOP_SIZE (left) < size)
1628 size = AOP_SIZE (left);
1629 while (size--)
1631 emitpcode (POC_COMFW, popGet (AOP (left), offset));
1632 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
1633 offset++;
1635 addSign (result, AOP_SIZE (left), !SPEC_USIGN (operandType (result)));
1638 release:
1639 /* release the aops */
1640 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1641 freeAsmop (result, NULL, ic, TRUE);
1644 /*-----------------------------------------------------------------*/
1645 /* genUminusFloat - unary minus for floating points */
1646 /*-----------------------------------------------------------------*/
1647 static void
1648 genUminusFloat (operand * op, operand * result)
1650 int size;
1652 FENTRY;
1654 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
1655 /* for this we just need to flip the
1656 first it then copy the rest in place */
1657 size = AOP_SIZE (op) - 1;
1659 mov2w_op (op, size);
1660 emitpcode (POC_XORLW, popGetLit (0x80));
1661 movwf (AOP (result), size);
1663 while (size--)
1665 mov2w_op (op, size);
1666 movwf (AOP (result), size);
1667 } // while
1670 /*-----------------------------------------------------------------*/
1671 /* genUminus - unary minus code generation */
1672 /*-----------------------------------------------------------------*/
1673 static void
1674 genUminus (iCode * ic)
1676 int size, i;
1677 sym_link *optype;
1679 FENTRY;
1681 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
1682 /* assign asmops */
1683 aopOp (IC_LEFT (ic), ic, FALSE);
1684 aopOp (IC_RESULT (ic), ic, TRUE);
1686 /* if both in bit space then special
1687 case */
1688 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY && AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1691 emitpcode (POC_BCF, popGet (AOP (IC_RESULT (ic)), 0));
1692 emitpcode (POC_BTFSS, popGet (AOP (IC_LEFT (ic)), 0));
1693 emitpcode (POC_BSF, popGet (AOP (IC_RESULT (ic)), 0));
1695 goto release;
1698 optype = operandType (IC_LEFT (ic));
1700 /* if float then do float stuff */
1701 if (IS_FLOAT (optype))
1703 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1704 goto release;
1707 /* otherwise subtract from zero by taking the 2's complement */
1708 size = AOP_SIZE (IC_LEFT (ic));
1710 for (i = 0; i < size; i++)
1712 if (pic14_sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1713 emitpcode (POC_COMF, popGet (AOP (IC_LEFT (ic)), i));
1714 else
1716 emitpcode (POC_COMFW, popGet (AOP (IC_LEFT (ic)), i));
1717 emitpcode (POC_MOVWF, popGet (AOP (IC_RESULT (ic)), i));
1721 emitpcode (POC_INCF, popGet (AOP (IC_RESULT (ic)), 0));
1722 for (i = 1; i < size; i++)
1724 emitSKPNZ;
1725 emitpcode (POC_INCF, popGet (AOP (IC_RESULT (ic)), i));
1728 release:
1729 /* release the aops */
1730 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1731 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1734 /*-----------------------------------------------------------------*/
1735 /* saverbank - saves an entire register bank on the stack */
1736 /*-----------------------------------------------------------------*/
1737 static void
1738 saverbank (int bank, iCode * ic, bool pushPsw)
1740 FENTRY;
1742 DEBUGpic14_emitcode ("; ***", "%s %d - WARNING no code generated", __FUNCTION__, __LINE__);
1743 #if 0
1744 int i;
1745 asmop *aop;
1746 regs *r = NULL;
1748 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
1749 if (options.useXstack)
1752 aop = newAsmop (0);
1753 r = getFreePtr (ic, &aop, FALSE);
1754 pic14_emitcode ("mov", "%s,_spx", r->name);
1758 for (i = 0; i < pic14_nRegs; i++)
1760 if (options.useXstack)
1762 pic14_emitcode ("inc", "%s", r->name);
1763 //pic14_emitcode("mov","a,(%s+%d)",
1764 // regspic14[i].base,8*bank+regspic14[i].offset);
1765 pic14_emitcode ("movx", "@%s,a", r->name);
1767 else
1768 pic14_emitcode ("push", ""); // "(%s+%d)",
1769 //regspic14[i].base,8*bank+regspic14[i].offset);
1772 if (pushPsw)
1774 if (options.useXstack)
1776 pic14_emitcode ("mov", "a,psw");
1777 pic14_emitcode ("movx", "@%s,a", r->name);
1778 pic14_emitcode ("inc", "%s", r->name);
1779 pic14_emitcode ("mov", "_spx,%s", r->name);
1780 freeAsmop (NULL, aop, ic, TRUE);
1783 else
1784 pic14_emitcode ("push", "psw");
1786 pic14_emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1788 ic->bankSaved = 1;
1789 #endif
1792 /*-----------------------------------------------------------------*/
1793 /* saveRegisters - will look for a call and save the registers */
1794 /*-----------------------------------------------------------------*/
1795 static void
1796 saveRegisters (iCode * lic)
1798 #if 0
1799 iCode *ic;
1800 sym_link *dtype;
1802 FENTRY;
1804 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
1806 /* look for call */
1807 for (ic = lic; ic; ic = ic->next)
1808 if (ic->op == CALL || ic->op == PCALL)
1809 break;
1811 if (!ic)
1813 fprintf (stderr, "found parameter push with no function call\n");
1814 return;
1817 /* if the registers have been saved already then do nothing */
1818 if (ic->regsSaved || IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type))
1819 return;
1821 /* find the registers in use at this time
1822 and push them away to safety */
1823 bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
1825 ic->regsSaved = 1;
1827 //fprintf(stderr, "ERROR: saveRegisters did not do anything to save registers, please report this as a bug.\n");
1829 dtype = operandType (IC_LEFT (ic));
1830 if (currFunc && dtype &&
1831 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) && IFFUNC_ISISR (currFunc->type) && !ic->bankSaved)
1833 saverbank (FUNC_REGBANK (dtype), ic, TRUE);
1835 #endif
1838 /*-----------------------------------------------------------------*/
1839 /* unsaveRegisters - pop the pushed registers */
1840 /*-----------------------------------------------------------------*/
1841 static void
1842 unsaveRegisters (iCode * ic)
1844 #if 0
1845 int i;
1846 bitVect *rsave;
1848 FENTRY;
1850 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
1851 /* find the registers in use at this time
1852 and push them away to safety */
1853 rsave = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
1855 if (options.useXstack)
1857 pic14_emitcode ("mov", "r0,%s", spname);
1858 for (i = pic14_nRegs; i >= 0; i--)
1860 if (bitVectBitValue (rsave, i))
1862 pic14_emitcode ("dec", "r0");
1863 pic14_emitcode ("movx", "a,@r0");
1864 pic14_emitcode ("mov", "%s,a", pic14_regWithIdx (i)->name);
1868 pic14_emitcode ("mov", "%s,r0", spname);
1869 } //else
1870 //for (i = pic14_nRegs ; i >= 0 ; i--) {
1871 // if (bitVectBitValue(rsave,i))
1872 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1875 #endif
1879 /*-----------------------------------------------------------------*/
1880 /* pushSide - */
1881 /*-----------------------------------------------------------------*/
1882 static void
1883 pushSide (operand * oper, int size)
1885 #if 0
1886 int offset = 0;
1887 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
1888 while (size--)
1890 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1891 if (AOP_TYPE (oper) != AOP_REG && AOP_TYPE (oper) != AOP_DIR && strcmp (l, "a"))
1893 pic14_emitcode ("mov", "a,%s", l);
1894 pic14_emitcode ("push", "acc");
1896 else
1897 pic14_emitcode ("push", "%s", l);
1899 #endif
1902 /*-----------------------------------------------------------------*/
1903 /* assignResultValue - */
1904 /*-----------------------------------------------------------------*/
1905 static void
1906 assignResultValue (iCode *ic)
1908 operand * oper = IC_RESULT(ic);
1909 int size = AOP_SIZE (oper);
1910 int offset = 0;
1912 /* _mul{s,su,us,u}char and _div{s,su}char return int, but some iCodes
1913 * assign it to a char-sized iTemp
1915 if (ic->op == CALL)
1917 /* the function type */
1918 sym_link *ftype = operandType (IC_LEFT (ic));
1919 /* the size of the return value */
1920 int rsize = getSize (ftype->next);
1921 assert(rsize > 0 && rsize <= 4);
1922 if (rsize > size)
1924 offset += rsize - size;
1925 DEBUGpic14_emitcode ("; ***", "%s %d ret-size=%d op-size=%d offset=%d", __FUNCTION__, __LINE__, rsize,size,offset);
1929 FENTRY;
1931 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
1933 DEBUGpic14_AopType (__LINE__, oper, NULL, NULL);
1935 /* assign MSB first (passed via WREG) */
1936 while (size--)
1938 get_returnvalue (oper, size, offset + GpseudoStkPtr);
1939 GpseudoStkPtr++;
1944 /*-----------------------------------------------------------------*/
1945 /* genIpush - genrate code for pushing this gets a little complex */
1946 /*-----------------------------------------------------------------*/
1947 static void
1948 genIpush (iCode * ic)
1950 FENTRY;
1952 DEBUGpic14_emitcode ("; ***", "%s %d - WARNING no code generated", __FUNCTION__, __LINE__);
1953 #if 0
1954 int size, offset = 0;
1955 char *l;
1958 /* if this is not a parm push : ie. it is spill push
1959 and spill push is always done on the local stack */
1960 if (!ic->parmPush)
1963 /* and the item is spilt then do nothing */
1964 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1965 return;
1967 aopOp (IC_LEFT (ic), ic, FALSE);
1968 size = AOP_SIZE (IC_LEFT (ic));
1969 /* push it on the stack */
1970 while (size--)
1972 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1973 if (*l == '#')
1975 MOVA (l);
1976 l = "acc";
1978 pic14_emitcode ("push", "%s", l);
1980 return;
1983 /* this is a parameter push: in this case we call
1984 the routine to find the call and save those
1985 registers that need to be saved */
1986 saveRegisters (ic);
1988 /* then do the push */
1989 aopOp (IC_LEFT (ic), ic, FALSE);
1992 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1993 size = AOP_SIZE (IC_LEFT (ic));
1995 while (size--)
1997 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1998 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG && AOP_TYPE (IC_LEFT (ic)) != AOP_DIR && strcmp (l, "a"))
2000 pic14_emitcode ("mov", "a,%s", l);
2001 pic14_emitcode ("push", "acc");
2003 else
2004 pic14_emitcode ("push", "%s", l);
2007 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2008 #endif
2011 /*-----------------------------------------------------------------*/
2012 /* genIpop - recover the registers: can happen only for spilling */
2013 /*-----------------------------------------------------------------*/
2014 static void
2015 genIpop (iCode * ic)
2017 FENTRY;
2019 DEBUGpic14_emitcode ("; ***", "%s %d - WARNING no code generated", __FUNCTION__, __LINE__);
2020 assert (!"genIpop -- unimplemented");
2021 #if 0
2022 int size, offset;
2025 /* if the temp was not pushed then */
2026 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2027 return;
2029 aopOp (IC_LEFT (ic), ic, FALSE);
2030 size = AOP_SIZE (IC_LEFT (ic));
2031 offset = (size - 1);
2032 while (size--)
2033 pic14_emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--, FALSE, TRUE));
2035 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2036 #endif
2039 /*-----------------------------------------------------------------*/
2040 /* unsaverbank - restores the resgister bank from stack */
2041 /*-----------------------------------------------------------------*/
2042 static void
2043 unsaverbank (int bank, iCode * ic, bool popPsw)
2045 FENTRY;
2047 DEBUGpic14_emitcode ("; ***", "%s %d - WARNING no code generated", __FUNCTION__, __LINE__);
2048 #if 0
2049 int i;
2050 asmop *aop;
2051 regs *r = NULL;
2053 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
2054 if (popPsw)
2056 if (options.useXstack)
2058 aop = newAsmop (0);
2059 r = getFreePtr (ic, &aop, FALSE);
2062 pic14_emitcode ("mov", "%s,_spx", r->name);
2063 pic14_emitcode ("movx", "a,@%s", r->name);
2064 pic14_emitcode ("mov", "psw,a");
2065 pic14_emitcode ("dec", "%s", r->name);
2068 else
2069 pic14_emitcode ("pop", "psw");
2072 for (i = (pic14_nRegs - 1); i >= 0; i--)
2074 if (options.useXstack)
2076 pic14_emitcode ("movx", "a,@%s", r->name);
2077 //pic14_emitcode("mov","(%s+%d),a",
2078 // regspic14[i].base,8*bank+regspic14[i].offset);
2079 pic14_emitcode ("dec", "%s", r->name);
2082 else
2083 pic14_emitcode ("pop", ""); //"(%s+%d)",
2084 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2087 if (options.useXstack)
2090 pic14_emitcode ("mov", "_spx,%s", r->name);
2091 freeAsmop (NULL, aop, ic, TRUE);
2094 #endif
2097 /*-----------------------------------------------------------------*/
2098 /* genCall - generates a call statement */
2099 /*-----------------------------------------------------------------*/
2100 static void
2101 genCall (iCode * ic)
2103 sym_link *dtype, *etype;
2104 symbol *sym;
2105 char *name, buf[20];
2106 int isExtern;
2108 FENTRY;
2110 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
2112 /* if caller saves & we have not saved then */
2113 if (!ic->regsSaved)
2114 saveRegisters (ic);
2116 /* if we are calling a function that is not using
2117 the same register bank then we need to save the
2118 destination registers on the stack */
2119 dtype = operandType (IC_LEFT (ic));
2120 etype = getSpec(dtype);
2121 if (currFunc && dtype &&
2122 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) && IFFUNC_ISISR (currFunc->type) && !ic->bankSaved)
2124 saverbank (FUNC_REGBANK (dtype), ic, TRUE);
2126 /* if send set is not empty the assign */
2127 if (_G.sendSet)
2129 iCode *sic;
2130 /* For the Pic port, there is no data stack.
2131 * So parameters passed to functions are stored
2132 * in registers. (The pCode optimizer will get
2133 * rid of most of these :).
2135 int pseudoStkPtr = -1;
2136 int firstTimeThruLoop = 1;
2138 _G.sendSet = reverseSet (_G.sendSet);
2140 /* First figure how many parameters are getting passed */
2141 for (sic = setFirstItem (_G.sendSet); sic; sic = setNextItem (_G.sendSet))
2144 aopOp (IC_LEFT (sic), sic, FALSE);
2145 pseudoStkPtr += AOP_SIZE (IC_LEFT (sic));
2146 freeAsmop (IC_LEFT (sic), NULL, sic, FALSE);
2149 for (sic = setFirstItem (_G.sendSet); sic; sic = setNextItem (_G.sendSet))
2151 int size, offset = 0;
2153 aopOp (IC_LEFT (sic), sic, FALSE);
2154 size = AOP_SIZE (IC_LEFT (sic));
2156 while (size--)
2158 DEBUGpic14_emitcode ("; ", "%d left %s", __LINE__, AopType (AOP_TYPE (IC_LEFT (sic))));
2160 if (!firstTimeThruLoop)
2162 /* If this is not the first time we've been through the loop
2163 * then we need to save the parameter in a temporary
2164 * register. The last byte of the last parameter is
2165 * passed in W. */
2166 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - --pseudoStkPtr));
2169 firstTimeThruLoop = 0;
2171 mov2w_op (IC_LEFT (sic), offset);
2172 offset++;
2174 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2176 _G.sendSet = NULL;
2178 /* make the call */
2179 if (IS_LITERAL(etype))
2181 SNPRINTF(buf,sizeof(buf),"0x%04X", (unsigned)ulFromVal(OP_VALUE(IC_LEFT(ic))));
2182 name = buf;
2183 isExtern = 1;
2185 else
2187 sym = OP_SYMBOL (IC_LEFT (ic));
2188 name = sym->rname[0] ? sym->rname : sym->name;
2190 * As SDCC emits code as soon as it reaches the end of each
2191 * function's definition, prototyped functions that are implemented
2192 * after the current one are always considered EXTERN, which
2193 * introduces many unnecessary PAGESEL instructions.
2194 * XXX: Use a post pass to iterate over all `CALL _name' statements
2195 * and insert `PAGESEL _name' and `PAGESEL $' around the CALL
2196 * only iff there is no definition of the function in the whole
2197 * file (might include this in the PAGESEL pass).
2199 isExtern = IS_EXTERN (sym->etype) || pic14_inISR;
2201 #if 0
2202 if (isExtern)
2204 /* Extern functions and ISRs maybe on a different page;
2205 * must call pagesel */
2206 #endif
2207 emitpcode (POC_PAGESEL, popGetWithString (name, 1));
2208 #if 0
2210 #endif
2212 if (!strcmp(name, "___memcpy"))
2213 emitpcode (POC_CALL, popGetExternal (name, 0));
2214 else
2215 emitpcode (POC_CALL, popGetWithString (name, isExtern));
2216 #if 0
2217 if (isExtern)
2219 /* May have returned from a different page;
2220 * must use pagesel to restore PCLATH before next
2221 * goto or call instruction */
2222 #endif
2223 emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
2224 #if 0
2226 #endif
2227 GpseudoStkPtr = 0;
2228 /* if we need assign a result value */
2229 if ((IS_ITEMP (IC_RESULT (ic)) &&
2230 (OP_SYMBOL (IC_RESULT (ic))->nRegs || OP_SYMBOL (IC_RESULT (ic))->spildir)) || IS_TRUE_SYMOP (IC_RESULT (ic)))
2232 _G.accInUse++;
2233 aopOp (IC_RESULT (ic), ic, FALSE);
2234 _G.accInUse--;
2236 assignResultValue (ic);
2238 DEBUGpic14_emitcode ("; ", "%d left %s", __LINE__, AopType (AOP_TYPE (IC_RESULT (ic))));
2240 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2243 /* if register bank was saved then pop them */
2244 if (ic->bankSaved)
2245 unsaverbank (FUNC_REGBANK (dtype), ic, TRUE);
2247 /* if we hade saved some registers then unsave them */
2248 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
2249 unsaveRegisters (ic);
2252 /*-----------------------------------------------------------------*/
2253 /* genPcall - generates a call by pointer statement */
2254 /*-----------------------------------------------------------------*/
2255 static void
2256 genPcall (iCode * ic)
2258 sym_link *dtype;
2259 symbol *albl = newiTempLabel (NULL);
2260 symbol *blbl = newiTempLabel (NULL);
2261 PIC_OPCODE poc;
2262 pCodeOp *pcop;
2263 operand *left;
2265 FENTRY;
2267 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
2268 /* if caller saves & we have not saved then */
2269 if (!ic->regsSaved)
2270 saveRegisters (ic);
2272 /* if we are calling a function that is not using
2273 the same register bank then we need to save the
2274 destination registers on the stack */
2275 dtype = operandType (IC_LEFT (ic));
2276 if (currFunc && dtype && IFFUNC_ISISR (currFunc->type) && (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)))
2277 saverbank (FUNC_REGBANK (dtype), ic, TRUE);
2279 left = IC_LEFT (ic);
2280 aopOp (left, ic, FALSE);
2281 DEBUGpic14_AopType (__LINE__, left, NULL, NULL);
2283 poc = (op_isLitLike (IC_LEFT (ic)) ? POC_MOVLW : POC_MOVFW);
2285 pushSide (IC_LEFT (ic), FARPTRSIZE);
2287 /* if send set is not empty, assign parameters */
2288 if (_G.sendSet)
2290 DEBUGpic14_emitcode ("; ***", "%s %d - WARNING arg-passing to indirect call not supported", __FUNCTION__, __LINE__);
2291 /* no way to pass args - W always gets used to make the call */
2293 /* first idea - factor out a common helper function and call it.
2294 But don't know how to get it generated only once in its own block
2296 if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2297 char *rname;
2298 char *buffer;
2299 size_t len;
2301 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2302 DEBUGpic14_emitcode ("; ***","%s %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2303 len = strlen(rname) + 16;
2304 buffer = Safe_alloc(len);
2305 SNPRINTF(buffer, len, "%s_goto_helper", rname);
2306 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2307 free(buffer);
2310 emitpcode (POC_CALL, popGetLabel (albl->key));
2311 pcop = popGetLabel (blbl->key);
2312 emitpcode (POC_PAGESEL, pcop); /* Must restore PCLATH before goto, without destroying W */
2313 emitpcode (POC_GOTO, pcop);
2314 emitpLabel (albl->key);
2316 emitpcode (poc, popGetAddr (AOP (left), 1, 0));
2317 emitpcode (POC_MOVWF, popCopyReg (&pc_pclath));
2318 emitpcode (poc, popGetAddr (AOP (left), 0, 0));
2319 emitpcode (POC_MOVWF, popCopyReg (&pc_pcl));
2321 emitpLabel (blbl->key);
2323 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2325 /* if we need to assign a result value */
2326 if ((IS_ITEMP (IC_RESULT (ic)) &&
2327 (OP_SYMBOL (IC_RESULT (ic))->nRegs || OP_SYMBOL (IC_RESULT (ic))->spildir)) || IS_TRUE_SYMOP (IC_RESULT (ic)))
2330 _G.accInUse++;
2331 aopOp (IC_RESULT (ic), ic, FALSE);
2332 _G.accInUse--;
2334 GpseudoStkPtr = 0;
2336 assignResultValue (ic);
2338 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2341 /* if register bank was saved then unsave them */
2342 if (currFunc && dtype && (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)))
2343 unsaverbank (FUNC_REGBANK (dtype), ic, TRUE);
2345 /* if we hade saved some registers then
2346 unsave them */
2347 if (ic->regsSaved)
2348 unsaveRegisters (ic);
2351 /*-----------------------------------------------------------------*/
2352 /* resultRemat - result is rematerializable */
2353 /*-----------------------------------------------------------------*/
2354 static int
2355 resultRemat (iCode * ic)
2357 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2358 FENTRY;
2360 if (SKIP_IC (ic) || ic->op == IFX)
2361 return 0;
2363 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2365 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2366 if (sym->remat && !POINTER_SET (ic))
2367 return 1;
2370 return 0;
2373 /*-----------------------------------------------------------------*/
2374 /* genFunction - generated code for function entry */
2375 /*-----------------------------------------------------------------*/
2376 static void
2377 genFunction (iCode * ic)
2379 symbol *sym;
2380 sym_link *ftype;
2382 FENTRY;
2384 DEBUGpic14_emitcode ("; ***", "%s %d curr label offset=%dprevious max_key=%d ", __FUNCTION__, __LINE__, labelOffset,
2385 max_key);
2387 labelOffset += (max_key + 4);
2388 max_key = 0;
2389 GpseudoStkPtr = 0;
2390 _G.nRegsSaved = 0;
2391 /* create the function header */
2392 pic14_emitcode (";", "-----------------------------------------");
2393 pic14_emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2394 pic14_emitcode (";", "-----------------------------------------");
2396 /* prevent this symbol from being emitted as 'extern' */
2397 pic14_stringInSet (sym->rname, &pic14_localFunctions, 1);
2399 pic14_emitcode ("", "%s:", sym->rname);
2400 addpCode2pBlock (pb, newpCodeFunction (moduleName, sym->rname, !IS_STATIC (sym->etype), IFFUNC_ISISR (sym->type)));
2402 /* mark symbol as NOT extern (even if it was declared so previously) */
2403 assert (IS_SPEC (sym->etype));
2404 SPEC_EXTR (sym->etype) = 0;
2405 sym->cdef = 0;
2406 if (!SPEC_OCLS (sym->etype))
2407 SPEC_OCLS (sym->etype) = code;
2408 addSetIfnotP (&SPEC_OCLS (sym->etype)->syms, sym);
2410 ftype = operandType (IC_LEFT (ic));
2412 /* here we need to generate the equates for the
2413 register bank if required */
2414 #if 0
2415 if (FUNC_REGBANK (ftype) != rbank)
2417 int i;
2419 rbank = FUNC_REGBANK (ftype);
2420 for (i = 0; i < pic14_nRegs; i++)
2422 if (strcmp (regspic14[i].base, "0") == 0)
2423 pic14_emitcode ("", "%s = 0x%02x", regspic14[i].dname, 8 * rbank + regspic14[i].offset);
2424 else
2425 pic14_emitcode ("", "%s = %s + 0x%02x", regspic14[i].dname, regspic14[i].base, 8 * rbank + regspic14[i].offset);
2428 #endif
2430 /* if this is an interrupt service routine */
2431 pic14_inISR = 0;
2432 if (IFFUNC_ISISR (sym->type))
2434 pic14_inISR = 1;
2436 /* generate ISR prolog if and not naked */
2437 if (!IFFUNC_ISNAKED (sym->type))
2439 if (pic->isEnhancedCore)
2442 * Enhanced CPUs have automatic context saving for W,
2443 * STATUS, BSR, FSRx, and PCLATH in shadow registers.
2445 emitpcode (POC_CLRF, popCopyReg (&pc_pclath));
2447 else
2449 emitpcode (POC_MOVWF, popCopyReg (&pc_wsave));
2450 emitpcode (POC_SWAPFW, popCopyReg (&pc_status));
2451 /* XXX: Why? Does this assume that ssave and psave reside
2452 * in a shared bank or bank0? We cannot guarantee the
2453 * latter...
2455 emitpcode (POC_CLRF, popCopyReg (&pc_status));
2456 emitpcode (POC_MOVWF, popCopyReg (&pc_ssave));
2457 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_status",1 ));
2458 emitpcode (POC_MOVFW, popCopyReg (&pc_pclath));
2459 /* during an interrupt PCLATH must be cleared before a goto or call statement */
2460 emitpcode (POC_CLRF, popCopyReg (&pc_pclath));
2461 emitpcode (POC_MOVWF, popCopyReg (&pc_psave));
2462 //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_pclath", 1));
2463 emitpcode (POC_MOVFW, popCopyReg (&pc_fsr));
2464 emitpcode (POC_MOVWF, popGetExternal ("___sdcc_saved_fsr", 1));
2468 pBlockConvert2ISR (pb);
2469 pic14_hasInterrupt = 1;
2471 else
2473 /* if callee-save to be used for this function
2474 then save the registers being used in this function */
2475 if (IFFUNC_CALLEESAVES (sym->type))
2477 int i;
2479 /* if any registers used */
2480 if (sym->regsUsed)
2482 /* save the registers used */
2483 for (i = 0; i < sym->regsUsed->size; i++)
2485 if (bitVectBitValue (sym->regsUsed, i))
2487 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2488 _G.nRegsSaved++;
2495 /* if critical function then turn interrupts off */
2496 if (IFFUNC_ISCRITICAL (ftype))
2498 genCritical (NULL);
2499 if (IFFUNC_ARGS (sym->type))
2501 fprintf (stderr, "PIC14: Functions with __critical (%s) must not have arguments for now.\n", sym->name);
2502 exit (1);
2503 } // if
2504 } // if
2506 /* set the register bank to the desired value */
2507 if (FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2509 pic14_emitcode ("push", "psw");
2510 pic14_emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2513 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2516 if (options.useXstack)
2518 pic14_emitcode ("mov", "r0,%s", spname);
2519 pic14_emitcode ("mov", "a,_bp");
2520 pic14_emitcode ("movx", "@r0,a");
2521 pic14_emitcode ("inc", "%s", spname);
2523 else
2525 /* set up the stack */
2526 pic14_emitcode ("push", "_bp"); /* save the callers stack */
2528 pic14_emitcode ("mov", "_bp,%s", spname);
2531 /* adjust the stack for the function */
2532 if (sym->stack)
2535 int i = sym->stack;
2536 if (i > 256)
2537 werror (W_STACK_OVERFLOW, sym->name);
2539 if (i > 3 && sym->recvSize < 4)
2542 pic14_emitcode ("mov", "a,sp");
2543 pic14_emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2544 pic14_emitcode ("mov", "sp,a");
2547 else
2548 while (i--)
2549 pic14_emitcode ("inc", "sp");
2552 if (sym->xstack)
2555 pic14_emitcode ("mov", "a,_spx");
2556 pic14_emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2557 pic14_emitcode ("mov", "_spx,a");
2562 /*-----------------------------------------------------------------*/
2563 /* genEndFunction - generates epilogue for functions */
2564 /*-----------------------------------------------------------------*/
2565 static void
2566 genEndFunction (iCode * ic)
2568 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2570 FENTRY;
2572 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
2574 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2576 pic14_emitcode ("mov", "%s,_bp", spname);
2579 /* if use external stack but some variables were
2580 added to the local stack then decrement the
2581 local stack */
2582 if (options.useXstack && sym->stack)
2584 pic14_emitcode ("mov", "a,sp");
2585 pic14_emitcode ("add", "a,#0x%02x", ((char) - sym->stack) & 0xff);
2586 pic14_emitcode ("mov", "sp,a");
2590 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2592 if (options.useXstack)
2594 pic14_emitcode ("mov", "r0,%s", spname);
2595 pic14_emitcode ("movx", "a,@r0");
2596 pic14_emitcode ("mov", "_bp,a");
2597 pic14_emitcode ("dec", "%s", spname);
2599 else
2601 pic14_emitcode ("pop", "_bp");
2605 /* restore the register bank */
2606 if (FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2607 pic14_emitcode ("pop", "psw");
2609 /* if critical function then turn interrupts off */
2610 if (IFFUNC_ISCRITICAL (sym->type))
2612 genEndCritical (NULL);
2613 } // if
2615 if (IFFUNC_ISISR (sym->type))
2618 /* now we need to restore the registers */
2619 /* if this isr has no bank i.e. is going to
2620 run with bank 0 , then we need to save more
2621 registers :-) */
2622 if (!FUNC_REGBANK (sym->type))
2625 /* if this function does not call any other
2626 function then we can be economical and
2627 save only those registers that are used */
2628 if (!IFFUNC_HASFCALL (sym->type))
2630 int i;
2632 /* if any registers used */
2633 if (sym->regsUsed)
2635 /* save the registers used */
2636 for (i = sym->regsUsed->size; i >= 0; i--)
2638 if (bitVectBitValue (sym->regsUsed, i))
2640 pic14_emitcode ("pop", "junk"); //"%s",pic14_regWithIdx(i)->dname);
2646 else
2648 /* this function has a function call; cannot
2649 determines register usage so we will have the
2650 entire bank */
2651 unsaverbank (0, ic, FALSE);
2655 /* if debug then send end of function */
2656 if (options.debug && debugFile && currFunc)
2658 debugFile->writeEndFunction (currFunc, ic, 1);
2661 /* generate ISR epilog if not enhanced core and not naked */
2662 if (!pic->isEnhancedCore && !IFFUNC_ISNAKED (sym->type))
2664 emitpcode (POC_MOVFW, popGetExternal ("___sdcc_saved_fsr", 1));
2665 emitpcode (POC_MOVWF, popCopyReg (&pc_fsr));
2666 //emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_pclath", 1));
2667 emitpcode (POC_MOVFW, popCopyReg (&pc_psave));
2668 emitpcode (POC_MOVWF, popCopyReg (&pc_pclath));
2669 emitpcode (POC_CLRF, popCopyReg (&pc_status)); // see genFunction
2670 //emitpcode(POC_SWAPFW, popGetExternal("___sdcc_saved_status", 1));
2671 emitpcode (POC_SWAPFW, popCopyReg (&pc_ssave));
2672 emitpcode (POC_MOVWF, popCopyReg (&pc_status));
2673 emitpcode (POC_SWAPF, popCopyReg (&pc_wsave));
2674 emitpcode (POC_SWAPFW, popCopyReg (&pc_wsave));
2676 addpCode2pBlock (pb, newpCodeLabel ("END_OF_INTERRUPT", -1));
2677 emitpcodeNULLop (POC_RETFIE);
2679 else
2681 if (IFFUNC_ISCRITICAL (sym->type))
2682 pic14_emitcode ("setb", "ea");
2684 if (IFFUNC_CALLEESAVES (sym->type))
2686 int i;
2688 /* if any registers used */
2689 if (sym->regsUsed)
2691 /* save the registers used */
2692 for (i = sym->regsUsed->size; i >= 0; i--)
2694 if (bitVectBitValue (sym->regsUsed, i))
2696 pic14_emitcode ("pop", "junk"); //"%s",pic14_regWithIdx(i)->dname);
2702 /* if debug then send end of function */
2703 if (options.debug && debugFile && currFunc)
2705 debugFile->writeEndFunction (currFunc, ic, 1);
2708 pic14_emitcode ("return", "");
2709 emitpcodeNULLop (POC_RETURN);
2711 /* Mark the end of a function */
2712 addpCode2pBlock (pb, newpCodeFunction (moduleName, NULL, 0, 0));
2717 /*-----------------------------------------------------------------*/
2718 /* genRet - generate code for return statement */
2719 /*-----------------------------------------------------------------*/
2720 static void
2721 genRet (iCode * ic)
2723 int size, offset = 0;
2725 FENTRY;
2727 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
2728 /* if we have no return value then
2729 just generate the "ret" */
2730 if (!IC_LEFT (ic))
2731 goto jumpret;
2733 /* we have something to return then
2734 move the return value into place */
2735 aopOp (IC_LEFT (ic), ic, FALSE);
2736 size = AOP_SIZE (IC_LEFT (ic));
2738 for (offset = 0; offset < size; offset++)
2740 pass_argument (IC_LEFT (ic), offset, size - 1 - offset);
2743 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2745 jumpret:
2746 /* generate a jump to the return label
2747 if the next is not the return statement */
2748 if (!(ic->next && ic->next->op == LABEL && IC_LABEL (ic->next) == returnLabel))
2751 emitpcode (POC_GOTO, popGetLabel (returnLabel->key));
2756 static set *critical_temps = NULL;
2758 static void
2759 genCritical (iCode * ic)
2761 pCodeOp *saved_intcon;
2763 (void) ic;
2765 if (!critical_temps)
2766 critical_temps = newSet ();
2768 saved_intcon = popGetTempReg ();
2769 addSetHead (&critical_temps, saved_intcon);
2771 /* This order saves one BANKSEL back to INTCON. */
2772 emitpcode (POC_MOVFW, popCopyReg (&pc_intcon));
2773 emitpcode (POC_BCF, popCopyGPR2Bit (popCopyReg (&pc_intcon), 7));
2774 emitpcode (POC_MOVWF, pCodeOpCopy (saved_intcon));
2777 static void
2778 genEndCritical (iCode * ic)
2780 pCodeOp *saved_intcon = NULL;
2782 (void) ic;
2784 saved_intcon = getSet (&critical_temps);
2785 if (!saved_intcon)
2787 fprintf (stderr, "Critical section left, but none entered -- ignoring for now.\n");
2788 return;
2789 } // if
2791 emitpcode (POC_BTFSC, popCopyGPR2Bit (pCodeOpCopy (saved_intcon), 7));
2792 emitpcode (POC_BSF, popCopyGPR2Bit (popCopyReg (&pc_intcon), 7));
2793 popReleaseTempReg (saved_intcon);
2796 /*-----------------------------------------------------------------*/
2797 /* genLabel - generates a label */
2798 /*-----------------------------------------------------------------*/
2799 static void
2800 genLabel (iCode * ic)
2802 FENTRY;
2804 /* special case never generate */
2805 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
2806 if (IC_LABEL (ic) == entryLabel)
2807 return;
2809 emitpLabel (IC_LABEL (ic)->key);
2810 pic14_emitcode ("", "_%05d_DS_:", labelKey2num (IC_LABEL (ic)->key + labelOffset));
2813 /*-----------------------------------------------------------------*/
2814 /* genGoto - generates a goto */
2815 /*-----------------------------------------------------------------*/
2816 //tsd
2817 static void
2818 genGoto (iCode * ic)
2820 FENTRY;
2822 emitpcode (POC_GOTO, popGetLabel (IC_LABEL (ic)->key));
2823 pic14_emitcode ("goto", "_%05d_DS_", labelKey2num (IC_LABEL (ic)->key + labelOffset));
2827 /*-----------------------------------------------------------------*/
2828 /* genMultbits :- multiplication of bits */
2829 /*-----------------------------------------------------------------*/
2830 static void
2831 genMultbits (operand * left, operand * right, operand * result)
2833 FENTRY;
2834 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
2836 if (!pic14_sameRegs (AOP (result), AOP (right)))
2837 emitpcode (POC_BSF, popGet (AOP (result), 0));
2839 emitpcode (POC_BTFSC, popGet (AOP (right), 0));
2840 emitpcode (POC_BTFSS, popGet (AOP (left), 0));
2841 emitpcode (POC_BCF, popGet (AOP (result), 0));
2846 /*-----------------------------------------------------------------*/
2847 /* genMultOneByte : 8 bit multiplication & division */
2848 /*-----------------------------------------------------------------*/
2849 static void
2850 genMultOneByte (operand * left, operand * right, operand * result)
2852 char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
2854 // symbol *lbl ;
2855 int size, offset, i;
2858 FENTRY;
2860 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
2861 DEBUGpic14_AopType (__LINE__, left, right, result);
2862 DEBUGpic14_AopTypeSign (__LINE__, left, right, result);
2864 /* (if two literals, the value is computed before) */
2865 /* if one literal, literal on the right */
2866 if (AOP_TYPE (left) == AOP_LIT)
2868 operand *t = right;
2869 right = left;
2870 left = t;
2873 assert (AOP_SIZE (left) == AOP_SIZE (right));
2875 size = min (AOP_SIZE (result), AOP_SIZE (left));
2876 offset = Gstack_base_addr - (2 * size - 1);
2878 /* pass right operand as argument */
2879 for (i = 0; i < size; i++)
2881 mov2w (AOP (right), i);
2882 emitpcode (POC_MOVWF, popRegFromIdx (++offset));
2883 } // for
2885 /* pass left operand as argument */
2886 for (i = 0; i < size; i++)
2888 mov2w (AOP (left), i);
2889 if (i != size - 1)
2890 emitpcode (POC_MOVWF, popRegFromIdx (++offset));
2891 } // for
2892 assert (offset == Gstack_base_addr);
2894 /* call library routine */
2895 assert (size > 0 && size <= 4);
2896 call_libraryfunc (func[size]);
2898 /* assign result */
2899 movwf (AOP (result), size - 1);
2900 for (i = 0; i < size - 1; i++)
2902 emitpcode (POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
2903 movwf (AOP (result), size - 2 - i);
2904 } // for
2906 /* now (zero-/sign) extend the result to its size */
2907 addSign (result, AOP_SIZE (left), !SPEC_USIGN (operandType (result)));
2910 /*-----------------------------------------------------------------*/
2911 /* genMult - generates code for multiplication */
2912 /*-----------------------------------------------------------------*/
2913 static void
2914 genMult (iCode * ic)
2916 operand *left = IC_LEFT (ic);
2917 operand *right = IC_RIGHT (ic);
2918 operand *result = IC_RESULT (ic);
2920 FENTRY;
2922 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
2923 /* assign the amsops */
2924 aopOp (left, ic, FALSE);
2925 aopOp (right, ic, FALSE);
2926 aopOp (result, ic, TRUE);
2928 DEBUGpic14_AopType (__LINE__, left, right, result);
2930 /* special cases first */
2931 /* both are bits */
2932 if (AOP_TYPE (left) == AOP_CRY && AOP_TYPE (right) == AOP_CRY)
2934 genMultbits (left, right, result);
2935 goto release;
2938 /* if both are of size == 1 */
2939 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
2941 genMultOneByte (left, right, result);
2942 goto release;
2945 /* should have been converted to function call */
2946 assert (0);
2948 release:
2949 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2950 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2951 freeAsmop (result, NULL, ic, TRUE);
2954 /*-----------------------------------------------------------------*/
2955 /* genDivbits :- division of bits */
2956 /*-----------------------------------------------------------------*/
2957 static void
2958 genDivbits (operand * left, operand * right, operand * result)
2961 char *l;
2963 FENTRY;
2965 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
2966 /* the result must be bit */
2967 pic14_emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
2968 l = aopGet (AOP (left), 0, FALSE, FALSE);
2970 MOVA (l);
2972 pic14_emitcode ("div", "ab");
2973 pic14_emitcode ("rrc", "a");
2974 aopPut (AOP (result), "c", 0);
2977 /*-----------------------------------------------------------------*/
2978 /* genDivOneByte : 8 bit division */
2979 /*-----------------------------------------------------------------*/
2980 static void
2981 genDivOneByte (operand * left, operand * right, operand * result)
2983 int sign;
2985 FENTRY;
2986 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
2988 assert (AOP_SIZE (right) == 1);
2989 assert (AOP_SIZE (left) == 1);
2991 sign = !(SPEC_USIGN (operandType (left)) && SPEC_USIGN (operandType (right)));
2993 if (AOP_TYPE (right) == AOP_LIT)
2995 /* XXX: might add specialized code */
2998 if (!sign)
3000 /* unsigned division */
3001 #if 1
3002 mov2w (AOP (right), 0);
3003 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr));
3004 mov2w (AOP (left), 0);
3005 call_libraryfunc ("__divuchar");
3006 movwf (AOP (result), 0);
3007 #else
3008 pCodeOp *temp;
3009 symbol *lbl;
3011 temp = popGetTempReg ();
3012 lbl = newiTempLabel (NULL);
3014 /* XXX: improve this naive approach:
3015 [result] = [a] / [b]
3016 ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3018 In PIC assembler:
3019 movf left,W
3020 movwf temp // temp <-- left
3021 movf right,W // W <-- right
3022 clrf result
3023 label1:
3024 incf result
3025 subwf temp,F // temp <-- temp - W
3026 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
3027 goto label1
3028 decf result // we just subtract once too often
3031 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3032 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3034 mov2w (AOP (left), 0);
3035 emitpcode (POC_MOVWF, temp);
3036 mov2w (AOP (right), 0);
3037 emitpcode (POC_CLRF, popGet (AOP (result), 0));
3039 emitpLabel (lbl->key);
3040 emitpcode (POC_INCF, popGet (AOP (result), 0));
3041 emitpcode (POC_SUBWF, temp);
3042 emitSKPNC;
3044 if (pic->isEnhancedCore)
3046 emitpcode (POC_BRA, popGetLabel (lbl->key));
3048 else
3050 emitpcode (POC_GOTO, popGetLabel (lbl->key));
3053 emitpcode (POC_DECF, popGet (AOP (result), 0));
3054 popReleaseTempReg (temp);
3055 #endif
3057 else
3059 /* signed division */
3060 mov2w (AOP (right), 0);
3061 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr));
3062 mov2w (AOP (left), 0);
3063 call_libraryfunc ("__divschar");
3064 movwf (AOP (result), 0);
3067 /* now performed the signed/unsigned division -- extend result */
3068 addSign (result, 1, sign);
3071 /*-----------------------------------------------------------------*/
3072 /* genDiv - generates code for division */
3073 /*-----------------------------------------------------------------*/
3074 static void
3075 genDiv (iCode * ic)
3077 operand *left = IC_LEFT (ic);
3078 operand *right = IC_RIGHT (ic);
3079 operand *result = IC_RESULT (ic);
3081 FENTRY;
3082 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
3083 /* assign the amsops */
3084 aopOp (left, ic, FALSE);
3085 aopOp (right, ic, FALSE);
3086 aopOp (result, ic, TRUE);
3088 /* special cases first */
3089 /* both are bits */
3090 if (AOP_TYPE (left) == AOP_CRY && AOP_TYPE (right) == AOP_CRY)
3092 genDivbits (left, right, result);
3093 goto release;
3096 /* if both are of size == 1 */
3097 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3099 genDivOneByte (left, right, result);
3100 goto release;
3103 /* should have been converted to function call */
3104 assert (0);
3105 release:
3106 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3107 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3108 freeAsmop (result, NULL, ic, TRUE);
3111 /*-----------------------------------------------------------------*/
3112 /* genModOneByte : 8 bit modulus */
3113 /*-----------------------------------------------------------------*/
3114 static void
3115 genModOneByte (operand * left, operand * right, operand * result)
3117 int sign;
3119 FENTRY;
3120 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
3122 assert (AOP_SIZE (right) == 1);
3123 assert (AOP_SIZE (left) == 1);
3125 sign = !(SPEC_USIGN (operandType (left)) && SPEC_USIGN (operandType (right)));
3127 if (AOP_TYPE (right) == AOP_LIT)
3129 /* XXX: might add specialized code */
3132 if (!sign)
3134 /* unsigned division */
3135 #if 1
3136 mov2w (AOP (right), 0);
3137 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr));
3138 mov2w (AOP (left), 0);
3139 call_libraryfunc ("__moduchar");
3140 movwf (AOP (result), 0);
3141 #else
3142 pCodeOp *temp;
3143 symbol *lbl;
3145 lbl = newiTempLabel (NULL);
3147 assert (!pic14_sameRegs (AOP (right), AOP (result)));
3149 /* XXX: improve this naive approach:
3150 [result] = [a] % [b]
3151 ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3153 In PIC assembler:
3154 movf left,W
3155 movwf result // result <-- left
3156 movf right,W // W <-- right
3157 label1:
3158 subwf result,F // result <-- result - W
3159 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
3160 goto label1
3161 addwf result, F // we just subtract once too often
3164 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3165 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3167 if (!pic14_sameRegs (AOP (left), AOP (result)))
3169 mov2w (AOP (left), 0);
3170 emitpcode (POC_MOVWF, popGet (AOP (result), 0));
3172 mov2w (AOP (right), 0);
3174 emitpLabel (lbl->key);
3175 emitpcode (POC_SUBWF, popGet (AOP (result), 0));
3176 emitSKPNC;
3178 if (pic->isEnhancedCore)
3180 emitpcode (POC_BRA, popGetLabel (lbl->key));
3182 else
3184 emitpcode (POC_GOTO, popGetLabel (lbl->key));
3187 emitpcode (POC_ADDWF, popGet (AOP (result), 0));
3188 #endif
3190 else
3192 /* signed division */
3193 mov2w (AOP (right), 0);
3194 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr));
3195 mov2w (AOP (left), 0);
3196 call_libraryfunc ("__modschar");
3197 movwf (AOP (result), 0);
3200 /* now we performed the signed/unsigned modulus -- extend result */
3201 addSign (result, 1, sign);
3204 /*-----------------------------------------------------------------*/
3205 /* genMod - generates code for division */
3206 /*-----------------------------------------------------------------*/
3207 static void
3208 genMod (iCode * ic)
3210 operand *left = IC_LEFT (ic);
3211 operand *right = IC_RIGHT (ic);
3212 operand *result = IC_RESULT (ic);
3214 FENTRY;
3215 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
3216 /* assign the amsops */
3217 aopOp (left, ic, FALSE);
3218 aopOp (right, ic, FALSE);
3219 aopOp (result, ic, TRUE);
3221 /* if both are of size == 1 */
3222 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3224 genModOneByte (left, right, result);
3225 goto release;
3228 /* should have been converted to function call */
3229 assert (0);
3231 release:
3232 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3233 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3234 freeAsmop (result, NULL, ic, TRUE);
3237 /*-----------------------------------------------------------------*/
3238 /* genIfxJump :- will create a jump depending on the ifx */
3239 /*-----------------------------------------------------------------*/
3241 note: May need to add parameter to indicate when a variable is in bit space.
3243 static void
3244 genIfxJump (iCode * ic, char *jval)
3247 FENTRY;
3248 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
3249 /* if true label then we jump if condition
3250 supplied is true */
3251 if (IC_TRUE (ic))
3254 if (strcmp (jval, "a") == 0)
3255 emitSKPZ;
3256 else if (strcmp (jval, "c") == 0)
3257 emitSKPC;
3258 else
3260 DEBUGpic14_emitcode ("; ***", "%d - assuming %s is in bit space", __LINE__, jval);
3261 emitpcode (POC_BTFSC, newpCodeOpBit (jval, -1, 1));
3264 emitpcode (POC_GOTO, popGetLabel (IC_TRUE (ic)->key));
3265 pic14_emitcode (" goto", "_%05d_DS_", labelKey2num (IC_TRUE (ic)->key + labelOffset));
3268 else
3270 /* false label is present */
3271 if (strcmp (jval, "a") == 0)
3272 emitSKPNZ;
3273 else if (strcmp (jval, "c") == 0)
3274 emitSKPNC;
3275 else
3277 DEBUGpic14_emitcode ("; ***", "%d - assuming %s is in bit space", __LINE__, jval);
3278 emitpcode (POC_BTFSS, newpCodeOpBit (jval, -1, 1));
3281 emitpcode (POC_GOTO, popGetLabel (IC_FALSE (ic)->key));
3282 pic14_emitcode (" goto", "_%05d_DS_", labelKey2num (IC_FALSE (ic)->key + labelOffset));
3287 /* mark the icode as generated */
3288 ic->generated = TRUE;
3291 /*-----------------------------------------------------------------*/
3292 /* genSkipc */
3293 /*-----------------------------------------------------------------*/
3294 static void
3295 genSkipc (resolvedIfx * rifx)
3297 FENTRY;
3298 if (!rifx)
3299 return;
3301 if (rifx->condition)
3302 emitSKPNC;
3303 else
3304 emitSKPC;
3306 emitpcode (POC_GOTO, popGetLabel (rifx->lbl->key));
3307 emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3308 rifx->generated = TRUE;
3311 #define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3312 #define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT)
3313 #define DEBUGpc emitpComment
3315 /*-----------------------------------------------------------------*/
3316 /* mov2w_regOrLit :- move to WREG either the offset's byte from */
3317 /* aop (if it's NOT a literal) or from lit (if */
3318 /* aop is a literal) */
3319 /*-----------------------------------------------------------------*/
3320 static void
3321 pic14_mov2w_regOrLit (asmop * aop, unsigned long lit, int offset)
3323 if (aop->type == AOP_LIT)
3325 emitpcode (POC_MOVLW, popGetLit ((lit >> (offset * 8)) & 0x00FF));
3327 else
3329 emitpcode (POC_MOVFW, popGet (aop, offset));
3333 /* genCmp performs a left < right comparison, stores
3334 * the outcome in result (if != NULL) and generates
3335 * control flow code for the ifx (if != NULL).
3337 * This version leaves in sequences like
3338 * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3339 * which should be optimized by the peephole
3340 * optimizer - RN 2005-01-01 */
3341 static void
3342 genCmp (operand * left, operand * right, operand * result, iCode * ifx, int sign)
3344 resolvedIfx rIfx;
3345 int size;
3346 int offs;
3347 symbol *templbl;
3348 operand *dummy;
3349 unsigned long lit;
3350 unsigned long mask;
3351 int performedLt;
3352 int invert_result = 0;
3354 FENTRY;
3356 assert (AOP_SIZE (left) == AOP_SIZE (right));
3357 assert (left && right);
3359 size = AOP_SIZE (right) - 1;
3360 mask = (0x100UL << (size * 8)) - 1;
3361 // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3362 performedLt = 1;
3363 templbl = NULL;
3364 lit = 0;
3366 resolveIfx (&rIfx, ifx);
3368 /**********************************************************************
3369 * handle bits - bit compares are promoted to int compares seemingly! *
3370 **********************************************************************/
3371 #if 0
3372 // THIS IS COMPLETELY UNTESTED!
3373 if (AOP_TYPE (left) == AOP_CRY && AOP_TYPE (right) == AOP_CRY)
3375 pCodeOp *pcleft = pic16_popGet (AOP (left), 0);
3376 pCodeOp *pcright = pic16_popGet (AOP (right), 0);
3377 assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3379 emitSETC;
3380 // 1 < {0,1} is false --> clear C by skipping the next instruction
3381 //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP (left),0), PCORB (pcleft)->bit);
3382 pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP (left), 0));
3383 // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3384 pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet (AOP (right), 0), PCORB (pcright)->bit));
3385 emitCLRC; // only skipped for left=0 && right=1
3387 goto correct_result_in_carry;
3388 } // if
3389 #endif
3391 /*************************************************
3392 * make sure that left is register (or the like) *
3393 *************************************************/
3394 if (!isAOP_REGlike (left))
3396 DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE (left), AOP_TYPE (right));
3397 assert (isAOP_LIT (left));
3398 assert (isAOP_REGlike (right));
3399 // swap left and right
3400 // left < right <==> right > left <==> (right >= left + 1)
3401 lit = ulFromVal (AOP (left)->aopu.aop_lit);
3403 if ((!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)))
3405 // MAXVALUE < right? always false
3406 if (performedLt)
3407 emitCLRC;
3408 else
3409 emitSETC;
3410 goto correct_result_in_carry;
3411 } // if
3413 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3414 // that's why we handled it above.
3415 lit++;
3417 dummy = left;
3418 left = right;
3419 right = dummy;
3421 performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3423 else if (isAOP_LIT (right))
3425 lit = ulFromVal (AOP (right)->aopu.aop_lit);
3426 } // if
3428 assert (isAOP_REGlike (left)); // left must be register or the like
3429 assert (isAOP_REGlike (right) || isAOP_LIT (right)); // right may be register-like or a literal
3431 /*************************************************
3432 * special cases go here *
3433 *************************************************/
3435 if (isAOP_LIT (right))
3437 if (!sign)
3439 // unsigned comparison to a literal
3440 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size + 1);
3441 if (lit == 0)
3443 // unsigned left < 0? always false
3444 if (performedLt)
3445 emitCLRC;
3446 else
3447 emitSETC;
3448 goto correct_result_in_carry;
3451 else
3453 // signed comparison to a literal
3454 DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size + 1,
3455 mask);
3456 if ((lit & mask) == ((0x80 << (size * 8)) & mask))
3458 // signed left < 0x80000000? always false
3459 if (performedLt)
3460 emitCLRC;
3461 else
3462 emitSETC;
3463 goto correct_result_in_carry;
3465 else if (lit == 0)
3467 // compare left < 0; set CARRY if SIGNBIT(left) is set
3468 if (performedLt)
3469 emitSETC;
3470 else
3471 emitCLRC;
3472 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP (left), size, FALSE, FALSE), 7, 0));
3473 if (performedLt)
3474 emitCLRC;
3475 else
3476 emitSETC;
3477 goto correct_result_in_carry;
3479 } // if (!sign)
3480 } // right is literal
3482 /*************************************************
3483 * perform a general case comparison *
3484 * make sure we get CARRY==1 <==> left >= right *
3485 *************************************************/
3486 // compare most significant bytes
3487 //DEBUGpc ("comparing bytes at offset %d", size);
3488 if (!sign)
3490 // unsigned comparison
3491 pic14_mov2w_regOrLit (AOP (right), lit, size);
3492 emitpcode (POC_SUBFW, popGet (AOP (left), size));
3494 else
3496 // signed comparison
3497 // (add 2^n to both operands then perform an unsigned comparison)
3498 if (isAOP_LIT (right))
3500 // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3501 unsigned char litbyte = (lit >> (8 * size)) & 0xFF;
3503 if (litbyte == 0x80)
3505 // left >= 0x80 -- always true, but more bytes to come
3506 mov2w (AOP (left), size);
3507 emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3508 emitSETC;
3510 else
3512 // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3513 mov2w (AOP (left), size);
3514 emitpcode (POC_ADDLW, popGetLit (0x80));
3515 emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3516 } // if
3518 else
3520 pCodeOp *pctemp = popGetTempReg ();
3521 mov2w (AOP (left), size);
3522 emitpcode (POC_ADDLW, popGetLit (0x80));
3523 emitpcode (POC_MOVWF, pctemp);
3524 mov2w (AOP (right), size);
3525 emitpcode (POC_ADDLW, popGetLit (0x80));
3526 emitpcode (POC_SUBFW, pctemp);
3527 popReleaseTempReg (pctemp);
3529 } // if (!sign)
3531 // compare remaining bytes (treat as unsigned case from above)
3532 templbl = newiTempLabel (NULL);
3533 offs = size;
3534 while (offs--)
3536 //DEBUGpc ("comparing bytes at offset %d", offs);
3537 emitSKPZ;
3539 if (pic->isEnhancedCore)
3541 emitpcode (POC_BRA, popGetLabel (templbl->key));
3543 else
3545 emitpcode (POC_GOTO, popGetLabel (templbl->key));
3548 pic14_mov2w_regOrLit (AOP (right), lit, offs);
3549 emitpcode (POC_SUBFW, popGet (AOP (left), offs));
3550 } // while (offs)
3551 emitpLabel (templbl->key);
3552 goto result_in_carry;
3554 result_in_carry:
3556 /****************************************************
3557 * now CARRY contains the result of the comparison: *
3558 * SUBWF sets CARRY iff *
3559 * F-W >= 0 <==> F >= W <==> !(F < W) *
3560 * (F=left, W=right) *
3561 ****************************************************/
3563 if (performedLt)
3565 invert_result = 1;
3566 // value will be used in the following genSkipc ()
3567 rIfx.condition ^= TRUE;
3568 } // if
3570 correct_result_in_carry:
3572 // assign result to variable (if necessary), but keep CARRY intact to be used below
3573 if (result && AOP_TYPE (result) != AOP_CRY)
3575 //DEBUGpc ("assign result");
3576 size = AOP_SIZE (result);
3577 while (size--)
3579 emitpcode (POC_CLRF, popGet (AOP (result), size));
3580 } // while
3581 if (invert_result)
3583 emitSKPC;
3584 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP (result), 0, FALSE, FALSE), 0, 0));
3586 else
3588 emitpcode (POC_RLF, popGet (AOP (result), 0));
3589 if (ifx)
3591 /* Result is expected to be in CARRY by genSkipc () below. */
3592 emitpcode (POC_RRFW, popGet (AOP (result), 0));
3593 } // if
3594 } // if
3595 } // if (result)
3597 // perform conditional jump
3598 if (ifx)
3600 //DEBUGpc ("generate control flow");
3601 genSkipc (&rIfx);
3602 ifx->generated = TRUE;
3603 } // if
3606 /*-----------------------------------------------------------------*/
3607 /* genCmpGt :- greater than comparison */
3608 /*-----------------------------------------------------------------*/
3609 static void
3610 genCmpGt (iCode * ic, iCode * ifx)
3612 operand *left, *right, *result;
3613 sym_link *letype, *retype;
3614 int sign;
3616 FENTRY;
3617 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
3618 left = IC_LEFT (ic);
3619 right = IC_RIGHT (ic);
3620 result = IC_RESULT (ic);
3622 sign = 0;
3623 if (IS_SPEC (operandType (left)) && IS_SPEC (operandType (right)))
3625 letype = getSpec (operandType (left));
3626 retype = getSpec (operandType (right));
3627 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3630 /* assign the amsops */
3631 aopOp (left, ic, FALSE);
3632 aopOp (right, ic, FALSE);
3633 aopOp (result, ic, TRUE);
3635 genCmp (right, left, result, ifx, sign);
3637 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3638 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3639 freeAsmop (result, NULL, ic, TRUE);
3642 /*-----------------------------------------------------------------*/
3643 /* genCmpLt - less than comparisons */
3644 /*-----------------------------------------------------------------*/
3645 static void
3646 genCmpLt (iCode * ic, iCode * ifx)
3648 operand *left, *right, *result;
3649 sym_link *letype, *retype;
3650 int sign;
3652 FENTRY;
3653 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
3654 left = IC_LEFT (ic);
3655 right = IC_RIGHT (ic);
3656 result = IC_RESULT (ic);
3658 sign = 0;
3659 if (IS_SPEC (operandType (left)) && IS_SPEC (operandType (right)))
3661 letype = getSpec (operandType (left));
3662 retype = getSpec (operandType (right));
3663 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3666 /* assign the amsops */
3667 aopOp (left, ic, FALSE);
3668 aopOp (right, ic, FALSE);
3669 aopOp (result, ic, TRUE);
3671 genCmp (left, right, result, ifx, sign);
3673 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3674 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3675 freeAsmop (result, NULL, ic, TRUE);
3678 /*-----------------------------------------------------------------*/
3679 /* genCmpEq - generates code for equal to */
3680 /*-----------------------------------------------------------------*/
3681 static void
3682 genCmpEq (iCode * ic, iCode * ifx)
3684 operand *left, *right, *result;
3685 int size;
3686 symbol *false_label = NULL;
3687 symbol *true_label = NULL;
3689 FENTRY;
3690 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
3692 if (ifx)
3693 DEBUGpic14_emitcode ("; ifx is non-null", "");
3694 else
3695 DEBUGpic14_emitcode ("; ifx is null", "");
3697 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3698 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3699 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
3701 DEBUGpic14_AopType (__LINE__, left, right, result);
3703 /* if literal, move literal to right */
3704 if (op_isLitLike (IC_LEFT (ic)))
3706 operand *tmp = right;
3707 right = left;
3708 left = tmp;
3711 if (ifx && !IC_TRUE (ifx))
3713 assert (IC_FALSE (ifx));
3714 false_label = IC_FALSE (ifx);
3717 size = min (AOP_SIZE (left), AOP_SIZE (right));
3718 assert (!pic14_sameRegs (AOP (result), AOP (left)));
3719 assert (!pic14_sameRegs (AOP (result), AOP (right)));
3721 /* assume left != right */
3723 int i;
3724 for (i = 0; i < AOP_SIZE (result); i++)
3726 emitpcode (POC_CLRF, popGet (AOP (result), i));
3730 if (AOP_TYPE (right) == AOP_LIT)
3732 unsigned long lit = ulFromVal (AOP (right)->aopu.aop_lit);
3733 int i;
3734 size = AOP_SIZE (left);
3735 assert (!op_isLitLike (left));
3737 /* special case: generic pointer comparison */
3738 if (IS_GENPTR(operandType(left)) || IS_GENPTR(operandType(right)))
3740 if ((lit & 0xffff) == 0)
3742 /* if left is NULL, both operands are equal */
3743 mov2w (AOP (left), 0);
3744 emitpcode (POC_IORFW, popGet (AOP (left), 1));
3745 /* now Z is set iff `left == right' */
3746 emitSKPNZ;
3747 true_label = newiTempLabel (NULL);
3748 emitpcode (POC_GOTO, popGetLabel (true_label->key));
3752 switch (lit)
3754 case 0:
3755 mov2w (AOP (left), 0);
3756 for (i = 1; i < size; i++)
3757 emitpcode (POC_IORFW, popGet (AOP (left), i));
3758 /* now Z is set iff `left == right' */
3759 emitSKPZ;
3760 if (!false_label)
3761 false_label = newiTempLabel (NULL);
3762 emitpcode (POC_GOTO, popGetLabel (false_label->key));
3763 break;
3765 default:
3766 for (i = 0; i < size; i++)
3768 mov2w (AOP (left), i);
3769 emitpcode (POC_XORLW, popGetLit (lit >> (8 * i)));
3770 /* now Z is cleared if `left != right' */
3771 emitSKPZ;
3772 if (!false_label)
3773 false_label = newiTempLabel (NULL);
3774 emitpcode (POC_GOTO, popGetLabel (false_label->key));
3775 } // for i
3776 break;
3777 } // switch (lit)
3779 else
3781 /* right is no literal */
3782 int i;
3784 /* special case: generic pointer comparison */
3785 if (IS_GENPTR(operandType(left)) || IS_GENPTR(operandType(right)))
3787 /* check if both operands are NULL */
3788 mov2w (AOP (left), 0);
3789 emitpcode (POC_IORFW, popGet (AOP (left), 1));
3790 emitpcode (POC_IORFW, popGet (AOP (right), 0));
3791 emitpcode (POC_IORFW, popGet (AOP (right), 1));
3792 /* now Z is set iff `left == right' */
3793 emitSKPNZ;
3794 true_label = newiTempLabel (NULL);
3795 emitpcode (POC_GOTO, popGetLabel (true_label->key));
3798 for (i = 0; i < size; i++)
3800 mov2w (AOP (right), i);
3801 emitpcode (POC_XORFW, popGet (AOP (left), i));
3802 /* now Z is cleared if `left != right' */
3803 emitSKPZ;
3804 if (!false_label)
3805 false_label = newiTempLabel (NULL);
3806 emitpcode (POC_GOTO, popGetLabel (false_label->key));
3807 } // for i
3810 /* if we reach here, left == right */
3812 if (true_label)
3814 emitpLabel (true_label->key);
3815 true_label = NULL;
3818 if (AOP_SIZE (result) > 0)
3820 emitpcode (POC_INCF, popGet (AOP (result), 0));
3823 if (ifx && IC_TRUE (ifx))
3825 emitpcode (POC_GOTO, popGetLabel (IC_TRUE (ifx)->key));
3828 if (false_label && (!ifx || IC_TRUE (ifx)))
3829 emitpLabel (false_label->key);
3831 if (ifx)
3832 ifx->generated = TRUE;
3834 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3835 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3836 freeAsmop (result, NULL, ic, TRUE);
3839 /*-----------------------------------------------------------------*/
3840 /* genAndOp - for && operation */
3841 /*-----------------------------------------------------------------*/
3842 static void
3843 genAndOp (iCode * ic)
3845 operand *left, *right, *result;
3846 /* symbol *tlbl; */
3848 FENTRY;
3849 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
3850 /* note here that && operations that are in an
3851 if statement are taken away by backPatchLabels
3852 only those used in arthmetic operations remain */
3853 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3854 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3855 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
3857 DEBUGpic14_AopType (__LINE__, left, right, result);
3859 emitpcode (POC_MOVFW, popGet (AOP (left), 0));
3860 emitpcode (POC_ANDFW, popGet (AOP (right), 0));
3861 emitpcode (POC_MOVWF, popGet (AOP (result), 0));
3863 /* if both are bit variables */
3864 /* if (AOP_TYPE(left) == AOP_CRY && */
3865 /* AOP_TYPE(right) == AOP_CRY ) { */
3866 /* pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
3867 /* pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
3868 /* pic14_outBitC(result); */
3869 /* } else { */
3870 /* tlbl = newiTempLabel(NULL); */
3871 /* pic14_toBoolean(left); */
3872 /* pic14_emitcode("jz","%05d_DS_",labelKey2num (tlbl->key)); */
3873 /* pic14_toBoolean(right); */
3874 /* pic14_emitcode("","%05d_DS_:",labelKey2num (tlbl->key)); */
3875 /* pic14_outBitAcc(result); */
3876 /* } */
3878 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3879 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3880 freeAsmop (result, NULL, ic, TRUE);
3884 /*-----------------------------------------------------------------*/
3885 /* genOrOp - for || operation */
3886 /*-----------------------------------------------------------------*/
3888 tsd pic port -
3889 modified this code, but it doesn't appear to ever get called
3892 static void
3893 genOrOp (iCode * ic)
3895 operand *left, *right, *result;
3896 symbol *tlbl;
3897 int i;
3899 /* note here that || operations that are in an
3900 if statement are taken away by backPatchLabels
3901 only those used in arthmetic operations remain */
3902 FENTRY;
3903 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
3904 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3905 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3906 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
3908 DEBUGpic14_AopType (__LINE__, left, right, result);
3910 for (i = 0; i < AOP_SIZE (result); i++)
3912 emitpcode (POC_CLRF, popGet (AOP (result), i));
3913 } // for i
3915 tlbl = newiTempLabel (NULL);
3916 pic14_toBoolean (left);
3917 emitSKPZ;
3918 emitpcode (POC_GOTO, popGetLabel (tlbl->key));
3919 pic14_toBoolean (right);
3920 emitpLabel (tlbl->key);
3921 /* here Z is clear IFF `left || right' */
3922 emitSKPZ;
3923 emitpcode (POC_INCF, popGet (AOP (result), 0));
3925 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3926 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3927 freeAsmop (result, NULL, ic, TRUE);
3930 /*-----------------------------------------------------------------*/
3931 /* isLiteralBit - test if lit == 2^n */
3932 /*-----------------------------------------------------------------*/
3933 static int
3934 isLiteralBit (unsigned long lit)
3936 unsigned long pw[32] = { 1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
3937 0x100L, 0x200L, 0x400L, 0x800L,
3938 0x1000L, 0x2000L, 0x4000L, 0x8000L,
3939 0x10000L, 0x20000L, 0x40000L, 0x80000L,
3940 0x100000L, 0x200000L, 0x400000L, 0x800000L,
3941 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
3942 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L
3944 int idx;
3946 FENTRY;
3947 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
3948 for (idx = 0; idx < 32; idx++)
3949 if (lit == pw[idx])
3950 return idx + 1;
3951 return 0;
3954 /*-----------------------------------------------------------------*/
3955 /* continueIfTrue - */
3956 /*-----------------------------------------------------------------*/
3957 static void
3958 continueIfTrue (iCode * ic)
3960 FENTRY;
3961 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
3962 if (IC_TRUE (ic))
3964 emitpcode (POC_GOTO, popGetLabel (IC_TRUE (ic)->key));
3965 pic14_emitcode ("ljmp", "%05d_DS_", labelKey2num (IC_TRUE (ic)->key));
3967 ic->generated = TRUE;
3970 /*-----------------------------------------------------------------*/
3971 /* jmpIfTrue - */
3972 /*-----------------------------------------------------------------*/
3973 static void
3974 jumpIfTrue (iCode * ic)
3976 FENTRY;
3977 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
3978 if (!IC_TRUE (ic))
3980 emitpcode (POC_GOTO, popGetLabel (IC_TRUE (ic)->key));
3981 pic14_emitcode ("ljmp", "%05d_DS_", labelKey2num (IC_TRUE (ic)->key));
3983 ic->generated = TRUE;
3986 /*-----------------------------------------------------------------*/
3987 /* jmpTrueOrFalse - */
3988 /*-----------------------------------------------------------------*/
3989 static void
3990 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
3992 FENTRY;
3993 // ugly but optimized by peephole
3994 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
3995 if (IC_TRUE (ic))
3997 symbol *nlbl = newiTempLabel (NULL);
3998 pic14_emitcode ("sjmp", "%05d_DS_", labelKey2num (nlbl->key));
3999 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
4000 pic14_emitcode ("ljmp", "%05d_DS_", labelKey2num (IC_TRUE (ic)->key));
4001 pic14_emitcode ("", "%05d_DS_:", labelKey2num (nlbl->key));
4003 else
4005 pic14_emitcode ("ljmp", "%05d_DS_", labelKey2num (IC_FALSE (ic)->key));
4006 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
4008 ic->generated = TRUE;
4011 /*-----------------------------------------------------------------*/
4012 /* genAnd - code for and */
4013 /*-----------------------------------------------------------------*/
4014 static void
4015 genAnd (iCode * ic, iCode * ifx)
4017 operand *left, *right, *result;
4018 int size, offset = 0;
4019 unsigned long lit = 0L;
4020 int bytelit = 0;
4021 resolvedIfx rIfx;
4023 FENTRY;
4024 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
4025 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4026 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4027 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4029 resolveIfx (&rIfx, ifx);
4031 /* if left is a literal & right is not then exchange them */
4032 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) || AOP_NEEDSACC (left))
4034 operand *tmp = right;
4035 right = left;
4036 left = tmp;
4039 /* if result = right then exchange them */
4040 if (pic14_sameRegs (AOP (result), AOP (right)))
4042 operand *tmp = right;
4043 right = left;
4044 left = tmp;
4047 /* if right is bit then exchange them */
4048 if (AOP_TYPE (right) == AOP_CRY && AOP_TYPE (left) != AOP_CRY)
4050 operand *tmp = right;
4051 right = left;
4052 left = tmp;
4054 if (AOP_TYPE (right) == AOP_LIT)
4055 lit = ulFromVal (AOP (right)->aopu.aop_lit);
4057 size = AOP_SIZE (result);
4059 DEBUGpic14_AopType (__LINE__, left, right, result);
4061 // if(bit & yy)
4062 // result = bit & yy;
4063 if (AOP_TYPE (left) == AOP_CRY)
4065 // c = bit & literal;
4066 if (AOP_TYPE (right) == AOP_LIT)
4068 if (lit & 1)
4070 if (size && pic14_sameRegs (AOP (result), AOP (left)))
4071 // no change
4072 goto release;
4073 pic14_emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4075 else
4077 // bit(result) = 0;
4078 if (size && (AOP_TYPE (result) == AOP_CRY))
4080 pic14_emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4081 goto release;
4083 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4085 jumpIfTrue (ifx);
4086 goto release;
4088 pic14_emitcode ("clr", "c");
4091 else
4093 if (AOP_TYPE (right) == AOP_CRY)
4095 // c = bit & bit;
4096 pic14_emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4097 pic14_emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4099 else
4101 // c = bit & val;
4102 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4103 // c = lsb
4104 pic14_emitcode ("rrc", "a");
4105 pic14_emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4108 // bit = c
4109 // val = c
4110 if (size)
4111 pic14_outBitC (result);
4112 // if(bit & ...)
4113 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4114 genIfxJump (ifx, "c");
4115 goto release;
4118 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4119 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4120 if ((AOP_TYPE (right) == AOP_LIT) && (AOP_TYPE (result) == AOP_CRY) && (AOP_TYPE (left) != AOP_CRY))
4122 int posbit = isLiteralBit (lit);
4123 /* left & 2^n */
4124 if (posbit)
4126 posbit--;
4127 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4128 // bit = left & 2^n
4129 if (size)
4130 pic14_emitcode ("mov", "c,acc.%d", posbit & 0x07);
4131 // if(left & 2^n)
4132 else
4134 if (ifx)
4136 int offset = 0;
4137 while (posbit > 7)
4139 posbit -= 8;
4140 offset++;
4142 emitpcode (((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
4143 newpCodeOpBit (aopGet (AOP (left), offset, FALSE, FALSE), posbit, 0));
4144 emitpcode (POC_GOTO, popGetLabel (rIfx.lbl->key));
4146 ifx->generated = TRUE;
4148 goto release;
4151 else
4153 symbol *tlbl = newiTempLabel (NULL);
4154 int sizel = AOP_SIZE (left);
4155 if (size)
4156 pic14_emitcode ("setb", "c");
4157 while (sizel--)
4159 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4161 // byte == 2^n ?
4162 if ((posbit = isLiteralBit (bytelit)) != 0)
4164 emitpcode (POC_BTFSC,
4165 newpCodeOpBit (aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0));
4167 else
4169 mov2w (AOP (left), offset);
4170 emitpcode (POC_ANDLW, newpCodeOpLit (bytelit & 0x0ff));
4171 emitSKPZ;
4173 emitpcode (POC_GOTO, popGetLabel (rIfx.condition ?
4174 rIfx.lbl->key : tlbl->key));
4176 offset++;
4178 if (!rIfx.condition)
4180 emitpcode (POC_GOTO, popGetLabel (rIfx.lbl->key));
4182 emitpLabel(tlbl->key);
4183 ifx->generated = TRUE;
4184 // bit = left & literal
4185 if (size)
4187 pic14_emitcode ("clr", "c");
4188 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
4190 // if(left & literal)
4191 else
4193 if (ifx)
4194 jmpTrueOrFalse (ifx, tlbl);
4195 goto release;
4198 pic14_outBitC (result);
4199 goto release;
4202 /* if left is same as result */
4203 if (pic14_sameRegs (AOP (result), AOP (left)))
4205 int know_W = -1;
4206 for (; size--; offset++, lit >>= 8)
4208 if (AOP_TYPE (right) == AOP_LIT)
4210 switch (lit & 0xff)
4212 case 0x00:
4213 /* and'ing with 0 has clears the result */
4214 emitpcode (POC_CLRF, popGet (AOP (result), offset));
4215 break;
4216 case 0xff:
4217 /* and'ing with 0xff is a nop when the result and left are the same */
4218 break;
4220 default:
4222 int p = my_powof2 ((~lit) & 0xff);
4223 if (p >= 0)
4225 /* only one bit is set in the literal, so use a bcf instruction */
4226 emitpcode (POC_BCF, newpCodeOpBit (aopGet (AOP (left), offset, FALSE, FALSE), p, 0));
4229 else
4231 if (know_W != (int) (lit & 0xff))
4232 emitpcode (POC_MOVLW, popGetLit (lit & 0xff));
4233 know_W = lit & 0xff;
4234 emitpcode (POC_ANDWF, popGet (AOP (left), offset));
4239 else
4241 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
4242 emitpcode (POC_ANDWF, popGet (AOP (left), offset));
4247 else
4249 // left & result in different registers
4250 if (AOP_TYPE (result) == AOP_CRY)
4252 // result = bit
4253 // if(size), result in bit
4254 // if(!size && ifx), conditional oper: if(left & right)
4255 symbol *tlbl = newiTempLabel (NULL);
4256 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4257 if (size)
4258 pic14_emitcode ("setb", "c");
4259 while (sizer--)
4261 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4262 pic14_emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
4263 pic14_emitcode ("jnz", "%05d_DS_", labelKey2num (tlbl->key));
4264 offset++;
4266 if (size)
4268 CLRC;
4269 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
4270 pic14_outBitC (result);
4272 else if (ifx)
4273 jmpTrueOrFalse (ifx, tlbl);
4275 else
4277 for (; (size--); offset++)
4279 // normal case
4280 // result = left & right
4281 if (AOP_TYPE (right) == AOP_LIT)
4283 int t = (lit >> (offset * 8)) & 0x0FFL;
4284 switch (t)
4286 case 0x00:
4287 emitpcode (POC_CLRF, popGet (AOP (result), offset));
4288 break;
4289 case 0xff:
4290 emitpcode (POC_MOVFW, popGet (AOP (left), offset));
4291 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
4292 break;
4293 default:
4294 emitpcode (POC_MOVLW, popGetLit (t));
4295 emitpcode (POC_ANDFW, popGet (AOP (left), offset));
4296 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
4298 continue;
4301 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
4302 emitpcode (POC_ANDFW, popGet (AOP (left), offset));
4303 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
4308 release:
4309 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4310 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4311 freeAsmop (result, NULL, ic, TRUE);
4314 /*-----------------------------------------------------------------*/
4315 /* genOr - code for or */
4316 /*-----------------------------------------------------------------*/
4317 static void
4318 genOr (iCode * ic, iCode * ifx)
4320 operand *left, *right, *result;
4321 int size, offset = 0;
4322 unsigned long lit = 0L;
4324 FENTRY;
4325 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
4327 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4328 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4329 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4331 DEBUGpic14_AopType (__LINE__, left, right, result);
4333 /* if left is a literal & right is not then exchange them */
4334 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) || AOP_NEEDSACC (left))
4336 operand *tmp = right;
4337 right = left;
4338 left = tmp;
4341 /* if result = right then exchange them */
4342 if (pic14_sameRegs (AOP (result), AOP (right)))
4344 operand *tmp = right;
4345 right = left;
4346 left = tmp;
4349 /* if right is bit then exchange them */
4350 if (AOP_TYPE (right) == AOP_CRY && AOP_TYPE (left) != AOP_CRY)
4352 operand *tmp = right;
4353 right = left;
4354 left = tmp;
4357 DEBUGpic14_AopType (__LINE__, left, right, result);
4359 if (AOP_TYPE (right) == AOP_LIT)
4360 lit = ulFromVal (AOP (right)->aopu.aop_lit);
4362 size = AOP_SIZE (result);
4364 // if(bit | yy)
4365 // xx = bit | yy;
4366 if (AOP_TYPE (left) == AOP_CRY)
4368 if (AOP_TYPE (right) == AOP_LIT)
4370 // c = bit & literal;
4371 if (lit)
4373 // lit != 0 => result = 1
4374 if (AOP_TYPE (result) == AOP_CRY)
4376 if (size)
4377 emitpcode (POC_BSF, popGet (AOP (result), 0));
4378 //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
4379 // AOP(result)->aopu.aop_dir,
4380 // AOP(result)->aopu.aop_dir);
4381 else if (ifx)
4382 continueIfTrue (ifx);
4383 goto release;
4386 else
4388 // lit == 0 => result = left
4389 if (size && pic14_sameRegs (AOP (result), AOP (left)))
4390 goto release;
4391 pic14_emitcode (";XXX mov", "c,%s %s,%d", AOP (left)->aopu.aop_dir, __FILE__, __LINE__);
4394 else
4396 if (AOP_TYPE (right) == AOP_CRY)
4398 if (pic14_sameRegs (AOP (result), AOP (left)))
4400 // c = bit | bit;
4401 emitpcode (POC_BCF, popGet (AOP (result), 0));
4402 emitpcode (POC_BTFSC, popGet (AOP (right), 0));
4403 emitpcode (POC_BSF, popGet (AOP (result), 0));
4405 pic14_emitcode ("bcf", "(%s >> 3), (%s & 7)", AOP (result)->aopu.aop_dir, AOP (result)->aopu.aop_dir);
4406 pic14_emitcode ("btfsc", "(%s >> 3), (%s & 7)", AOP (right)->aopu.aop_dir, AOP (right)->aopu.aop_dir);
4407 pic14_emitcode ("bsf", "(%s >> 3), (%s & 7)", AOP (result)->aopu.aop_dir, AOP (result)->aopu.aop_dir);
4409 else
4411 emitpcode (POC_BCF, popGet (AOP (result), 0));
4412 emitpcode (POC_BTFSS, popGet (AOP (right), 0));
4413 emitpcode (POC_BTFSC, popGet (AOP (left), 0));
4414 emitpcode (POC_BSF, popGet (AOP (result), 0));
4417 else
4419 // c = bit | val;
4420 symbol *tlbl = newiTempLabel (NULL);
4421 pic14_emitcode (";XXX ", " %s,%d", __FILE__, __LINE__);
4424 emitpcode (POC_BCF, popGet (AOP (result), 0));
4426 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4427 pic14_emitcode (";XXX setb", "c");
4428 pic14_emitcode (";XXX jb", "%s,%05d_DS_", AOP (left)->aopu.aop_dir, labelKey2num (tlbl->key));
4429 pic14_toBoolean (right);
4430 pic14_emitcode (";XXX jnz", "%05d_DS_", labelKey2num (tlbl->key));
4431 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4433 jmpTrueOrFalse (ifx, tlbl);
4434 goto release;
4436 else
4438 CLRC;
4439 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
4443 // bit = c
4444 // val = c
4445 if (size)
4446 pic14_outBitC (result);
4447 // if(bit | ...)
4448 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4449 genIfxJump (ifx, "c");
4450 goto release;
4453 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4454 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4455 if ((AOP_TYPE (right) == AOP_LIT) && (AOP_TYPE (result) == AOP_CRY) && (AOP_TYPE (left) != AOP_CRY))
4457 if (lit)
4459 pic14_emitcode (";XXX ", " %s,%d", __FILE__, __LINE__);
4460 // result = 1
4461 if (size)
4462 pic14_emitcode (";XXX setb", "%s", AOP (result)->aopu.aop_dir);
4463 else
4464 continueIfTrue (ifx);
4465 goto release;
4467 else
4469 pic14_emitcode (";XXX ", " %s,%d", __FILE__, __LINE__);
4470 // lit = 0, result = boolean(left)
4471 if (size)
4472 pic14_emitcode (";XXX setb", "c");
4473 pic14_toBoolean (left);
4474 if (size)
4476 symbol *tlbl = newiTempLabel (NULL);
4477 pic14_emitcode (";XXX jnz", "%05d_DS_", labelKey2num (tlbl->key));
4478 CLRC;
4479 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
4481 else
4483 genIfxJump (ifx, "a");
4484 goto release;
4487 pic14_outBitC (result);
4488 goto release;
4491 /* if left is same as result */
4492 if (pic14_sameRegs (AOP (result), AOP (left)))
4494 int know_W = -1;
4495 for (; size--; offset++, lit >>= 8)
4497 if (AOP_TYPE (right) == AOP_LIT)
4499 if ((lit & 0xff) == 0)
4500 /* or'ing with 0 has no effect */
4501 continue;
4502 else
4504 int p = my_powof2 (lit & 0xff);
4505 if (p >= 0)
4507 /* only one bit is set in the literal, so use a bsf instruction */
4508 emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP (left), offset, FALSE, FALSE), p, 0));
4510 else
4512 if (know_W != (int) (lit & 0xff))
4513 emitpcode (POC_MOVLW, popGetLit (lit & 0xff));
4514 know_W = lit & 0xff;
4515 emitpcode (POC_IORWF, popGet (AOP (left), offset));
4520 else
4522 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
4523 emitpcode (POC_IORWF, popGet (AOP (left), offset));
4527 else
4529 // left & result in different registers
4530 if (AOP_TYPE (result) == AOP_CRY)
4532 // result = bit
4533 // if(size), result in bit
4534 // if(!size && ifx), conditional oper: if(left | right)
4535 symbol *tlbl = newiTempLabel (NULL);
4536 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4537 pic14_emitcode (";XXX ", " %s,%d", __FILE__, __LINE__);
4540 if (size)
4541 pic14_emitcode (";XXX setb", "c");
4542 while (sizer--)
4544 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4545 pic14_emitcode (";XXX orl", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
4546 pic14_emitcode (";XXX jnz", "%05d_DS_", labelKey2num (tlbl->key));
4547 offset++;
4549 if (size)
4551 CLRC;
4552 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
4553 pic14_outBitC (result);
4555 else if (ifx)
4556 jmpTrueOrFalse (ifx, tlbl);
4558 else
4559 for (; (size--); offset++)
4561 // normal case
4562 // result = left | right
4563 if (AOP_TYPE (right) == AOP_LIT)
4565 int t = (lit >> (offset * 8)) & 0x0FFL;
4566 switch (t)
4568 case 0x00:
4569 emitpcode (POC_MOVFW, popGet (AOP (left), offset));
4570 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
4572 break;
4573 default:
4574 emitpcode (POC_MOVLW, popGetLit (t));
4575 emitpcode (POC_IORFW, popGet (AOP (left), offset));
4576 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
4578 continue;
4581 // faster than result <- left, anl result,right
4582 // and better if result is SFR
4583 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
4584 emitpcode (POC_IORFW, popGet (AOP (left), offset));
4585 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
4589 release:
4590 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4591 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4592 freeAsmop (result, NULL, ic, TRUE);
4595 /*-----------------------------------------------------------------*/
4596 /* genXor - code for xclusive or */
4597 /*-----------------------------------------------------------------*/
4598 static void
4599 genXor (iCode * ic, iCode * ifx)
4601 operand *left, *right, *result;
4602 int size, offset = 0;
4603 unsigned long lit = 0L;
4604 resolvedIfx rIfx;
4606 FENTRY;
4607 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
4609 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4610 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4611 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4613 resolveIfx (&rIfx, ifx);
4615 /* if left is a literal & right is not ||
4616 if left needs acc & right does not */
4617 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4619 operand *tmp = right;
4620 right = left;
4621 left = tmp;
4624 /* if result = right then exchange them */
4625 if (pic14_sameRegs (AOP (result), AOP (right)))
4627 operand *tmp = right;
4628 right = left;
4629 left = tmp;
4632 /* if right is bit then exchange them */
4633 if (AOP_TYPE (right) == AOP_CRY && AOP_TYPE (left) != AOP_CRY)
4635 operand *tmp = right;
4636 right = left;
4637 left = tmp;
4639 if (AOP_TYPE (right) == AOP_LIT)
4640 lit = ulFromVal (AOP (right)->aopu.aop_lit);
4642 size = AOP_SIZE (result);
4644 // if(bit ^ yy)
4645 // xx = bit ^ yy;
4646 if (AOP_TYPE (left) == AOP_CRY)
4648 if (AOP_TYPE (right) == AOP_LIT)
4650 // c = bit & literal;
4651 if (lit >> 1)
4653 // lit>>1 != 0 => result = 1
4654 if (AOP_TYPE (result) == AOP_CRY)
4656 if (size)
4658 emitpcode (POC_BSF, popGet (AOP (result), offset));
4659 pic14_emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4661 else if (ifx)
4662 continueIfTrue (ifx);
4663 goto release;
4665 pic14_emitcode ("setb", "c");
4667 else
4669 // lit == (0 or 1)
4670 if (lit == 0)
4672 // lit == 0, result = left
4673 if (size && pic14_sameRegs (AOP (result), AOP (left)))
4674 goto release;
4675 pic14_emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4677 else
4679 // lit == 1, result = not(left)
4680 if (size && pic14_sameRegs (AOP (result), AOP (left)))
4682 emitpcode (POC_MOVLW, popGet (AOP (result), offset));
4683 emitpcode (POC_XORWF, popGet (AOP (result), offset));
4684 pic14_emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4685 goto release;
4687 else
4689 assert (!"incomplete genXor");
4690 pic14_emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4691 pic14_emitcode ("cpl", "c");
4697 else
4699 // right != literal
4700 symbol *tlbl = newiTempLabel (NULL);
4701 if (AOP_TYPE (right) == AOP_CRY)
4703 // c = bit ^ bit;
4704 pic14_emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4706 else
4708 int sizer = AOP_SIZE (right);
4709 // c = bit ^ val
4710 // if val>>1 != 0, result = 1
4711 pic14_emitcode ("setb", "c");
4712 while (sizer)
4714 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
4715 if (sizer == 1)
4716 // test the msb of the lsb
4717 pic14_emitcode ("anl", "a,#0xfe");
4718 pic14_emitcode ("jnz", "%05d_DS_", labelKey2num (tlbl->key));
4719 sizer--;
4721 // val = (0,1)
4722 pic14_emitcode ("rrc", "a");
4724 pic14_emitcode ("jnb", "%s,%05d_DS_", AOP (left)->aopu.aop_dir, (labelKey2num (tlbl->key)));
4725 pic14_emitcode ("cpl", "c");
4726 pic14_emitcode ("", "%05d_DS_:", (labelKey2num (tlbl->key)));
4728 // bit = c
4729 // val = c
4730 if (size)
4731 pic14_outBitC (result);
4732 // if(bit | ...)
4733 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4734 genIfxJump (ifx, "c");
4735 goto release;
4738 if (pic14_sameRegs (AOP (result), AOP (left)))
4740 /* if left is same as result */
4741 for (; size--; offset++)
4743 if (AOP_TYPE (right) == AOP_LIT)
4745 int t = (lit >> (offset * 8)) & 0x0FFL;
4746 if (t == 0x00L)
4747 continue;
4748 else
4750 emitpcode (POC_MOVLW, popGetLit (t));
4751 emitpcode (POC_XORWF, popGet (AOP (left), offset));
4754 else
4756 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
4757 emitpcode (POC_XORWF, popGet (AOP (left), offset));
4761 else
4763 // left & result in different registers
4764 if (AOP_TYPE (result) == AOP_CRY)
4766 // result = bit
4767 // if(size), result in bit
4768 // if(!size && ifx), conditional oper: if(left ^ right)
4769 symbol *tlbl = newiTempLabel (NULL);
4770 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4771 if (size)
4772 pic14_emitcode ("setb", "c");
4773 while (sizer--)
4775 if ((AOP_TYPE (right) == AOP_LIT) && (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
4777 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4779 else
4781 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4782 pic14_emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
4784 pic14_emitcode ("jnz", "%05d_DS_", labelKey2num (tlbl->key));
4785 if (AOP_TYPE (right) == AOP_LIT)
4787 int t = (lit >> (offset * 8)) & 0x0FFL;
4788 switch (t)
4790 case 0x00:
4791 emitpcode (POC_MOVFW, popGet (AOP (left), offset));
4792 break;
4793 case 0xff:
4794 emitpcode (POC_COMFW, popGet (AOP (left), offset));
4795 break;
4796 default:
4797 emitpcode (POC_MOVLW, popGetLit (t));
4798 emitpcode (POC_XORFW, popGet (AOP (left), offset));
4801 else if (offset >= AOP_SIZE(left))
4803 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
4805 else if (offset >= AOP_SIZE(right))
4807 emitpcode (POC_MOVFW, popGet (AOP (left), offset));
4809 else
4811 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
4812 emitpcode (POC_XORFW, popGet (AOP (left), offset));
4814 emitSKPZ;
4815 if (ifx)
4816 emitpcode (POC_GOTO, popGetLabel (rIfx.condition ?
4817 rIfx.lbl->key : tlbl->key));
4818 offset++;
4820 if (!rIfx.condition)
4822 emitpcode (POC_GOTO, popGetLabel (rIfx.lbl->key));
4824 emitpLabel(tlbl->key);
4825 ifx->generated = TRUE;
4826 if (size)
4828 CLRC;
4829 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl->key));
4830 pic14_outBitC (result);
4832 else if (ifx)
4833 jmpTrueOrFalse (ifx, tlbl);
4835 else
4836 for (; (size--); offset++)
4838 // normal case
4839 // result = left & right
4840 if (AOP_TYPE (right) == AOP_LIT)
4842 int t = (lit >> (offset * 8)) & 0x0FFL;
4843 switch (t)
4845 case 0x00:
4846 emitpcode (POC_MOVFW, popGet (AOP (left), offset));
4847 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
4848 break;
4849 case 0xff:
4850 emitpcode (POC_COMFW, popGet (AOP (left), offset));
4851 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
4852 break;
4853 default:
4854 emitpcode (POC_MOVLW, popGetLit (t));
4855 emitpcode (POC_XORFW, popGet (AOP (left), offset));
4856 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
4858 continue;
4861 // faster than result <- left, anl result,right
4862 // and better if result is SFR
4863 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
4864 emitpcode (POC_XORFW, popGet (AOP (left), offset));
4865 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
4869 release:
4870 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4871 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4872 freeAsmop (result, NULL, ic, TRUE);
4875 /*-----------------------------------------------------------------*/
4876 /* genInline - write the inline code out */
4877 /*-----------------------------------------------------------------*/
4878 static void
4879 pic14_genInline (iCode * ic)
4881 char *buffer, *bp, *bp1;
4882 bool inComment = FALSE;
4884 FENTRY;
4885 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
4887 genLine.lineElement.isInline += (!options.asmpeep);
4889 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
4891 while (*bp)
4893 switch (*bp)
4895 case ';':
4896 inComment = TRUE;
4897 ++bp;
4898 break;
4900 case '\x87':
4901 case '\n':
4902 inComment = FALSE;
4903 *bp++ = '\0';
4904 if (*bp1)
4905 addpCode2pBlock (pb, newpCodeAsmDir (bp1, NULL)); // inline directly, no process
4906 bp1 = bp;
4907 break;
4909 default:
4910 /* Add \n for labels, not dirs such as c:\mydir */
4911 if (!inComment && (*bp == ':') && (isspace ((unsigned char) bp[1])))
4913 ++bp;
4914 *bp = '\0';
4915 ++bp;
4916 /* print label, use this special format with NULL directive
4917 * to denote that the argument should not be indented with tab */
4918 addpCode2pBlock (pb, newpCodeAsmDir (NULL, bp1)); // inline directly, no process
4919 bp1 = bp;
4921 else
4922 ++bp;
4923 break;
4926 if ((bp1 != bp) && *bp1)
4927 addpCode2pBlock (pb, newpCodeAsmDir (bp1, NULL)); // inline directly, no process
4929 Safe_free (buffer);
4931 /* consumed; we can free it here */
4932 dbuf_free (IC_INLINE (ic));
4934 genLine.lineElement.isInline -= (!options.asmpeep);
4937 /*-----------------------------------------------------------------*/
4938 /* genRRC - rotate right with carry */
4939 /*-----------------------------------------------------------------*/
4940 static void
4941 genRRC (iCode * ic)
4943 operand *left, *result;
4944 int size, same;
4946 FENTRY;
4947 /* rotate right with carry */
4948 left = IC_LEFT (ic);
4949 result = IC_RESULT (ic);
4950 aopOp (left, ic, FALSE);
4951 aopOp (result, ic, FALSE);
4953 DEBUGpic14_AopType (__LINE__, left, NULL, result);
4955 same = pic14_sameRegs (AOP (result), AOP (left));
4957 size = AOP_SIZE (result);
4959 /* get the lsb and put it into the carry */
4960 emitpcode (POC_RRFW, popGet (AOP (left), 0));
4962 while (size--)
4964 if (same)
4966 emitpcode (POC_RRF, popGet (AOP (left), size));
4968 else
4970 emitpcode (POC_RRFW, popGet (AOP (left), size));
4971 emitpcode (POC_MOVWF, popGet (AOP (result), size));
4975 freeAsmop (left, NULL, ic, TRUE);
4976 freeAsmop (result, NULL, ic, TRUE);
4979 /*-----------------------------------------------------------------*/
4980 /* genRLC - generate code for rotate left with carry */
4981 /*-----------------------------------------------------------------*/
4982 static void
4983 genRLC (iCode * ic)
4985 operand *left, *result;
4986 int size, offset = 0;
4987 int same;
4989 FENTRY;
4990 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
4991 /* rotate right with carry */
4992 left = IC_LEFT (ic);
4993 result = IC_RESULT (ic);
4994 aopOp (left, ic, FALSE);
4995 aopOp (result, ic, FALSE);
4997 DEBUGpic14_AopType (__LINE__, left, NULL, result);
4999 same = pic14_sameRegs (AOP (result), AOP (left));
5001 /* move it to the result */
5002 size = AOP_SIZE (result);
5004 /* get the msb and put it into the carry */
5005 emitpcode (POC_RLFW, popGet (AOP (left), size - 1));
5007 offset = 0;
5009 while (size--)
5011 if (same)
5013 emitpcode (POC_RLF, popGet (AOP (left), offset));
5015 else
5017 emitpcode (POC_RLFW, popGet (AOP (left), offset));
5018 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
5021 offset++;
5025 freeAsmop (left, NULL, ic, TRUE);
5026 freeAsmop (result, NULL, ic, TRUE);
5029 static void
5030 genGetABit (iCode * ic)
5032 operand *left, *right, *result;
5033 int shCount;
5034 int offset;
5035 int i;
5037 left = IC_LEFT (ic);
5038 right = IC_RIGHT (ic);
5039 result = IC_RESULT (ic);
5041 aopOp (left, ic, FALSE);
5042 aopOp (right, ic, FALSE);
5043 aopOp (result, ic, TRUE);
5045 shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
5046 offset = shCount / 8;
5047 shCount %= 8;
5049 /* load and mask the source byte */
5050 mov2w (AOP (left), offset);
5051 emitpcode (POC_ANDLW, popGetLit (1 << shCount));
5053 /* move selected bit to bit 0 */
5054 switch (shCount)
5056 case 0:
5057 /* nothing more to do */
5058 break;
5059 default:
5060 /* keep W==0, force W=0x01 otherwise */
5061 emitSKPZ;
5062 emitpcode (POC_MOVLW, popGetLit (1));
5063 break;
5064 } // switch
5066 /* write result */
5067 emitpcode (POC_MOVWF, popGet (AOP (result), 0));
5069 for (i = 1; i < AOP_SIZE (result); ++i)
5071 emitpcode (POC_CLRF, popGet (AOP (result), i));
5072 } // for
5074 freeAsmop (left, NULL, ic, TRUE);
5075 freeAsmop (right, NULL, ic, TRUE);
5076 freeAsmop (result, NULL, ic, TRUE);
5079 /*-----------------------------------------------------------------*/
5080 /* AccLsh - shift left accumulator by known count */
5081 /* MARK: pic14 always rotates through CARRY! */
5082 /*-----------------------------------------------------------------*/
5083 static void
5084 AccLsh (pCodeOp * pcop, int shCount)
5086 FENTRY;
5087 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
5088 shCount &= 0x0007; // shCount : 0..7
5089 switch (shCount)
5091 case 0:
5092 return;
5093 break;
5094 case 1:
5095 emitCLRC;
5096 emitpcode (POC_RLF, pcop);
5097 return;
5098 break;
5099 case 2:
5100 emitpcode (POC_RLF, pcop);
5101 emitpcode (POC_RLF, pcop);
5102 break;
5103 case 3:
5104 emitpcode (POC_RLF, pcop);
5105 emitpcode (POC_RLF, pcop);
5106 emitpcode (POC_RLF, pcop);
5107 break;
5108 case 4:
5109 emitpcode (POC_SWAPF, pcop);
5110 break;
5111 case 5:
5112 emitpcode (POC_SWAPF, pcop);
5113 emitpcode (POC_RLF, pcop);
5114 break;
5115 case 6:
5116 emitpcode (POC_SWAPF, pcop);
5117 emitpcode (POC_RLF, pcop);
5118 emitpcode (POC_RLF, pcop);
5119 break;
5120 case 7:
5121 emitpcode (POC_RRFW, pcop);
5122 emitpcode (POC_RRF, pcop);
5123 break;
5125 /* clear invalid bits */
5126 emitpcode (POC_MOVLW, popGetLit ((unsigned char) (~((1UL << shCount) - 1))));
5127 emitpcode (POC_ANDWF, pcop);
5130 /*-----------------------------------------------------------------*/
5131 /* AccRsh - shift right accumulator by known count */
5132 /* MARK: pic14 always rotates through CARRY! */
5133 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
5134 /* 1: mask out invalid bits (zero-extend) */
5135 /* 2: sign-extend result (pretty slow) */
5136 /*-----------------------------------------------------------------*/
5137 static void
5138 AccRsh (pCodeOp * pcop, int shCount, int mask_mode)
5140 FENTRY;
5141 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
5142 shCount &= 0x0007; // shCount : 0..7
5143 switch (shCount)
5145 case 0:
5146 return;
5147 break;
5148 case 1:
5149 /* load sign if needed */
5150 if (mask_mode == 2)
5151 emitpcode (POC_RLFW, pcop);
5152 else if (mask_mode == 1)
5153 emitCLRC;
5154 emitpcode (POC_RRF, pcop);
5155 return;
5156 break;
5157 case 2:
5158 /* load sign if needed */
5159 if (mask_mode == 2)
5160 emitpcode (POC_RLFW, pcop);
5161 emitpcode (POC_RRF, pcop);
5162 /* load sign if needed */
5163 if (mask_mode == 2)
5164 emitpcode (POC_RLFW, pcop);
5165 emitpcode (POC_RRF, pcop);
5166 if (mask_mode == 2)
5167 return;
5168 break;
5169 case 3:
5170 /* load sign if needed */
5171 if (mask_mode == 2)
5172 emitpcode (POC_RLFW, pcop);
5173 emitpcode (POC_RRF, pcop);
5174 /* load sign if needed */
5175 if (mask_mode == 2)
5176 emitpcode (POC_RLFW, pcop);
5177 emitpcode (POC_RRF, pcop);
5178 /* load sign if needed */
5179 if (mask_mode == 2)
5180 emitpcode (POC_RLFW, pcop);
5181 emitpcode (POC_RRF, pcop);
5182 if (mask_mode == 2)
5183 return;
5184 break;
5185 case 4:
5186 emitpcode (POC_SWAPF, pcop);
5187 break;
5188 case 5:
5189 emitpcode (POC_SWAPF, pcop);
5190 emitpcode (POC_RRF, pcop);
5191 break;
5192 case 6:
5193 emitpcode (POC_SWAPF, pcop);
5194 emitpcode (POC_RRF, pcop);
5195 emitpcode (POC_RRF, pcop);
5196 break;
5197 case 7:
5198 if (mask_mode == 2)
5200 /* load sign */
5201 emitpcode (POC_RLFW, pcop);
5202 emitpcode (POC_CLRF, pcop);
5203 emitSKPNC;
5204 emitpcode (POC_COMF, pcop);
5205 return;
5207 else
5209 emitpcode (POC_RLFW, pcop);
5210 emitpcode (POC_RLF, pcop);
5212 break;
5215 if (mask_mode == 0)
5217 /* leave invalid bits undefined */
5218 return;
5221 /* clear invalid bits -- zero-extend */
5222 emitpcode (POC_MOVLW, popGetLit (0x00ff >> shCount));
5223 emitpcode (POC_ANDWF, pcop);
5225 if (mask_mode == 2)
5227 /* sign-extend */
5228 emitpcode (POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
5229 emitpcode (POC_BTFSC, newpCodeOpBit (get_op (pcop, NULL, 0), 7 - shCount, 0));
5230 emitpcode (POC_IORWF, pcop);
5234 /*-----------------------------------------------------------------*/
5235 /* movLeft2Result - move byte from left to result */
5236 /*-----------------------------------------------------------------*/
5237 static void
5238 movLeft2Result (operand * left, int offl, operand * result, int offr)
5240 FENTRY;
5241 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
5242 if (!pic14_sameRegs (AOP (left), AOP (result)) || (offl != offr))
5244 aopGet (AOP (left), offl, FALSE, FALSE);
5246 emitpcode (POC_MOVFW, popGet (AOP (left), offl));
5247 emitpcode (POC_MOVWF, popGet (AOP (result), offr));
5251 /*-----------------------------------------------------------------*/
5252 /* shiftLeft_Left2ResultLit - shift left by known count */
5253 /*-----------------------------------------------------------------*/
5255 static void
5256 shiftLeft_Left2ResultLit (operand * left, operand * result, int shCount)
5258 int size, same, offr, i;
5260 size = AOP_SIZE (left);
5261 if (AOP_SIZE (result) < size)
5262 size = AOP_SIZE (result);
5264 same = pic14_sameRegs (AOP (left), AOP (result));
5266 offr = shCount / 8;
5267 shCount = shCount & 0x07;
5269 if (size <= offr)
5271 offr = size;
5273 else
5275 size -= offr;
5277 switch (shCount)
5279 case 0: /* takes 0 or 2N cycles (for offr==0) */
5280 if (!same || offr)
5282 for (i = size - 1; i >= 0; i--)
5283 movLeft2Result (left, i, result, offr + i);
5284 } // if
5285 break;
5287 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
5288 if (same && offr)
5290 shiftLeft_Left2ResultLit (left, result, 8 * offr);
5291 shiftLeft_Left2ResultLit (result, result, shCount);
5292 return; /* prevent clearing result again */
5294 else
5296 if (pic->isEnhancedCore)
5298 for (i = 0; i < size; i++)
5300 if (same && !offr)
5302 if (i == 0)
5304 emitpcode (POC_LSLF, popGet (AOP (left), i));
5306 else
5308 emitpcode (POC_RLF, popGet (AOP (left), i));
5311 else
5313 if (i == 0)
5315 emitpcode (POC_LSLFW, popGet (AOP (left), i));
5317 else
5319 emitpcode (POC_RLFW, popGet (AOP (left), i));
5322 emitpcode (POC_MOVWF, popGet (AOP (result), i + offr));
5326 else
5328 emitCLRC;
5329 for (i = 0; i < size; i++)
5331 if (same && !offr)
5333 emitpcode (POC_RLF, popGet (AOP (left), i));
5335 else
5337 emitpcode (POC_RLFW, popGet (AOP (left), i));
5338 emitpcode (POC_MOVWF, popGet (AOP (result), i + offr));
5339 } // if
5340 } // for
5341 } // if (pic->isEnhancedCore)
5342 } // if (same && offr)
5343 break;
5345 case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
5346 /* works in-place/with offr as well */
5347 emitpcode (POC_SWAPFW, popGet (AOP (left), size - 1));
5348 emitpcode (POC_ANDLW, popGetLit (0xF0));
5349 emitpcode (POC_MOVWF, popGet (AOP (result), size - 1 + offr));
5351 for (i = size - 2; i >= 0; i--)
5353 emitpcode (POC_SWAPFW, popGet (AOP (left), i));
5354 emitpcode (POC_MOVWF, popGet (AOP (result), i + offr));
5355 emitpcode (POC_ANDLW, popGetLit (0x0F));
5356 emitpcode (POC_IORWF, popGet (AOP (result), i + offr + 1));
5357 emitpcode (POC_XORWF, popGet (AOP (result), i + offr));
5358 } // for i
5359 break;
5361 case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
5362 /* works in-place/with offr as well */
5363 emitpcode (POC_RRFW, popGet (AOP (left), size - 1));
5364 for (i = size - 2; i >= 0; i--)
5366 emitpcode (POC_RRFW, popGet (AOP (left), i));
5367 emitpcode (POC_MOVWF, popGet (AOP (result), offr + i + 1));
5368 } // for i
5369 emitpcode (POC_CLRF, popGet (AOP (result), offr));
5370 emitpcode (POC_RRF, popGet (AOP (result), offr));
5371 break;
5373 default:
5374 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount - 1);
5375 shiftLeft_Left2ResultLit (result, result, 1);
5376 return; /* prevent clearing result again */
5377 break;
5378 } // switch
5381 while (0 < offr--)
5383 emitpcode (POC_CLRF, popGet (AOP (result), offr));
5384 } // while
5387 /*-----------------------------------------------------------------*/
5388 /* shiftRight_Left2ResultLit - shift right by known count */
5389 /*-----------------------------------------------------------------*/
5391 static void
5392 shiftRight_Left2ResultLit (operand * left, operand * result, int shCount, int sign)
5394 int size, same, offr, i;
5396 size = AOP_SIZE (left);
5397 if (AOP_SIZE (result) < size)
5398 size = AOP_SIZE (result);
5400 same = pic14_sameRegs (AOP (left), AOP (result));
5402 offr = shCount / 8;
5403 shCount = shCount & 0x07;
5405 if (size <= offr)
5407 size = AOP_SIZE (result);
5408 if (sign)
5410 emitpcode (POC_MOVLW, popGetLit (0));
5411 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE), 7, 0));
5412 emitpcode (POC_MOVLW, popGetLit (0xff));
5413 while (size--)
5415 emitpcode (POC_MOVWF, popGet (AOP (result), size));
5416 } // while
5418 else
5420 while (size--)
5422 emitpcode (POC_CLRF, popGet (AOP (result), size));
5423 } // while
5426 else
5428 size -= offr;
5430 switch (shCount)
5432 case 0: /* takes 0 or 2N cycles (for offr==0) */
5433 if (!same || offr)
5435 for (i = 0; i < size; i++)
5436 movLeft2Result (left, i + offr, result, i);
5437 } // if
5438 break;
5440 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
5441 emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign,
5442 same, offr);
5443 if (same && offr)
5445 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
5446 shiftRight_Left2ResultLit (result, result, shCount, sign);
5447 return; /* prevent sign-extending result again */
5449 else
5451 if (pic->isEnhancedCore)
5453 for (i = size - 1; i >= 0; i--)
5455 if (same && !offr)
5457 if (i == (size - 1))
5459 if (sign)
5461 emitpcode (POC_ASRF, popGet (AOP (left), i));
5463 else
5465 emitpcode (POC_LSRF, popGet (AOP (left), i));
5468 else
5470 emitpcode (POC_RRF, popGet (AOP (left), i));
5473 else
5475 if (i == (size - 1))
5477 if (sign)
5479 emitpcode (POC_ASRFW, popGet (AOP (left), i + offr));
5481 else
5483 emitpcode (POC_LSRFW, popGet (AOP (left), i + offr));
5486 else
5488 emitpcode (POC_RRFW, popGet (AOP (left), i + offr));
5491 emitpcode (POC_MOVWF, popGet (AOP (result), i));
5492 } // if (same && !offr)
5493 } // for i
5495 else
5497 emitCLRC;
5498 if (sign)
5500 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE), 7, 0));
5501 emitSETC;
5504 for (i = size - 1; i >= 0; i--)
5506 if (same && !offr)
5508 emitpcode (POC_RRF, popGet (AOP (left), i));
5510 else
5512 emitpcode (POC_RRFW, popGet (AOP (left), i + offr));
5513 emitpcode (POC_MOVWF, popGet (AOP (result), i));
5515 } // for i
5516 } // if (pic->isEnhancedCore)
5517 } // if (same && offr)
5518 break;
5520 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
5521 /* works in-place/with offr as well */
5522 emitpcode (POC_SWAPFW, popGet (AOP (left), offr));
5523 emitpcode (POC_ANDLW, popGetLit (0x0F));
5524 emitpcode (POC_MOVWF, popGet (AOP (result), 0));
5526 for (i = 1; i < size; i++)
5528 emitpcode (POC_SWAPFW, popGet (AOP (left), i + offr));
5529 emitpcode (POC_MOVWF, popGet (AOP (result), i));
5530 emitpcode (POC_ANDLW, popGetLit (0xF0));
5531 emitpcode (POC_IORWF, popGet (AOP (result), i - 1));
5532 emitpcode (POC_XORWF, popGet (AOP (result), i));
5533 } // for i
5535 if (sign)
5537 emitpcode (POC_MOVLW, popGetLit (0xF0));
5538 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP (result), size - 1, FALSE, FALSE), 3, 0));
5539 emitpcode (POC_IORWF, popGet (AOP (result), size - 1));
5540 } // if
5541 break;
5543 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
5544 /* works in-place/with offr as well */
5545 emitpcode (POC_RLFW, popGet (AOP (left), offr));
5546 for (i = 0; i < size - 1; i++)
5548 emitpcode (POC_RLFW, popGet (AOP (left), offr + i + 1));
5549 emitpcode (POC_MOVWF, popGet (AOP (result), i));
5550 } // for i
5551 emitpcode (POC_CLRF, popGet (AOP (result), size - 1));
5552 if (!sign)
5554 emitpcode (POC_RLF, popGet (AOP (result), size - 1));
5556 else
5558 emitSKPNC;
5559 emitpcode (POC_DECF, popGet (AOP (result), size - 1));
5561 break;
5563 default:
5564 shiftRight_Left2ResultLit (left, result, offr * 8 + shCount - 1, sign);
5565 shiftRight_Left2ResultLit (result, result, 1, sign);
5566 return; /* prevent sign extending result again */
5567 break;
5568 } // switch
5570 addSign (result, size, sign);
5574 /*-----------------------------------------------------------------*
5575 * genMultiAsm - repeat assembly instruction for size of register.
5576 * if endian == 1, then the high byte (i.e base address + size of
5577 * register) is used first else the low byte is used first;
5578 *-----------------------------------------------------------------*/
5579 static void
5580 genMultiAsm (PIC_OPCODE poc, operand * reg, int size, int endian)
5583 int offset = 0;
5585 FENTRY;
5586 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
5588 if (!reg)
5589 return;
5591 if (!endian)
5593 endian = 1;
5595 else
5597 endian = -1;
5598 offset = size - 1;
5601 while (size--)
5603 emitpcode (poc, popGet (AOP (reg), offset));
5604 offset += endian;
5609 /*-----------------------------------------------------------------*/
5610 /* loadSignToC - load the operand's sign bit into CARRY */
5611 /*-----------------------------------------------------------------*/
5613 static void
5614 loadSignToC (operand * op)
5616 FENTRY;
5617 assert (op && AOP (op) && AOP_SIZE (op));
5619 emitCLRC;
5620 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP (op), AOP_SIZE (op) - 1, FALSE, FALSE), 7, 0));
5621 emitSETC;
5624 /*-----------------------------------------------------------------*/
5625 /* genRightShift - generate code for right shifting */
5626 /*-----------------------------------------------------------------*/
5627 static void
5628 genGenericShift (iCode * ic, int shiftRight)
5630 operand *right, *left, *result;
5631 int size;
5632 symbol *tlbl, *tlbl1, *inverselbl;
5634 FENTRY;
5635 /* if signed then we do it the hard way preserve the
5636 sign bit moving it inwards */
5637 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
5639 /* signed & unsigned types are treated the same : i.e. the
5640 signed is NOT propagated inwards : quoting from the
5641 ANSI - standard : "for E1 >> E2, is equivalent to division
5642 by 2**E2 if unsigned or if it has a non-negative value,
5643 otherwise the result is implementation defined ", MY definition
5644 is that the sign does not get propagated */
5646 right = IC_RIGHT (ic);
5647 left = IC_LEFT (ic);
5648 result = IC_RESULT (ic);
5650 aopOp (right, ic, FALSE);
5651 aopOp (left, ic, FALSE);
5652 aopOp (result, ic, FALSE);
5654 /* if the shift count is known then do it
5655 as efficiently as possible */
5656 if (AOP_TYPE (right) == AOP_LIT)
5658 int lit = (int) ulFromVal (AOP (right)->aopu.aop_lit);
5659 if (lit < 0)
5661 lit = -lit;
5662 shiftRight = !shiftRight;
5665 if (shiftRight)
5666 shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN (operandType (left)));
5667 else
5668 shiftLeft_Left2ResultLit (left, result, lit);
5669 //genRightShiftLiteral (left,right,result,ic, 0);
5670 return;
5673 /* shift count is unknown then we have to form
5674 a loop get the loop count in B : Note: we take
5675 only the lower order byte since shifting
5676 more that 32 bits make no sense anyway, ( the
5677 largest size of an object can be only 32 bits ) */
5679 /* we must not overwrite the shift counter */
5680 assert (!pic14_sameRegs (AOP (right), AOP (result)));
5682 /* now move the left to the result if they are not the
5683 same */
5684 if (!pic14_sameRegs (AOP (left), AOP (result)))
5686 size = min (AOP_SIZE (result), AOP_SIZE (left));
5687 while (size--)
5689 mov2w (AOP (left), size);
5690 movwf (AOP (result), size);
5692 addSign (result, AOP_SIZE (left), !SPEC_USIGN (operandType (left)));
5695 tlbl = newiTempLabel (NULL);
5696 tlbl1 = newiTempLabel (NULL);
5697 inverselbl = NULL;
5698 size = AOP_SIZE (result);
5700 mov2w (AOP (right), 0);
5701 if (!SPEC_USIGN (operandType (right)))
5703 inverselbl = newiTempLabel (NULL);
5704 /* signed shift count -- invert shift direction for c<0 */
5705 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP (right), 0, FALSE, FALSE), 7, 0));
5706 emitpcode (POC_GOTO, popGetLabel (inverselbl->key));
5707 } // if
5708 emitpcode (POC_SUBLW, popGetLit (0)); /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
5709 /* check for `a = b >> c' with `-c == 0' */
5710 emitSKPNZ;
5711 emitpcode (POC_GOTO, popGetLabel (tlbl1->key));
5712 emitpLabel (tlbl->key);
5713 /* propagate the sign bit inwards for SIGNED result */
5714 if (shiftRight && !SPEC_USIGN (operandType (result)))
5715 loadSignToC (result);
5716 genMultiAsm (shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
5717 emitpcode (POC_ADDLW, popGetLit (1)); /* clears CARRY (unless W==0 afterwards) */
5718 emitSKPC;
5719 emitpcode (POC_GOTO, popGetLabel (tlbl->key));
5721 if (!SPEC_USIGN (operandType (right)))
5723 symbol *inv_loop = newiTempLabel (NULL);
5725 shiftRight = !shiftRight; /* invert shift direction */
5727 /* we came here from the code above -- we are done */
5728 emitpcode (POC_GOTO, popGetLabel (tlbl1->key));
5730 /* emit code for shifting N<0 steps, count is already in W */
5731 emitpLabel (inverselbl->key);
5732 if (!shiftRight || SPEC_USIGN (operandType (result)))
5733 emitCLRC;
5734 emitpLabel (inv_loop->key);
5735 /* propagate the sign bit inwards for SIGNED result */
5736 if (shiftRight && !SPEC_USIGN (operandType (result)))
5737 loadSignToC (result);
5738 genMultiAsm (shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
5739 emitpcode (POC_ADDLW, popGetLit (1));
5740 emitSKPC;
5741 emitpcode (POC_GOTO, popGetLabel (inv_loop->key));
5742 } // if
5744 emitpLabel (tlbl1->key);
5746 freeAsmop (left, NULL, ic, TRUE);
5747 freeAsmop (right, NULL, ic, TRUE);
5748 freeAsmop (result, NULL, ic, TRUE);
5751 /*-----------------------------------------------------------------*/
5752 /* genRot - generates code for rotation */
5753 /*-----------------------------------------------------------------*/
5754 static void
5755 genRot (iCode *ic)
5757 operand *left = IC_LEFT (ic);
5758 operand *right = IC_RIGHT (ic);
5759 unsigned int lbits = bitsForType (operandType (left));
5760 if (IS_OP_LITERAL (right) && operandLitValueUll (right) % lbits == 1)
5761 genRLC (ic);
5762 else if (IS_OP_LITERAL (right) && operandLitValueUll (right) % lbits == lbits - 1)
5763 genRRC (ic);
5764 else
5765 wassertl (0, "Unsupported rotation.");
5768 static void
5769 genRightShift (iCode * ic)
5771 genGenericShift (ic, 1);
5774 static void
5775 genLeftShift (iCode * ic)
5777 genGenericShift (ic, 0);
5780 /*-----------------------------------------------------------------*/
5781 /* SetIrp - Set IRP bit */
5782 /*-----------------------------------------------------------------*/
5783 static void
5784 SetIrp (operand * result)
5786 FENTRY;
5787 if (AOP_TYPE (result) == AOP_LIT)
5789 unsigned lit = (unsigned) double2ul (operandLitValue (result));
5790 if (lit & 0x100)
5791 emitSETIRP;
5792 else
5793 emitCLRIRP;
5795 else if ((AOP_TYPE (result) == AOP_PCODE) && (AOP (result)->aopu.pcop->type == PO_LITERAL))
5797 int addrs = PCOL (AOP (result)->aopu.pcop)->lit;
5798 if (addrs & 0x100)
5799 emitSETIRP;
5800 else
5801 emitCLRIRP;
5803 else if ((AOP_TYPE (result) == AOP_PCODE) && (AOP (result)->aopu.pcop->type == PO_IMMEDIATE))
5805 emitCLRIRP; /* always ensure this is clear as it may have previously been set */
5806 emitpcode (POC_MOVLW, popGetAddr (AOP (result), 1, 0));
5807 emitpcode (POC_ANDLW, popGetLit (0x01));
5808 emitSKPZ;
5809 emitSETIRP;
5811 else
5813 emitCLRIRP; /* always ensure this is clear as it may have previously been set */
5814 if (AOP_SIZE (result) > 1)
5816 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP (result), 1, FALSE, FALSE), 0, 0));
5817 emitSETIRP;
5822 static void
5823 setup_fsr (operand * ptr)
5825 if (pic->isEnhancedCore)
5827 mov2w_op (ptr, 0);
5828 emitpcode (POC_MOVWF, popCopyReg (&pc_fsr0l));
5829 mov2w_op (ptr, 1);
5830 emitpcode (POC_MOVWF, popCopyReg (&pc_fsr0h));
5832 else
5834 mov2w_op (ptr, 0);
5835 emitpcode (POC_MOVWF, popCopyReg (&pc_fsr));
5837 /* also setup-up IRP */
5838 SetIrp (ptr);
5842 static void
5843 inc_fsr (int delta)
5845 if (0 == delta)
5847 /* Nothing to do. */
5848 return;
5849 } // if
5851 if (pic->isEnhancedCore)
5853 if (pic14_options.no_ext_instr)
5856 * Not sure if we may modify W here, so implement this without
5857 * touching W.
5859 * Efficiency is not too important here, as enhanced cores
5860 * will most likely use extended instructions here. This is
5861 * only a workaround for gputils 0.13.7, which supports the
5862 * 16f1934 enhanced core, but fails to assemble ADDFSR.
5864 while (delta > 0)
5866 emitpcode (POC_INCFSZ, popCopyReg (&pc_fsr0l));
5867 emitpcode (POC_DECF, popCopyReg (&pc_fsr0h));
5868 emitpcode (POC_INCF, popCopyReg (&pc_fsr0h));
5869 --delta;
5870 } // while
5871 while (delta < 0)
5873 addpCode2pBlock (pb, newpCodeAsmDir("MOVF", "FSR0L, 1"));
5874 emitSKPNZ;
5875 emitpcode (POC_DECF, popCopyReg (&pc_fsr0h));
5876 emitpcode (POC_DECF, popCopyReg (&pc_fsr0l));
5877 ++delta;
5878 } // while
5880 else
5882 assert (delta >= -32);
5883 assert (delta < 32);
5884 /* Hack: Turn this into a PCI (not that easy due to the argument structure). */
5885 addpCode2pBlock (pb, newpCodeAsmDir ("ADDFSR", "FSR0, %d", delta));
5886 } // if
5888 else
5890 while (delta > 0)
5892 emitpcode (POC_INCF, popCopyReg (&pc_fsr));
5893 --delta;
5894 } // while
5895 while (delta < 0)
5897 emitpcode (POC_DECF, popCopyReg (&pc_fsr));
5898 ++delta;
5899 } // while
5900 } // if
5903 /*-----------------------------------------------------------------*/
5904 /* emitPtrByteGet - emits code to get a byte into WREG from an */
5905 /* arbitrary pointer (__code, __data, generic) */
5906 /*-----------------------------------------------------------------*/
5907 static void
5908 emitPtrByteGet (operand * src, int p_type, bool alreadyAddressed)
5910 FENTRY;
5911 switch (p_type)
5913 case POINTER:
5914 case FPOINTER:
5915 if (!alreadyAddressed)
5916 setup_fsr (src);
5917 emitpcode (POC_MOVFW, popCopyReg (pc_indf));
5918 break;
5920 case CPOINTER:
5921 assert (AOP_SIZE (src) == 2);
5922 mov2w_op (src, 0);
5923 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
5924 mov2w_op (src, 1);
5925 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5926 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
5927 call_libraryfunc ("__gptrget1");
5928 break;
5930 case GPOINTER:
5931 assert (AOP_SIZE (src) == 3);
5932 mov2w_op (src, 0);
5933 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
5934 mov2w_op (src, 1);
5935 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5936 mov2w_op (src, 2);
5937 call_libraryfunc ("__gptrget1");
5938 break;
5940 default:
5941 assert (!"unhandled pointer type");
5942 break;
5946 /*-----------------------------------------------------------------*/
5947 /* emitPtrByteSet - emits code to set a byte from src through a */
5948 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR). */
5949 /*-----------------------------------------------------------------*/
5950 static void
5951 emitPtrByteSet (operand * dst, int p_type, bool alreadyAddressed)
5953 FENTRY;
5954 switch (p_type)
5956 case POINTER:
5957 case FPOINTER:
5958 if (!alreadyAddressed)
5959 setup_fsr (dst);
5960 emitpcode (POC_MOVWF, popCopyReg (pc_indf));
5961 break;
5963 case CPOINTER:
5964 assert (!"trying to assign to __code pointer");
5965 break;
5967 case GPOINTER:
5968 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - 2));
5969 mov2w_op (dst, 0);
5970 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
5971 mov2w_op (dst, 1);
5972 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr));
5973 mov2w_op (dst, 2);
5974 call_libraryfunc ("__gptrput1");
5975 break;
5977 default:
5978 assert (!"unhandled pointer type");
5979 break;
5984 * Read data from address pointed by left to result.
5985 * For bitfields (blen != 0) does the corresponding bit masking
5986 * and zero/sign extensions.
5987 * For non-bitfields (blen == bstr == 0) just reads the number of
5988 * bytes determined by the size of result.
5990 static void
5991 emitPtrGet (operand * result, operand * left, int ptype, int blen, int bstr)
5993 /* emit call to __gptrget */
5994 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
5995 int offset = 0;
5996 int size, mask = 0;
5998 if (blen == 0)
6000 size = AOP_SIZE(result);
6002 else
6004 /* single byte field case (with mask): blen 2..7, blen + bstr 2..8 */
6005 /* single byte field case (full byte): blen 8, bstr 0 */
6006 /* multi byte field case: blen > 8, bstr 0 */
6008 /* bytes to move without masking */
6009 size = blen / 8;
6011 /* bits to mask in the last byte */
6012 blen = blen % 8;
6014 /* mask to apply */
6015 if (blen)
6017 mask = (((1UL << blen) - 1) << bstr) & 0x00ff;
6018 size++;
6022 assert (size > 0 && size <= 4);
6024 switch (ptype)
6026 case -1:
6027 while (size--)
6029 emitpcode (POC_MOVFW, popGet (AOP (left), offset));
6030 if (!size && blen)
6031 emitpcode (POC_ANDLW, popGetLit (mask));
6032 movwf (AOP (result), offset);
6033 if (size)
6034 offset++;
6036 goto manage_signs;
6038 case POINTER:
6039 case FPOINTER:
6040 assert (AOP_SIZE (left) == 2);
6041 setup_fsr (left);
6042 while (size--)
6044 emitpcode (POC_MOVFW, popCopyReg (pc_indf));
6045 if (!size && blen)
6046 emitpcode (POC_ANDLW, popGetLit (mask));
6047 movwf (AOP (result), offset);
6048 if (size)
6050 inc_fsr (1);
6051 offset++;
6054 goto manage_signs;
6056 case GPOINTER:
6057 assert (AOP_SIZE (left) == 3);
6058 mov2w_op (left, 0);
6059 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
6060 mov2w_op (left, 1);
6061 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6062 mov2w_op (left, 2);
6063 break;
6065 case CPOINTER:
6066 /* special case: assign from __code */
6067 assert (OP_IN_CODE_SPACE(left) || AOP_SIZE (left) == 2);
6068 mov2w_op (left, 0);
6069 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
6070 mov2w_op (left, 1);
6071 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6072 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
6073 break;
6075 default:
6076 assert (!"unhandled pointer type");
6079 /* This is for GPOINTER and CPOINTER only */
6081 call_libraryfunc (func[size]);
6083 if (blen)
6084 emitpcode (POC_ANDLW, popGetLit (mask));
6086 /* save result */
6087 movwf (AOP (result), --size);
6088 while (size--)
6090 emitpcode (POC_MOVFW, popRegFromIdx (Gstack_base_addr - offset++));
6091 movwf (AOP (result), size);
6092 } // while
6094 manage_signs:
6096 /* This is for all pointers */
6098 /* Handle the partial byte at the end */
6099 if (blen)
6101 if (bstr)
6102 AccRsh (popGet (AOP (result), offset), bstr, 1); /* zero extend the bitfield */
6104 if (!SPEC_USIGN (OP_SYM_ETYPE (left)))
6106 /* signed bitfield */
6107 emitpcode (POC_MOVLW, popGetLit (0x00ff << blen));
6108 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP (result), offset, FALSE, FALSE), blen - 1, 0));
6109 emitpcode (POC_IORWF, popGet (AOP (result), offset));
6113 if (AOP_SIZE(result) > ++offset)
6114 addSign (result, offset, !SPEC_USIGN (OP_SYM_ETYPE (left)));
6117 /*-----------------------------------------------------------------*/
6118 /* genUnpackBits - generates code for unpacking bits */
6119 /*-----------------------------------------------------------------*/
6120 static void
6121 genUnpackBits (operand * result, operand * left, int ptype, iCode * ifx)
6123 sym_link *etype; /* bitfield type information */
6124 unsigned blen; /* bitfield length */
6125 unsigned bstr; /* bitfield starting bit within byte */
6127 FENTRY;
6128 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6129 etype = getSpec (operandType (result));
6130 blen = SPEC_BLEN (etype);
6131 bstr = SPEC_BSTR (etype);
6133 /* single bit field case */
6134 if (blen == 1)
6136 if (ifx)
6138 /* that is for an if statement */
6139 pCodeOp *pcop;
6140 resolvedIfx rIfx;
6142 resolveIfx (&rIfx, ifx);
6143 if (ptype == -1) /* direct */
6144 pcop = newpCodeOpBit (aopGet (AOP (left), 0, FALSE, FALSE), bstr, 0);
6145 else
6147 setup_fsr (left);
6148 pcop = newpCodeOpBit (pc_indf->pcop.name, bstr, 0);
6150 emitpcode ((rIfx.condition) ? POC_BTFSC : POC_BTFSS, pcop);
6151 emitpcode (POC_GOTO, popGetLabel (rIfx.lbl->key));
6152 ifx->generated = TRUE;
6154 else
6157 * In case of a volatile bitfield read such as
6158 * (void)PORTCbits.RC3;
6159 * we end up having no result ...
6161 int haveResult = !!AOP_SIZE(result);
6163 if (haveResult)
6165 assert (!pic14_sameRegs (AOP (result), AOP (left)));
6166 emitpcode (POC_CLRF, popGet (AOP (result), 0));
6167 } // if
6169 switch (ptype)
6171 case -1:
6172 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP (left), 0, FALSE, FALSE), bstr, 0));
6173 /* If haveResult, adjust result below, otherwise: */
6174 if (!haveResult)
6176 /* Dummy instruction to allow bit-test above (volatile dummy bitfield read). */
6177 emitpcode (POC_MOVLW, popGetLit (0));
6178 } // if
6179 break;
6181 case POINTER:
6182 case FPOINTER:
6183 case GPOINTER:
6184 case CPOINTER:
6185 emitPtrByteGet (left, ptype, FALSE);
6186 if (haveResult)
6188 emitpcode (POC_ANDLW, popGetLit (1UL << bstr));
6189 emitSKPZ;
6190 /* adjust result below */
6191 } // if
6192 break;
6194 default:
6195 assert (!"unhandled pointer type");
6196 } // switch
6198 /* move sign-/zero extended bit to result */
6199 if (haveResult)
6201 if (SPEC_USIGN (OP_SYM_ETYPE (left)))
6202 emitpcode (POC_INCF, popGet (AOP (result), 0));
6203 else
6204 emitpcode (POC_DECF, popGet (AOP (result), 0));
6205 addSign (result, 1, !SPEC_USIGN (OP_SYM_ETYPE (left)));
6206 } // if
6209 else
6211 emitPtrGet (result, left, ptype, blen, bstr);
6215 #if 1
6216 /*-----------------------------------------------------------------*/
6217 /* genDataPointerGet - generates code when ptr offset is known */
6218 /*-----------------------------------------------------------------*/
6219 static void
6220 genDataPointerGet (operand * left, operand * result, iCode * ic)
6222 unsigned int size;
6223 int offset = 0;
6225 FENTRY;
6226 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6229 /* optimization - most of the time, left and result are the same
6230 * address, but different types. for the pic code, we could omit
6231 * the following
6233 aopOp (result, ic, TRUE);
6235 if (pic14_sameRegs (AOP (left), AOP (result)))
6236 goto release;
6238 DEBUGpic14_AopType (__LINE__, left, NULL, result);
6240 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
6242 size = AOP_SIZE (result);
6244 offset = 0;
6245 while (size--)
6247 emitpcode (POC_MOVFW, popGet (AOP (left), offset));
6248 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
6249 offset++;
6252 release:
6253 freeAsmop (left, NULL, ic, TRUE);
6254 freeAsmop (result, NULL, ic, TRUE);
6256 #endif
6258 /*-----------------------------------------------------------------*/
6259 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
6260 /*-----------------------------------------------------------------*/
6261 static void
6262 genNearPointerGet (operand * left, operand * result, iCode * ic)
6264 sym_link *ltype = operandType (left);
6265 sym_link *rtype = operandType (result);
6266 sym_link *retype = getSpec (rtype); /* bitfield type information */
6267 int direct = 0;
6269 FENTRY;
6270 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6273 aopOp (left, ic, FALSE);
6275 /* if left is rematerialisable and
6276 result is not bit variable type and
6277 the left is pointer to data space i.e
6278 lower 128 bytes of space */
6279 if (AOP_TYPE (left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
6280 !IS_BITVAR (retype) && PIC_IS_DATA_PTR (ltype))
6282 genDataPointerGet (left, result, ic);
6283 return;
6286 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6287 aopOp (result, ic, FALSE);
6289 /* Check if can access directly instead of via a pointer */
6290 if ((AOP_TYPE (left) == AOP_PCODE) && (AOP (left)->aopu.pcop->type == PO_IMMEDIATE))
6292 direct = 1;
6295 if (IS_BITFIELD (getSpec (operandType (result))))
6297 genUnpackBits (result, left, direct ? -1 : POINTER, ifxForOp (IC_RESULT (ic), ic));
6299 else
6301 emitPtrGet (result, left, direct ? -1 : POINTER, 0, 0);
6304 /* done */
6305 freeAsmop (left, NULL, ic, TRUE);
6306 freeAsmop (result, NULL, ic, TRUE);
6310 /*-----------------------------------------------------------------*/
6311 /* genGenPointerGet - gget value from generic pointer space */
6312 /*-----------------------------------------------------------------*/
6313 static void
6314 genGenPointerGet (operand * left, operand * result, iCode * ic)
6316 FENTRY;
6317 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6318 aopOp (left, ic, FALSE);
6319 aopOp (result, ic, FALSE);
6322 DEBUGpic14_AopType (__LINE__, left, NULL, result);
6324 if (IS_BITFIELD (getSpec (operandType (result))))
6326 genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT (ic), ic));
6328 else
6330 emitPtrGet (result, left, GPOINTER, 0, 0);
6333 freeAsmop (left, NULL, ic, TRUE);
6334 freeAsmop (result, NULL, ic, TRUE);
6338 /*-----------------------------------------------------------------*/
6339 /* genConstPointerGet - get value from const generic pointer space */
6340 /*-----------------------------------------------------------------*/
6341 static void
6342 genConstPointerGet (operand * left, operand * result, iCode * ic)
6344 //sym_link *retype = getSpec(operandType(result));
6345 #if 0
6346 symbol *albl, *blbl; //, *clbl;
6347 pCodeOp *pcop;
6348 #endif
6350 FENTRY;
6351 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6352 aopOp (left, ic, FALSE);
6353 aopOp (result, ic, FALSE);
6355 DEBUGpic14_AopType (__LINE__, left, NULL, result);
6357 DEBUGpic14_emitcode ("; ", " %d getting const pointer", __LINE__);
6359 if (IS_BITFIELD (getSpec (operandType (result))))
6361 genUnpackBits (result, left, CPOINTER, ifxForOp (IC_RESULT (ic), ic));
6363 else
6365 emitPtrGet (result, left, CPOINTER, 0, 0);
6368 freeAsmop (left, NULL, ic, TRUE);
6369 freeAsmop (result, NULL, ic, TRUE);
6373 /*-----------------------------------------------------------------*/
6374 /* genPointerGet - generate code for pointer get */
6375 /*-----------------------------------------------------------------*/
6376 static void
6377 genPointerGet (iCode * ic)
6379 operand *left, *result;
6380 sym_link *type, *etype;
6381 int p_type = -1;
6383 FENTRY;
6384 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6386 left = IC_LEFT (ic);
6387 result = IC_RESULT (ic);
6389 /* depending on the type of pointer we need to
6390 move it to the correct pointer register */
6391 type = operandType (left);
6392 etype = getSpec (type);
6394 if (IS_PTR_CONST (type))
6395 DEBUGpic14_emitcode ("; ***", "%d - const pointer", __LINE__);
6397 /* if left is of type of pointer then it is simple */
6398 if (IS_PTR (type) && !IS_FUNC (type->next))
6399 p_type = DCL_TYPE (type);
6400 else
6402 /* we have to go by the storage class */
6403 p_type = PTR_TYPE (SPEC_OCLS (etype));
6405 DEBUGpic14_emitcode ("; ***", "%d - resolve pointer by storage class", __LINE__);
6407 if (SPEC_OCLS (etype)->codesp)
6409 DEBUGpic14_emitcode ("; ***", "%d - cpointer", __LINE__);
6410 //p_type = CPOINTER ;
6412 else if (SPEC_OCLS (etype)->fmap && !SPEC_OCLS (etype)->paged)
6413 DEBUGpic14_emitcode ("; ***", "%d - fpointer", __LINE__);
6414 /*p_type = FPOINTER ; */
6415 else if (SPEC_OCLS (etype)->fmap && SPEC_OCLS (etype)->paged)
6416 DEBUGpic14_emitcode ("; ***", "%d - ppointer", __LINE__);
6417 /* p_type = PPOINTER; */
6418 else if (SPEC_OCLS (etype) == idata)
6419 DEBUGpic14_emitcode ("; ***", "%d - ipointer", __LINE__);
6420 /* p_type = IPOINTER; */
6421 else
6422 DEBUGpic14_emitcode ("; ***", "%d - pointer", __LINE__);
6423 /* p_type = POINTER ; */
6426 /* now that we have the pointer type we assign
6427 the pointer values */
6428 switch (p_type)
6431 case POINTER:
6432 case FPOINTER:
6433 //case IPOINTER:
6434 genNearPointerGet (left, result, ic);
6435 break;
6437 case PPOINTER:
6438 genPagedPointerGet(left,result,ic);
6439 break;
6441 case FPOINTER:
6442 genFarPointerGet (left,result,ic);
6443 break;
6445 case CPOINTER:
6446 genConstPointerGet (left, result, ic);
6447 break;
6449 case GPOINTER:
6450 genGenPointerGet (left, result, ic);
6451 break;
6452 default:
6453 assert (!"unhandled pointer type");
6454 break;
6460 * Write data from right to the address pointed by result.
6461 * For bitfields (blen != 0) does the corresponding bit masking
6462 * and zero/sign extensions.
6463 * For non-bitfields (blen == bstr == 0) just writes the number of
6464 * bytes determined by the size of right.
6466 static void
6467 emitPtrPut (operand * right, operand * result, int ptype, int blen, int bstr)
6469 /* emit call to __gptrput */
6470 char *func[] = { NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4" };
6471 int offset = 0;
6472 pCodeOp *temp = NULL;
6473 int litval = 0; /* source literal value (if AOP_LIT) */
6474 unsigned char mask = 0; /* bitmask within current byte */
6475 int size;
6476 symbol *lbl = NULL;
6478 if (blen == 0)
6480 size = AOP_SIZE(right);
6482 else
6484 /* single byte field case (with mask): blen 2..7, blen + bstr 2..8 */
6485 /* single byte field case (full byte): blen 8, bstr 0 */
6486 /* multi byte field case: blen > 8, bstr 0 */
6488 /* bytes to move without masking */
6489 size = blen / 8;
6491 /* bits to mask in the last byte */
6492 blen = blen % 8;
6494 /* If there was a partial byte at the end */
6495 if (blen)
6497 mask = ((unsigned char) (0xFF << (blen + bstr)) | (unsigned char) (0xFF >> (8 - bstr)));
6499 if (AOP_TYPE (right) == AOP_LIT)
6501 /* Case with partial byte and literal source
6503 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
6504 litval <<= bstr;
6505 litval >>= 8 * size;
6506 litval &= (~mask) & 0xff;
6508 else
6510 /* Case with a bitfield 1 < length <= 8 and arbitrary source */
6511 temp = popGetTempReg ();
6513 mov2w (AOP (right), size);
6514 emitpcode (POC_ANDLW, popGetLit ((1UL << blen) - 1));
6515 emitpcode (POC_MOVWF, temp);
6516 if (bstr)
6517 AccLsh (temp, bstr);
6520 /* Include the last byte into the size count */
6521 size++;
6525 /* The following assertion fails for
6526 * struct foo { char a; char b; } bar;
6527 * void demo(struct foo *dst, char c) { dst->b = c; }
6528 * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
6529 * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
6530 * of size 2.
6531 * The frontend seems to guarantee that IC_LEFT has the correct size,
6532 * it works fine both for larger and smaller types of `char c'.
6533 * */
6534 //assert (size == getSize(OP_SYM_ETYPE(result)));
6535 assert (size > 0 && size <= 4);
6537 switch (ptype)
6539 case -1:
6540 while (size--)
6542 if (size || !blen)
6544 if (AOP_TYPE (right) == AOP_LIT)
6545 emitpcode (POC_MOVLW, popGet (AOP (right), offset));
6546 else
6547 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
6548 movwf (AOP (result), offset);
6549 if (size)
6550 offset++;
6552 else
6554 emitpcode (POC_MOVFW, popGet (AOP (result), offset));
6555 if (AOP_TYPE (right) == AOP_LIT)
6557 if ((litval | mask) != 0x00ff)
6558 emitpcode (POC_ANDLW, popGetLit (mask));
6559 if (litval != 0x00)
6560 emitpcode (POC_IORLW, popGetLit (litval));
6562 else
6564 emitpcode (POC_ANDLW, popGetLit (mask));
6565 emitpcode (POC_IORFW, temp);
6567 movwf (AOP (result), offset);
6570 break;
6572 case GPOINTER:
6573 /* GPOINTER should point to data space, because code space is not writeable */
6574 if (!blen)
6576 /* For non-bitfields use the library functions.
6577 * They will silently ignore tries to write to code space.
6579 /* pass arguments */
6580 /* - value (MSB in Gstack_base_addr-2, growing downwards) */
6582 int off = size;
6583 int idx = 2;
6584 while (off--)
6586 mov2w_op (right, off);
6587 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
6590 /* - address */
6591 assert (AOP_SIZE (result) == 3);
6592 mov2w (AOP (result), 0);
6593 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
6594 mov2w (AOP (result), 1);
6595 emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr));
6596 mov2w (AOP (result), 2);
6597 call_libraryfunc (func[size]);
6598 break;
6601 /* For bitfields, manage the pointer as a data pointer */
6602 lbl = newiTempLabel (NULL);
6603 mov2w (AOP (result), 2);
6604 /* If result happends to be a remat, it may be a literal and mov2w doesn't set Z */
6605 emitpcode (POC_IORLW, popGetLit (0));
6606 emitSKPZ;
6607 if (pic->isEnhancedCore)
6608 emitpcode (POC_BRA, popGetLabel (lbl->key));
6609 else
6610 emitpcode (POC_GOTO, popGetLabel (lbl->key));
6612 case POINTER:
6613 case FPOINTER:
6614 setup_fsr (result);
6615 while (size--)
6617 if (size || !blen)
6619 if (AOP_TYPE (right) == AOP_LIT)
6620 emitpcode (POC_MOVLW, popGet (AOP (right), offset));
6621 else
6622 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
6623 emitpcode (POC_MOVWF, popCopyReg (pc_indf));
6624 if (size)
6626 inc_fsr (1);
6627 offset++;
6630 else
6632 emitpcode (POC_MOVFW, popCopyReg (pc_indf));
6633 if (AOP_TYPE (right) == AOP_LIT)
6635 if ((litval | mask) != 0x00ff)
6636 emitpcode (POC_ANDLW, popGetLit (mask));
6637 if (litval != 0x00)
6638 emitpcode (POC_IORLW, popGetLit (litval));
6640 else
6642 emitpcode (POC_ANDLW, popGetLit (mask));
6643 emitpcode (POC_IORFW, temp);
6645 emitpcode (POC_MOVWF, popCopyReg (pc_indf));
6648 if (lbl)
6649 emitpLabel (lbl->key);
6650 break;
6652 case CPOINTER:
6653 assert (!"trying to assign via pointer to __code space");
6654 break;
6656 default:
6657 assert (!"unhandled pointer type");
6660 if (temp)
6661 popReleaseTempReg (temp);
6664 /*-----------------------------------------------------------------*/
6665 /* genPackBits - generates code for packed bit storage */
6666 /*-----------------------------------------------------------------*/
6667 static void
6668 genPackBits (sym_link * etype, operand * result, operand * right, int p_type)
6670 unsigned blen; /* bitfield length */
6671 unsigned bstr; /* bitfield starting bit within byte */
6673 FENTRY;
6674 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6676 blen = SPEC_BLEN (etype);
6677 bstr = SPEC_BSTR (etype);
6679 /* single bit field case */
6680 if (blen == 1)
6682 pCodeOp *pcop;
6684 if (AOP_TYPE (right) == AOP_LIT)
6686 /* Case with a bitfield length <8 and literal source */
6687 int lit = (int) ulFromVal (AOP (right)->aopu.aop_lit);
6689 switch (p_type)
6691 case -1:
6692 if (AOP (result)->type == AOP_PCODE)
6693 pcop = newpCodeOpBit (aopGet (AOP (result), 0, FALSE, FALSE), bstr, 0);
6694 else
6695 pcop = popGet (AOP (result), 0);
6696 emitpcode (lit ? POC_BSF : POC_BCF, pcop);
6697 break;
6699 case POINTER:
6700 case FPOINTER:
6701 setup_fsr (result);
6702 emitpcode (lit ? POC_BSF : POC_BCF, newpCodeOpBit (PCOP (pc_indf)->name, bstr, 0));
6703 break;
6705 case CPOINTER:
6706 assert (!"trying to assign to bitfield via pointer to __code space");
6707 break;
6709 case GPOINTER:
6710 emitPtrByteGet (result, p_type, FALSE);
6711 if (lit)
6713 emitpcode (POC_IORLW, newpCodeOpLit (1UL << bstr));
6715 else
6717 emitpcode (POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
6719 emitPtrByteSet (result, p_type, TRUE);
6720 break;
6722 default:
6723 assert (!"unhandled pointer type");
6724 break;
6725 } // switch (p_type)
6727 else
6729 /* right is no literal */
6731 switch (p_type)
6733 case -1:
6734 /* Note more efficient code, of pre clearing bit then only setting it if required,
6735 * can only be done if it is known that the result is not a SFR */
6736 if (AOP (result)->type == AOP_PCODE)
6737 pcop = newpCodeOpBit (aopGet (AOP (result), 0, FALSE, FALSE), bstr, 0);
6738 else
6739 pcop = popGet (AOP (result), 0);
6740 emitpcode (POC_RRFW, popGet (AOP (right), 0));
6741 emitSKPC;
6742 emitpcode (POC_BCF, pcop);
6743 emitSKPNC;
6744 emitpcode (POC_BSF, pcop);
6745 break;
6747 case POINTER:
6748 case FPOINTER:
6749 case GPOINTER:
6750 emitPtrByteGet (result, p_type, FALSE);
6751 emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP (right), 0, FALSE, FALSE), 0, 0));
6752 emitpcode (POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
6753 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP (right), 0, FALSE, FALSE), 0, 0));
6754 emitpcode (POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
6755 emitPtrByteSet (result, p_type, TRUE);
6756 break;
6758 case CPOINTER:
6759 assert (!"trying to assign to bitfield via pointer to __code space");
6760 break;
6762 default:
6763 assert (!"unhandled pointer type");
6764 break;
6765 } // switch
6766 } // if (AOP(right)->type != AOP_LIT)
6768 else
6770 emitPtrPut (right, result, p_type, blen, bstr);
6774 /*-----------------------------------------------------------------*/
6775 /* genDataPointerSet - remat pointer to data space */
6776 /*-----------------------------------------------------------------*/
6777 static void
6778 genDataPointerSet (operand * right, operand * result, iCode * ic)
6780 int size = 0;
6781 int offset = 0;
6782 sym_link *rtype = operandType(right);
6784 FENTRY;
6785 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6786 aopOp (right, ic, FALSE);
6788 assert (IS_SYMOP (result));
6789 assert (IS_PTR (OP_SYM_TYPE (result)));
6792 * Determine size from right operand (not result):
6793 * The result might be a rematerialized pointer to (the first field in) a struct,
6794 * which then assumes the type (and size) of the struct rather than the first field.
6796 size = AOP_SIZE(right);
6798 /*test the right operand has a pointer value*/
6799 if ((AOP_TYPE(right) == AOP_PCODE) && IS_PTR(rtype))
6801 while (size--)
6803 emitpcode(POC_MOVLW, popGetAddr(AOP(right), size, 0));
6804 emitpcode(POC_MOVWF, popGet(AOP(result), size));
6807 else
6809 // tsd, was l+1 - the underline `_' prefix was being stripped
6810 while (size--)
6812 emitpComment ("%s:%u: size=%d, offset=%d, AOP_TYPE(res)=%d", __FILE__, __LINE__, size, offset,
6813 AOP_TYPE (result));
6815 if (AOP_TYPE (right) == AOP_LIT)
6817 unsigned int lit = pic14aopLiteral (AOP (IC_RIGHT (ic))->aopu.aop_lit, offset);
6818 //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
6819 if (lit & 0xff)
6821 emitpcode (POC_MOVLW, popGetLit (lit & 0xff));
6822 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
6824 else
6826 emitpcode (POC_CLRF, popGet (AOP (result), offset));
6829 else
6831 //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
6832 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
6833 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
6835 offset++;
6839 freeAsmop (right, NULL, ic, TRUE);
6840 freeAsmop (result, NULL, ic, TRUE);
6843 /*-----------------------------------------------------------------*/
6844 /* genNearPointerSet - pic14_emitcode for near pointer put */
6845 /*-----------------------------------------------------------------*/
6846 static void
6847 genNearPointerSet (operand * right, operand * result, iCode * ic)
6849 sym_link *ptype = operandType (result);
6850 sym_link *retype = getSpec (operandType (right));
6851 sym_link *letype = getSpec (ptype);
6852 int direct = 0;
6855 FENTRY;
6856 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6857 aopOp (result, ic, FALSE);
6859 #if 1
6860 /* if the result is rematerializable &
6861 in data space & not a bit variable */
6862 //if (AOP_TYPE(result) == AOP_IMMD &&
6863 if (AOP_TYPE (result) == AOP_PCODE && PIC_IS_DATA_PTR (ptype) && !IS_BITVAR (retype) && !IS_BITVAR (letype))
6865 genDataPointerSet (right, result, ic);
6866 return;
6868 #endif
6870 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6871 aopOp (right, ic, FALSE);
6872 DEBUGpic14_AopType (__LINE__, NULL, right, result);
6874 /* Check if can access directly instead of via a pointer */
6875 if ((AOP_TYPE (result) == AOP_PCODE) && (AOP (result)->aopu.pcop->type == PO_IMMEDIATE))
6877 direct = 1;
6880 if (IS_BITFIELD (letype))
6882 genPackBits (letype, result, right, direct ? -1 : POINTER);
6884 else
6886 emitPtrPut (right, result, direct ? -1 : POINTER, 0, 0);
6889 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6890 /* done */
6892 freeAsmop (right, NULL, ic, TRUE);
6893 freeAsmop (result, NULL, ic, TRUE);
6896 /*-----------------------------------------------------------------*/
6897 /* genGenPointerSet - set value from generic pointer space */
6898 /*-----------------------------------------------------------------*/
6899 static void
6900 genGenPointerSet (operand * right, operand * result, iCode * ic)
6902 sym_link *retype = getSpec (operandType (result));
6904 FENTRY;
6905 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6906 aopOp (right, ic, FALSE);
6907 aopOp (result, ic, FALSE);
6910 DEBUGpic14_AopType (__LINE__, right, NULL, result);
6912 if (IS_BITFIELD (retype))
6914 genPackBits (retype, result, right, GPOINTER);
6916 else
6918 emitPtrPut (right, result, GPOINTER, 0, 0);
6921 freeAsmop (right, NULL, ic, TRUE);
6922 freeAsmop (result, NULL, ic, TRUE);
6925 /*-----------------------------------------------------------------*/
6926 /* genPointerSet - stores the value into a pointer location */
6927 /*-----------------------------------------------------------------*/
6928 static void
6929 genPointerSet (iCode * ic)
6931 operand *right, *result;
6932 sym_link *type, *etype;
6933 int p_type;
6935 FENTRY;
6936 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
6938 right = IC_RIGHT (ic);
6939 result = IC_RESULT (ic);
6941 /* depending on the type of pointer we need to
6942 move it to the correct pointer register */
6943 type = operandType (result);
6944 etype = getSpec (type);
6945 /* if left is of type of pointer then it is simple */
6946 if (IS_PTR (type) && !IS_FUNC (type->next))
6948 p_type = DCL_TYPE (type);
6950 else
6952 /* we have to go by the storage class */
6953 p_type = PTR_TYPE (SPEC_OCLS (etype));
6955 /* if (SPEC_OCLS(etype)->codesp ) { */
6956 /* p_type = CPOINTER ; */
6957 /* } */
6958 /* else */
6959 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6960 /* p_type = FPOINTER ; */
6961 /* else */
6962 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6963 /* p_type = PPOINTER ; */
6964 /* else */
6965 /* if (SPEC_OCLS(etype) == idata ) */
6966 /* p_type = IPOINTER ; */
6967 /* else */
6968 /* p_type = POINTER ; */
6971 /* now that we have the pointer type we assign
6972 the pointer values */
6973 switch (p_type)
6975 case POINTER:
6976 case FPOINTER:
6977 //case IPOINTER:
6978 genNearPointerSet (right, result, ic);
6979 break;
6981 case PPOINTER:
6982 genPagedPointerSet (right,result,ic);
6983 break;
6985 case FPOINTER:
6986 genFarPointerSet (right,result,ic);
6987 break;
6989 case GPOINTER:
6990 genGenPointerSet (right, result, ic);
6991 break;
6993 default:
6994 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "genPointerSet: illegal pointer type");
6995 exit (1);
6999 /*-----------------------------------------------------------------*/
7000 /* genIfx - generate code for Ifx statement */
7001 /*-----------------------------------------------------------------*/
7002 static void
7003 genIfx (iCode * ic, iCode * popIc)
7005 operand *cond = IC_COND (ic);
7006 int isbit = 0;
7008 FENTRY;
7009 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
7011 aopOp (cond, ic, FALSE);
7013 /* get the value into acc */
7014 if (AOP_TYPE (cond) != AOP_CRY)
7015 pic14_toBoolean (cond);
7016 else
7017 isbit = 1;
7019 /* if there was something to be popped then do it */
7020 if (popIc)
7021 genIpop (popIc);
7023 if (isbit)
7025 /* This assumes that CARRY is set iff cond is true */
7026 if (IC_TRUE (ic))
7028 assert (!IC_FALSE (ic));
7029 emitpcode (POC_BTFSC, popGet (AOP (cond), 0));
7030 //emitSKPNC;
7031 emitpcode (POC_GOTO, popGetLabel (IC_TRUE (ic)->key));
7033 else
7035 assert (IC_FALSE (ic));
7036 emitpcode (POC_BTFSS, popGet (AOP (cond), 0));
7037 //emitSKPC;
7038 emitpcode (POC_GOTO, popGetLabel (IC_FALSE (ic)->key));
7040 if (0)
7042 static int hasWarned = 0;
7043 if (!hasWarned)
7045 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n",
7046 ic->filename, ic->lineno);
7047 hasWarned = 1;
7051 else
7053 /* now Z is set iff !cond */
7054 if (IC_TRUE (ic))
7056 assert (!IC_FALSE (ic));
7057 emitSKPZ;
7058 emitpcode (POC_GOTO, popGetLabel (IC_TRUE (ic)->key));
7060 else
7062 emitSKPNZ;
7063 emitpcode (POC_GOTO, popGetLabel (IC_FALSE (ic)->key));
7067 ic->generated = TRUE;
7069 /* the result is now in the accumulator */
7070 freeAsmop (cond, NULL, ic, TRUE);
7073 /*-----------------------------------------------------------------*/
7074 /* genAddrOf - generates code for address of */
7075 /*-----------------------------------------------------------------*/
7076 static void
7077 genAddrOf (iCode * ic)
7079 operand *right, *result, *left;
7080 int size, offset;
7082 FENTRY;
7083 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
7086 //aopOp(IC_RESULT(ic),ic,FALSE);
7088 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7089 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7090 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7092 DEBUGpic14_AopType (__LINE__, left, right, result);
7093 assert (IS_SYMOP (left));
7095 /* sanity check: generic pointers to code space are not yet supported,
7096 * pionters to codespace must not be assigned addresses of __data values. */
7097 #if 0
7098 fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL (result)->name, OP_SYMBOL (left)->name);
7099 fprintf (stderr, "result->type : ");
7100 printTypeChain (OP_SYM_TYPE (result), stderr);
7101 fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE (result)))),
7102 IS_CODEPTR (OP_SYM_TYPE (result)), IS_PTR_CONST (OP_SYM_TYPE (result)));
7103 fprintf (stderr, "result->etype: ");
7104 printTypeChain (OP_SYM_ETYPE (result), stderr);
7105 fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_ETYPE (result)))),
7106 IS_CODEPTR (OP_SYM_ETYPE (result)), IS_PTR_CONST (OP_SYM_ETYPE (result)));
7107 fprintf (stderr, "left->type : ");
7108 printTypeChain (OP_SYM_TYPE (left), stderr);
7109 fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE (left)))),
7110 IS_CODEPTR (OP_SYM_TYPE (left)), IS_PTR_CONST (OP_SYM_TYPE (left)));
7111 fprintf (stderr, "left->etype : ");
7112 printTypeChain (OP_SYM_ETYPE (left), stderr);
7113 fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_ETYPE (left)))),
7114 IS_CODEPTR (OP_SYM_ETYPE (left)), IS_PTR_CONST (OP_SYM_ETYPE (left)));
7115 #endif
7117 if (IS_SYMOP (result) && IS_CODEPTR (OP_SYM_TYPE (result)) && !IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE (left)))))
7119 fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
7120 IS_SYMOP (result) ? OP_SYMBOL (result)->name : "unknown", OP_SYMBOL (left)->name);
7122 else if (IS_SYMOP (result) && !IS_CODEPTR (OP_SYM_TYPE (result)) && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE (left)))))
7124 fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
7125 IS_SYMOP (result) ? OP_SYMBOL (result)->name : "unknown", OP_SYMBOL (left)->name);
7128 size = AOP_SIZE (IC_RESULT (ic));
7129 if (IS_SYMOP (result) && IS_GENPTR (OP_SYM_TYPE (result)))
7131 /* strip tag */
7132 if (size > GPTRSIZE - 1)
7133 size = GPTRSIZE - 1;
7135 offset = 0;
7137 while (size--)
7139 /* fixing bug #863624, reported from (errolv) */
7140 emitpcode (POC_MOVLW, popGetImmd (OP_SYMBOL (left)->rname, offset, 0, IS_FUNC (OP_SYM_TYPE (left))));
7141 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
7143 #if 0
7144 emitpcode (POC_MOVLW, popGet (AOP (left), offset));
7145 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
7146 #endif
7147 offset++;
7150 if (IS_SYMOP (result) && IS_GENPTR (OP_SYM_TYPE (result)))
7152 /* provide correct tag */
7153 int isCode = IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE (left))));
7154 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
7155 movwf (AOP (result), 2);
7158 freeAsmop (left, NULL, ic, FALSE);
7159 freeAsmop (result, NULL, ic, TRUE);
7163 /*-----------------------------------------------------------------*/
7164 /* genAssign - generate code for assignment */
7165 /*-----------------------------------------------------------------*/
7166 static void
7167 genAssign (iCode * ic)
7169 operand *result, *right;
7170 int size, offset, know_W;
7171 unsigned long lit = 0L;
7173 result = IC_RESULT (ic);
7174 right = IC_RIGHT (ic);
7176 FENTRY;
7177 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
7179 /* if they are the same */
7180 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7181 return;
7183 aopOp (right, ic, FALSE);
7184 aopOp (result, ic, TRUE);
7186 DEBUGpic14_AopType (__LINE__, NULL, right, result);
7188 /* if they are the same registers */
7189 if (pic14_sameRegs (AOP (right), AOP (result)))
7190 goto release;
7192 /* special case: assign from __code */
7193 if (OP_IN_CODE_SPACE(right))
7195 emitpComment ("genAssign from CODESPACE");
7196 genConstPointerGet (right, result, ic);
7197 goto release;
7200 /* just for symmetry reasons... */
7201 if (!IS_ITEMP (result) && IS_SYMOP (result) && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE (result)))))
7203 assert (!"cannot write to CODESPACE");
7206 /* if the result is a bit */
7207 if (AOP_TYPE (result) == AOP_CRY)
7210 /* if the right size is a literal then
7211 we know what the value is */
7212 if (AOP_TYPE (right) == AOP_LIT)
7215 emitpcode ((((int) operandLitValue (right)) ? POC_BSF : POC_BCF), popGet (AOP (result), 0));
7217 if (((int) operandLitValue (right)))
7218 pic14_emitcode ("bsf", "(%s >> 3),(%s & 7)", AOP (result)->aopu.aop_dir, AOP (result)->aopu.aop_dir);
7219 else
7220 pic14_emitcode ("bcf", "(%s >> 3),(%s & 7)", AOP (result)->aopu.aop_dir, AOP (result)->aopu.aop_dir);
7221 goto release;
7224 /* the right is also a bit variable */
7225 if (AOP_TYPE (right) == AOP_CRY)
7227 emitpcode (POC_BCF, popGet (AOP (result), 0));
7228 emitpcode (POC_BTFSC, popGet (AOP (right), 0));
7229 emitpcode (POC_BSF, popGet (AOP (result), 0));
7231 pic14_emitcode ("bcf", "(%s >> 3),(%s & 7)", AOP (result)->aopu.aop_dir, AOP (result)->aopu.aop_dir);
7232 pic14_emitcode ("btfsc", "(%s >> 3),(%s & 7)", AOP (right)->aopu.aop_dir, AOP (right)->aopu.aop_dir);
7233 pic14_emitcode ("bsf", "(%s >> 3),(%s & 7)", AOP (result)->aopu.aop_dir, AOP (result)->aopu.aop_dir);
7234 goto release;
7237 /* we need to or */
7238 emitpcode (POC_BCF, popGet (AOP (result), 0));
7239 pic14_toBoolean (right);
7240 emitSKPZ;
7241 emitpcode (POC_BSF, popGet (AOP (result), 0));
7242 //aopPut(AOP(result),"a",0);
7243 goto release;
7246 /* bit variables done */
7247 /* general case */
7248 size = AOP_SIZE (result);
7249 offset = 0;
7250 if (AOP_TYPE (right) == AOP_DIR && (AOP_TYPE (result) == AOP_REG) && size == 1)
7252 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
7253 if (aopIdx (AOP (result), 0) == 4)
7255 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
7256 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
7257 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
7258 goto release;
7260 else
7261 DEBUGpic14_emitcode ("; WARNING", "%s %d ignoring register storage", __FUNCTION__, __LINE__);
7264 if (size > AOP_SIZE(right))
7265 size = AOP_SIZE(right);
7266 know_W = -1;
7267 while (size--)
7270 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
7271 if (AOP_TYPE (right) == AOP_LIT)
7273 lit = (unsigned long) pic14aopLiteral (AOP (right)->aopu.aop_lit, offset) & 0x0ff;
7274 if (lit & 0xff)
7276 if (know_W != (int) (lit & 0xff))
7277 emitpcode (POC_MOVLW, popGetLit (lit & 0xff));
7278 know_W = lit & 0xff;
7279 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
7281 else
7282 emitpcode (POC_CLRF, popGet (AOP (result), offset));
7285 else if (AOP_TYPE (right) == AOP_CRY)
7287 emitpcode (POC_CLRF, popGet (AOP (result), offset));
7288 if (offset == 0)
7290 emitpcode (POC_BTFSS, popGet (AOP (right), 0));
7291 emitpcode (POC_INCF, popGet (AOP (result), 0));
7294 else
7296 mov2w_op (right, offset);
7297 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
7300 offset++;
7303 /* now (zero-/sign) extend the result to its size */
7304 if (AOP_SIZE(result) > offset)
7305 addSign (result, offset, !SPEC_USIGN (operandType (right)));
7307 release:
7308 freeAsmop (right, NULL, ic, FALSE);
7309 freeAsmop (result, NULL, ic, TRUE);
7312 /*-----------------------------------------------------------------*/
7313 /* genJumpTab - generates code for jump table */
7314 /*-----------------------------------------------------------------*/
7315 static void
7316 genJumpTab (iCode * ic)
7318 symbol *jtab;
7319 char *l;
7321 FENTRY;
7322 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
7324 aopOp (IC_JTCOND (ic), ic, FALSE);
7325 /* get the condition into accumulator */
7326 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
7327 MOVA (l);
7328 /* multiply by three */
7329 pic14_emitcode ("add", "a,acc");
7330 pic14_emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
7332 jtab = newiTempLabel (NULL);
7333 pic14_emitcode ("mov", "dptr,#%05d_DS_", labelKey2num (jtab->key));
7334 pic14_emitcode ("jmp", "@a+dptr");
7335 pic14_emitcode ("", "%05d_DS_:", labelKey2num (jtab->key));
7337 emitpcode (POC_MOVLW, popGetHighLabel (jtab->key));
7338 emitpcode (POC_MOVWF, popCopyReg (&pc_pclath));
7339 emitpcode (POC_MOVLW, popGetLabel (jtab->key));
7340 emitpcode (POC_ADDFW, popGet (AOP (IC_JTCOND (ic)), 0));
7341 emitSKPNC;
7342 emitpcode (POC_INCF, popCopyReg (&pc_pclath));
7343 emitpcode (POC_MOVWF, popCopyReg (&pc_pcl));
7344 emitpLabel (jtab->key);
7346 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7348 /* now generate the jump labels */
7349 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab; jtab = setNextItem (IC_JTLABELS (ic)))
7351 pic14_emitcode ("ljmp", "%05d_DS_", labelKey2num (jtab->key));
7352 emitpcode (POC_GOTO, popGetLabel (jtab->key));
7358 /*-----------------------------------------------------------------*/
7359 /* genCast - gen code for casting */
7360 /*-----------------------------------------------------------------*/
7361 static void
7362 genCast (iCode * ic)
7364 operand *result = IC_RESULT (ic);
7365 sym_link *restype = operandType (result);
7366 sym_link *rtype = operandType (IC_RIGHT (ic));
7367 operand *right = IC_RIGHT (ic);
7368 int size, offset;
7370 FENTRY;
7371 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
7372 /* if they are equivalent then do nothing */
7373 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7374 return;
7376 aopOp (right, ic, FALSE);
7377 aopOp (result, ic, FALSE);
7379 DEBUGpic14_AopType (__LINE__, NULL, right, result);
7381 /* if the result is a bit */
7382 if (AOP_TYPE (result) == AOP_CRY)
7384 assert (!"assigning to bit variables is not supported");
7387 if ((AOP_TYPE (right) == AOP_CRY) && (AOP_TYPE (result) == AOP_REG))
7389 int offset = 1;
7390 size = AOP_SIZE (result);
7392 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
7394 emitpcode (POC_CLRF, popGet (AOP (result), 0));
7395 emitpcode (POC_BTFSC, popGet (AOP (right), 0));
7396 emitpcode (POC_INCF, popGet (AOP (result), 0));
7398 while (size--)
7399 emitpcode (POC_CLRF, popGet (AOP (result), offset++));
7401 goto release;
7404 if (IS_BOOL (operandType (result)))
7406 pic14_toBoolean (right);
7407 emitSKPZ;
7408 emitpcode (POC_MOVLW, popGetLit (1));
7409 emitpcode (POC_MOVWF, popGet (AOP (result), 0));
7410 goto release;
7413 if ((IS_PTR (restype) || IS_PTR(rtype)
7414 || (AOP_TYPE (right) == AOP_PCODE && AOP (right)->aopu.pcop->type == PO_IMMEDIATE)) && !IS_INTEGRAL(rtype))
7416 operand *result = IC_RESULT (ic);
7417 //operand *left = IC_LEFT(ic);
7418 operand *right = IC_RIGHT (ic);
7419 int tag = 0xff, isAddr = 0;
7421 /* copy common part */
7422 int max, size = AOP_SIZE (result);
7423 if (size > AOP_SIZE (right))
7424 size = AOP_SIZE (right);
7425 DEBUGpic14_emitcode ("; ***", "%s %d (size=%d)", __FUNCTION__, __LINE__, size);
7427 /* warn if we discard generic opinter tag */
7428 if (!IS_GENPTR (restype) && IS_GENPTR (rtype) && (AOP_SIZE (result) < AOP_SIZE (right)))
7430 //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
7431 } // if
7433 if ((IS_SYMOP(right) && OP_SYMBOL(right)->remat) || IS_FUNC(operandType(right)))
7434 isAddr = 1;
7436 max = size;
7437 while (size--)
7439 if (isAddr)
7440 mov2w_op (right, size);
7441 else
7442 emitpcode (POC_MOVFW, popGet (AOP (right), size));
7443 movwf (AOP (result), size);
7444 } // while
7446 size = max;
7447 while (size < GPTRSIZE - 1 && AOP_SIZE(result) > size)
7448 emitpcode (POC_CLRF, popGet (AOP (result), size++));
7450 /* upcast into generic pointer type? */
7451 // if (IS_GENPTR (restype) && (size < AOP_SIZE (result)) && (!IS_GENPTR (rtype) || AOP_SIZE (right) < GPTRSIZE))
7452 if (size == GPTRSIZE - 1 && AOP_SIZE(result) > size)
7454 //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
7455 if (IS_PTR (rtype))
7457 switch (DCL_TYPE (rtype))
7459 case POINTER: /* __data */
7460 case FPOINTER: /* __data */
7461 assert (AOP_SIZE (right) == 2);
7462 tag = GPTRTAG_DATA;
7463 break;
7465 case CPOINTER: /* __code */
7466 assert (AOP_SIZE (right) == 2);
7467 tag = GPTRTAG_CODE;
7468 break;
7470 case GPOINTER: /* unknown destination, __data or __code */
7471 /* assume __data space (address of immediate) */
7472 assert (AOP_TYPE (right) == AOP_PCODE && AOP (right)->aopu.pcop->type == PO_IMMEDIATE);
7473 if (AOP (right)->code)
7474 tag = GPTRTAG_CODE;
7475 else
7476 tag = GPTRTAG_DATA;
7477 break;
7479 default:
7480 assert (!"unhandled pointer type");
7481 } // switch
7482 DEBUGpic14_emitcode ("; ***", "%s %d (tag=%d)", __FUNCTION__, __LINE__, tag);
7484 else if (AOP_TYPE (right) == AOP_PCODE && AOP (right)->aopu.pcop->type == PO_IMMEDIATE)
7486 if (AOP (right)->code)
7487 tag = GPTRTAG_CODE;
7488 else
7489 tag = GPTRTAG_DATA;
7490 DEBUGpic14_emitcode ("; ***", "%s %d (tag=%d)", __FUNCTION__, __LINE__, tag);
7492 else
7494 /* convert other values into pointers to __data space */
7495 tag = GPTRTAG_DATA;
7496 DEBUGpic14_emitcode ("; ***", "%s %d (tag=%d)", __FUNCTION__, __LINE__, tag);
7499 if (tag == 0)
7501 emitpcode (POC_CLRF, popGet (AOP (result), size++));
7503 else
7505 emitpcode (POC_MOVLW, popGetLit (tag));
7506 movwf (AOP (result), size++);
7509 addSign (result, size, 0);
7510 goto release;
7513 /* if they are the same size : or less */
7514 if (AOP_SIZE (result) <= AOP_SIZE (right))
7517 /* if they are in the same place */
7518 if (pic14_sameRegs (AOP (right), AOP (result)))
7519 goto release;
7521 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
7522 if (IS_PTR_CONST (rtype))
7523 DEBUGpic14_emitcode ("; ***", "%d - right is const pointer", __LINE__);
7524 if (IS_PTR_CONST (operandType (IC_RESULT (ic))))
7525 DEBUGpic14_emitcode ("; ***", "%d - result is const pointer", __LINE__);
7527 if ((AOP_TYPE (right) == AOP_PCODE) && AOP (right)->aopu.pcop->type == PO_IMMEDIATE)
7529 emitpcode (POC_MOVLW, popGetAddr (AOP (right), 0, 0));
7530 emitpcode (POC_MOVWF, popGet (AOP (result), 0));
7531 emitpcode (POC_MOVLW, popGetAddr (AOP (right), 1, 0));
7532 emitpcode (POC_MOVWF, popGet (AOP (result), 1));
7533 if (AOP_SIZE (result) < 2)
7534 fprintf (stderr, "%d -- result is not big enough to hold a ptr\n", __LINE__);
7537 else
7540 /* if they in different places then copy */
7541 size = AOP_SIZE (result);
7542 offset = 0;
7543 while (size--)
7545 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
7546 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
7548 //aopPut(AOP(result),
7549 // aopGet(AOP(right),offset,FALSE,FALSE),
7550 // offset);
7552 offset++;
7555 goto release;
7558 /* so we now know that the size of destination is greater
7559 than the size of the source. */
7561 /* we move to result for the size of source */
7562 size = AOP_SIZE (right);
7563 offset = 0;
7564 while (size--)
7566 emitpcode (POC_MOVFW, popGet (AOP (right), offset));
7567 emitpcode (POC_MOVWF, popGet (AOP (result), offset));
7568 offset++;
7571 addSign (result, AOP_SIZE (right), !SPEC_USIGN (rtype));
7573 release:
7574 freeAsmop (right, NULL, ic, TRUE);
7575 freeAsmop (result, NULL, ic, TRUE);
7579 /*-----------------------------------------------------------------*/
7580 /* genDjnz - generate decrement & jump if not zero instruction */
7581 /*-----------------------------------------------------------------*/
7582 static int
7583 genDjnz (iCode * ic, iCode * ifx)
7585 FENTRY;
7586 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
7588 if (!ifx)
7589 return 0;
7591 /* if the if condition has a false label
7592 then we cannot save */
7593 if (IC_FALSE (ifx))
7594 return 0;
7596 /* if the minus is not of the form
7597 a = a - 1 */
7598 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) || !IS_OP_LITERAL (IC_RIGHT (ic)))
7599 return 0;
7601 if (operandLitValue (IC_RIGHT (ic)) != 1)
7602 return 0;
7604 /* if the size of this greater than one then no
7605 saving */
7606 if (getSize (operandType (IC_RESULT (ic))) > 1)
7607 return 0;
7609 /* otherwise we can save BIG */
7610 aopOp (IC_RESULT (ic), ic, FALSE);
7612 emitpcode (POC_DECFSZ, popGet (AOP (IC_RESULT (ic)), 0));
7613 emitpcode (POC_GOTO, popGetLabel (IC_TRUE (ifx)->key));
7615 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7616 ifx->generated = TRUE;
7617 return 1;
7620 /*-----------------------------------------------------------------*/
7621 /* genReceive - generate code for a receive iCode */
7622 /*-----------------------------------------------------------------*/
7623 static void
7624 genReceive (iCode * ic)
7626 FENTRY;
7627 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__, __LINE__);
7629 if (isOperandInFarSpace (IC_RESULT (ic)) && (OP_SYMBOL (IC_RESULT (ic))->isspilt || IS_TRUE_SYMOP (IC_RESULT (ic))))
7632 int size = getSize (operandType (IC_RESULT (ic)));
7633 int offset = fReturnSizePic - size;
7634 while (size--)
7636 pic14_emitcode ("push", "%s", (strcmp (fReturn[fReturnSizePic - offset - 1], "a") ?
7637 fReturn[fReturnSizePic - offset - 1] : "acc"));
7638 offset++;
7640 aopOp (IC_RESULT (ic), ic, FALSE);
7641 size = AOP_SIZE (IC_RESULT (ic));
7642 offset = 0;
7643 while (size--)
7645 pic14_emitcode ("pop", "acc");
7646 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
7650 else
7652 _G.accInUse++;
7653 aopOp (IC_RESULT (ic), ic, FALSE);
7654 _G.accInUse--;
7655 GpseudoStkPtr = ic->parmBytes; // address used arg on stack
7656 assignResultValue (ic);
7659 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7662 /*-----------------------------------------------------------------*/
7663 /* genDummyRead - generate code for dummy read of volatiles */
7664 /*-----------------------------------------------------------------*/
7665 static void
7666 genDummyRead (iCode * ic)
7668 FENTRY;
7669 pic14_emitcode ("; genDummyRead", "");
7670 pic14_emitcode ("; not implemented", "");
7672 ic = ic;
7675 /*-----------------------------------------------------------------*/
7676 /* genpic14Code - generate code for pic14 based controllers */
7677 /*-----------------------------------------------------------------*/
7679 * At this point, ralloc.c has gone through the iCode and attempted
7680 * to optimize in a way suitable for a PIC. Now we've got to generate
7681 * PIC instructions that correspond to the iCode.
7683 * Once the instructions are generated, we'll pass through both the
7684 * peep hole optimizer and the pCode optimizer.
7685 *-----------------------------------------------------------------*/
7687 void
7688 genpic14Code (iCode * lic)
7690 iCode *ic;
7691 int cln = 0;
7692 const char *cline;
7694 FENTRY;
7696 pic = pic14_getPIC();
7698 pb = newpCodeChain (GcurMemmap, 0, newpCodeCharP ("; Starting pCode block"));
7699 addpBlock (pb);
7701 /* if debug information required */
7702 if (options.debug && debugFile && currFunc)
7704 debugFile->writeFunction (currFunc, lic);
7708 for (ic = lic; ic; ic = ic->next)
7710 initGenLineElement ();
7712 //DEBUGpic14_emitcode(";ic","");
7713 //fprintf (stderr, "in ic loop\n");
7714 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
7715 //ic->lineno, printCLine(ic->filename, ic->lineno));
7717 if (!options.noCcodeInAsm && (cln != ic->lineno))
7719 cln = ic->lineno;
7720 //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
7721 cline = printCLine (ic->filename, ic->lineno);
7722 if (!cline || strlen (cline) == 0)
7723 cline = printCLine (ic->filename, ic->lineno);
7724 addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
7725 //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
7728 if (options.iCodeInAsm)
7730 const char *iLine = printILine (ic);
7731 emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
7732 dbuf_free (iLine);
7734 /* if the result is marked as
7735 spilt and rematerializable or code for
7736 this has already been generated then
7737 do nothing */
7738 if (resultRemat (ic) || ic->generated)
7739 continue;
7741 /* depending on the operation */
7742 switch (ic->op)
7744 case '!':
7745 genNot (ic);
7746 break;
7748 case '~':
7749 genCpl (ic);
7750 break;
7752 case UNARYMINUS:
7753 genUminus (ic);
7754 break;
7756 case IPUSH:
7757 genIpush (ic);
7758 break;
7760 case IPOP:
7761 /* IPOP happens only when trying to restore a
7762 spilt live range, if there is an ifx statement
7763 following this pop then the if statement might
7764 be using some of the registers being popped which
7765 would destroy the contents of the register so
7766 we need to check for this condition and handle it */
7767 if (ic->next && ic->next->op == IFX && regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7768 genIfx (ic->next, ic);
7769 else
7770 genIpop (ic);
7771 break;
7773 case CALL:
7774 genCall (ic);
7775 break;
7777 case PCALL:
7778 genPcall (ic);
7779 break;
7781 case FUNCTION:
7782 genFunction (ic);
7783 break;
7785 case ENDFUNCTION:
7786 genEndFunction (ic);
7787 break;
7789 case RETURN:
7790 genRet (ic);
7791 break;
7793 case LABEL:
7794 genLabel (ic);
7795 break;
7797 case GOTO:
7798 genGoto (ic);
7799 break;
7801 case '+':
7802 genPlus (ic);
7803 break;
7805 case '-':
7806 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7807 genMinus (ic);
7808 break;
7810 case '*':
7811 genMult (ic);
7812 break;
7814 case '/':
7815 genDiv (ic);
7816 break;
7818 case '%':
7819 genMod (ic);
7820 break;
7822 case '>':
7823 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7824 break;
7826 case '<':
7827 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7828 break;
7830 case LE_OP:
7831 case GE_OP:
7832 case NE_OP:
7834 /* note these two are xlated by algebraic equivalence
7835 during parsing SDCC.y */
7836 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "got '>=' or '<=' shouldn't have come here");
7837 exit (1);
7838 break;
7840 case EQ_OP:
7841 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7842 break;
7844 case AND_OP:
7845 genAndOp (ic);
7846 break;
7848 case OR_OP:
7849 genOrOp (ic);
7850 break;
7852 case '^':
7853 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7854 break;
7856 case '|':
7857 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7858 break;
7860 case BITWISEAND:
7861 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7862 break;
7864 case INLINEASM:
7865 pic14_genInline (ic);
7866 break;
7868 case GETABIT:
7869 genGetABit (ic);
7870 break;
7872 case ROT:
7873 genRot (ic);
7874 break;
7876 case LEFT_OP:
7877 genLeftShift (ic);
7878 break;
7880 case RIGHT_OP:
7881 genRightShift (ic);
7882 break;
7884 case GET_VALUE_AT_ADDRESS:
7885 genPointerGet (ic);
7886 break;
7888 case '=':
7889 if (POINTER_SET (ic))
7890 genPointerSet (ic);
7891 else
7892 genAssign (ic);
7893 break;
7895 case IFX:
7896 genIfx (ic, NULL);
7897 break;
7899 case ADDRESS_OF:
7900 genAddrOf (ic);
7901 break;
7903 case JUMPTABLE:
7904 genJumpTab (ic);
7905 break;
7907 case CAST:
7908 genCast (ic);
7909 break;
7911 case RECEIVE:
7912 genReceive (ic);
7913 break;
7915 case SEND:
7916 addSet (&_G.sendSet, ic);
7917 break;
7919 case DUMMY_READ_VOLATILE:
7920 genDummyRead (ic);
7921 break;
7923 case CRITICAL:
7924 genCritical (ic);
7925 break;
7927 case ENDCRITICAL:
7928 genEndCritical (ic);
7929 break;
7931 default:
7932 fprintf (stderr, "UNHANDLED iCode: ");
7933 piCode (ic, stderr);
7934 ic = ic;
7935 break;
7940 /* now we are ready to call the
7941 peep hole optimizer */
7942 if (!options.nopeep)
7944 peepHole (&genLine.lineHead);
7946 /* now do the actual printing */
7947 printLine (genLine.lineHead, codeOutBuf);
7949 #ifdef PCODE_DEBUG
7950 DFPRINTF ((stderr, "printing pBlock\n\n"));
7951 printpBlock (stdout, pb);
7952 #endif
7954 /* destroy the line list */
7955 destroy_line_list ();
7958 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
7959 * (meaning: representing its own address) or not (referencing its contents).
7960 * This can only be decided based on the operand's type. */
7961 static int
7962 aop_isLitLike (asmop * aop)
7964 assert (aop);
7965 if (aop->type == AOP_LIT)
7966 return TRUE;
7967 if (aop->type == AOP_IMMD)
7968 return TRUE;
7969 if ((aop->type == AOP_PCODE) &&
7970 ((aop->aopu.pcop->type == PO_LITERAL) ||
7971 (aop->aopu.pcop->type == PO_IMMEDIATE)))
7973 /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
7974 * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
7975 return TRUE;
7977 return FALSE;
7981 op_isLitLike (operand * op)
7983 assert (op);
7984 if (aop_isLitLike (AOP (op)))
7985 return TRUE;
7986 if (IS_SYMOP (op) && IS_FUNC (OP_SYM_TYPE (op)))
7987 return TRUE;
7988 if (IS_SYMOP (op) && IS_PTR (OP_SYM_TYPE (op)) && (AOP_TYPE (op) == AOP_PCODE) && (AOP (op)->aopu.pcop->type == PO_IMMEDIATE))
7990 return TRUE;
7993 return FALSE;