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)
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
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 -------------------------------------------------------------------------*/
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.
41 #include "dbuf_string.h"
46 extern struct dbuf_s
*codeOutBuf
;
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
;
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
108 /*-----------------------------------------------------------------*/
109 /* my_powof2(n) - If `n' is an integer power of 2, then the */
110 /* exponent of 2 is returned, otherwise -1 is */
112 /* note that this is similar to the function `powof2' in SDCCsymt */
116 /*-----------------------------------------------------------------*/
118 my_powof2 (unsigned long num
)
122 if ((num
& (num
- 1)) == 0)
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",
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));
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",
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') : '-'));
170 DEBUGpic14_emitcode (const char *inst
, const char *fmt
, ...)
174 if (!debug_verbose
&& !options
.debug
)
178 va_emitcode (inst
, fmt
, ap
);
181 addpCode2pBlock (pb
, newpCodeCharP (genLine
.lineCurr
->line
));
185 emitpComment (const char *fmt
, ...)
191 dbuf_init (&dbuf
, INITIAL_INLINEASM
);
193 dbuf_append_char (&dbuf
, ';');
195 dbuf_vprintf (&dbuf
, fmt
, ap
);
198 line
= dbuf_detach_c_str (&dbuf
);
202 addpCode2pBlock (pb
, newpCodeCharP (genLine
.lineCurr
->line
));
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... */
215 emitpcode_real (PIC_OPCODE poc
, pCodeOp
* pcop
)
218 addpCode2pBlock (pb
, newpCode (poc
, pcop
));
221 static int has_warned
= FALSE
;
223 DEBUGpic14_emitcode (";", "%s ignoring NULL pcop", __FUNCTION__
);
227 fprintf (stderr
, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n");
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 /*-----------------------------------------------------------------*/
242 pic14_emitcode (const char *inst
, const char *fmt
, ...)
247 va_emitcode (inst
, fmt
, ap
);
251 addpCode2pBlock (pb
, newpCodeCharP (genLine
.lineCurr
->line
));
254 /*-----------------------------------------------------------------*/
255 /* pic14_emitDebuggerSymbol - associate the current code location */
256 /* with a debugger symbol */
257 /*-----------------------------------------------------------------*/
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 /*-----------------------------------------------------------------*/
270 newAsmop (short type
)
274 aop
= Safe_alloc(sizeof(asmop
));
279 /*-----------------------------------------------------------------*/
280 /* resolveIfx - converts an iCode ifx into a form more useful for */
281 /* generating code */
282 /*-----------------------------------------------------------------*/
284 resolveIfx (resolvedIfx
* resIfx
, iCode
* ifx
)
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 */
296 resIfx
->lbl
= NULL
; /* this is wrong: newiTempLabel(NULL); / * oops, there is no ifx. so create a label */
302 resIfx
->lbl
= IC_TRUE (ifx
);
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 /*-----------------------------------------------------------------*/
319 aopForSym (iCode
* ic
, symbol
* sym
, bool result
)
322 memmap
*space
= SPEC_OCLS (sym
->etype
);
324 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
325 /* if already has one */
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
);
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
))
353 DEBUGpic14_emitcode (";", "%d size = %d, name =%s", __LINE__
, aop
->size
, sym
->rname
);
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
))
368 DEBUGpic14_emitcode (";", "%d size = %d, name =%s", __LINE__
, aop
->size
, sym
->rname
);
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
))
393 /*-----------------------------------------------------------------*/
394 /* aopForRemat - rematerialzes an object */
395 /*-----------------------------------------------------------------*/
397 aopForRemat (operand
* op
) // x symbol *sym)
399 symbol
*sym
= OP_SYMBOL (op
);
401 asmop
*aop
= newAsmop (AOP_PCODE
);
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__
);
415 val
+= (int) operandLitValue (IC_RIGHT (ic
));
417 else if (ic
->op
== '-')
419 val
-= (int) operandLitValue (IC_RIGHT (ic
));
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
));
442 aopIdx (asmop
* aop
, int offset
)
447 if (aop
->type
!= AOP_REG
)
450 return aop
->aopu
.aop_reg
[offset
]->rIdx
;
454 /*-----------------------------------------------------------------*/
455 /* regsInCommon - two operands have some registers in common */
456 /*-----------------------------------------------------------------*/
458 regsInCommon (operand
* op1
, operand
* op2
)
463 /* if they have registers in common */
464 if (!IS_SYMOP (op1
) || !IS_SYMOP (op2
))
467 sym1
= OP_SYMBOL (op1
);
468 sym2
= OP_SYMBOL (op2
);
470 if (sym1
->nRegs
== 0 || sym2
->nRegs
== 0)
473 for (i
= 0; i
< sym1
->nRegs
; i
++)
479 for (j
= 0; j
< sym2
->nRegs
; j
++)
484 if (sym2
->regs
[j
] == sym1
->regs
[i
])
492 /*-----------------------------------------------------------------*/
493 /* operandsEqu - equivalent */
494 /*-----------------------------------------------------------------*/
496 operandsEqu (operand
* op1
, operand
* op2
)
500 /* if they not symbols */
501 if (!IS_SYMOP (op1
) || !IS_SYMOP (op2
))
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
)
512 /* if they are the same */
516 if (sym1
->rname
[0] && sym2
->rname
[0] && strcmp (sym1
->rname
, sym2
->rname
) == 0)
520 /* if left is a tmp & right is not */
521 if (IS_ITEMP (op1
) && !IS_ITEMP (op2
) && sym1
->isspilt
&& (sym1
->usl
.spillLoc
== sym2
))
524 if (IS_ITEMP (op2
) && !IS_ITEMP (op1
) && sym2
->isspilt
&& sym1
->level
> 0 && (sym2
->usl
.spillLoc
== sym1
))
530 /*-----------------------------------------------------------------*/
531 /* pic14_sameRegs - two asmops have the same registers */
532 /*-----------------------------------------------------------------*/
534 pic14_sameRegs (asmop
* aop1
, asmop
* aop2
)
541 if (aop1
->type
!= AOP_REG
|| aop2
->type
!= AOP_REG
)
544 if (aop1
->size
!= aop2
->size
)
547 for (i
= 0; i
< aop1
->size
; i
++)
548 if (aop1
->aopu
.aop_reg
[i
] != aop2
->aopu
.aop_reg
[i
])
554 /*-----------------------------------------------------------------*/
555 /* aopOp - allocates an asmop for an operand : */
556 /*-----------------------------------------------------------------*/
558 aopOp (operand
* op
, iCode
* ic
, bool result
)
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
));
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 */
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
;
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
);
602 /* this is a temporary : this has
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
);
621 /* if it is spilt then two situations
623 b) has a spill location */
624 if (sym
->isspilt
|| sym
->nRegs
== 0)
627 DEBUGpic14_emitcode (";", "%d", __LINE__
);
628 /* rematerialize it NOW */
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);
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__
);
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__
);
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
);
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 /*----------------------------------------------------------------*/
719 freeAsmop (operand
* op
, asmop
* aaop
, iCode
* ic
, bool pop
)
733 /* all other cases just dealloc */
739 OP_SYMBOL (op
)->aop
= NULL
;
740 /* if the symbol has a spill */
742 SPIL_LOC (op
)->aop
= NULL
;
747 /*-----------------------------------------------------------------*/
748 /* pic14aopLiteral - string from a literal value */
749 /*-----------------------------------------------------------------*/
751 pic14aopLiteral (value
* val
, int offset
)
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
];
777 /*-----------------------------------------------------------------*/
778 /* aopGet - for fetching value of the aop */
779 /*-----------------------------------------------------------------*/
781 aopGet (asmop
* aop
, int offset
, bool bit16
, bool dname
)
783 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
784 /* offset is greater than
787 if (offset
> (aop
->size
- 1) && aop
->type
!= AOP_LIT
)
790 /* depending on type */
795 SNPRINTF(buffer
, sizeof(buffer
), "%s", aop
->aopu
.aop_immd
);
797 SNPRINTF(buffer
, sizeof(buffer
), "(%s >> %d)", aop
->aopu
.aop_immd
, offset
* 8);
799 SNPRINTF(buffer
, sizeof(buffer
), "%s", aop
->aopu
.aop_immd
);
800 DEBUGpic14_emitcode (";", "%d immd %s", __LINE__
, buffer
);
801 return Safe_strdup(buffer
);
806 SNPRINTF(buffer
, sizeof(buffer
), "(%s + %d)", aop
->aopu
.aop_dir
, offset
);
807 DEBUGpic14_emitcode (";", "oops AOP_DIR did this %s\n", buffer
);
810 SNPRINTF(buffer
, sizeof(buffer
), "%s", aop
->aopu
.aop_dir
);
811 return Safe_strdup(buffer
);
815 // return aop->aopu.aop_reg[offset]->dname;
817 return aop
->aopu
.aop_reg
[offset
]->name
;
820 //pic14_emitcode(";","%d",__LINE__);
821 return aop
->aopu
.aop_dir
;
824 SNPRINTF(buffer
, sizeof(buffer
), "0x%02x", pic14aopLiteral (aop
->aopu
.aop_lit
, offset
));
825 return Safe_strdup(buffer
);
829 if (strcmp (aop
->aopu
.aop_str
[offset
], "a") == 0 && dname
)
831 DEBUGpic14_emitcode (";", "%d - %s", __LINE__
, aop
->aopu
.aop_str
[offset
]);
832 return aop
->aopu
.aop_str
[offset
];
836 pCodeOp
*pcop
= aop
->aopu
.pcop
;
837 DEBUGpic14_emitcode (";", "%d: aopGet AOP_PCODE type %s", __LINE__
, pCodeOpType (pcop
));
840 if (pcop
->type
== PO_IMMEDIATE
)
842 offset
+= PCOI (pcop
)->index
;
847 DEBUGpic14_emitcode (";", "%s offset %d", pcop
->name
, offset
);
848 SNPRINTF(buffer
, sizeof(buffer
), "(%s+%d)", pcop
->name
, offset
);
852 DEBUGpic14_emitcode (";", "%s", pcop
->name
);
853 SNPRINTF(buffer
, sizeof(buffer
), "%s", pcop
->name
);
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");
867 /*-----------------------------------------------------------------*/
868 /* popGetTempReg - create a new temporary pCodeOp */
869 /*-----------------------------------------------------------------*/
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
;
886 /*-----------------------------------------------------------------*/
887 /* popReleaseTempReg - create a new temporary pCodeOp */
888 /*-----------------------------------------------------------------*/
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 /*-----------------------------------------------------------------*/
902 popGetLabel (unsigned int key
)
905 DEBUGpic14_emitcode ("; ***", "%s key=%d, label offset %d", __FUNCTION__
, key
, labelOffset
);
907 if (key
> (unsigned int) max_key
)
910 return newpCodeOpLabel (NULL
, labelKey2num (key
+ labelOffset
));
913 /*-------------------------------------------------------------------*/
914 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
915 /*-------------------------------------------------------------------*/
917 popGetHighLabel (unsigned int key
)
920 pcop
= popGetLabel (key
);
921 PCOLAB (pcop
)->offset
= 1;
925 /*-----------------------------------------------------------------*/
926 /* popGetLit - asm operator to pcode operator conversion */
927 /*-----------------------------------------------------------------*/
929 popGetLit (unsigned int lit
)
932 return newpCodeOpLit ((unsigned char) lit
);
935 /*-----------------------------------------------------------------*/
936 /* popGetImmd - asm operator to pcode immediate conversion */
937 /*-----------------------------------------------------------------*/
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 /*-----------------------------------------------------------------*/
949 popGetWithString (const char *str
, int isExtern
)
955 werror (E_INTERNAL_ERROR
, __FILE__
, __LINE__
, "NULL string");
959 pcop
= newpCodeOp (str
, PO_STR
);
960 PCOS (pcop
)->isPublic
= isExtern
? 1 : 0;
966 popGetExternal (const char *str
, int isReg
)
973 werror (E_INTERNAL_ERROR
, __FILE__
, __LINE__
, "NULL string");
979 pcop
= newpCodeOpRegFromStr (str
);
983 pcop
= popGetWithString (str
, 1);
986 /* create symbol, mark it as `extern' */
987 sym
= findSym (SymbolTab
, NULL
, str
+1);
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 */
1000 for (esym
= setFirstItem (externs
); esym
; esym
= setNextItem (externs
))
1002 if (!strcmp (str
, esym
->rname
))
1008 DEBUGpic14_emitcode (";", "%s %d added extern %s", __FUNCTION__
, __LINE__
, str
);
1009 addSet (&externs
, sym
);
1017 /*-----------------------------------------------------------------*/
1018 /* popRegFromString - */
1019 /*-----------------------------------------------------------------*/
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__
);
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
);
1045 DEBUGpic14_emitcode (";", "%d %s offset=%d", __LINE__
, pcop
->name
, offset
);
1047 PCOR (pcop
)->instance
= offset
;
1052 /*-----------------------------------------------------------------*/
1053 /*-----------------------------------------------------------------*/
1055 popRegFromIdx (int rIdx
)
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
;
1074 /*-----------------------------------------------------------------*/
1075 /* popGet - asm operator to pcode operator conversion */
1076 /*-----------------------------------------------------------------*/
1078 popGet (asmop
* aop
, int offset
) //, bool bit16, bool dname)
1080 //char *s = buffer ;
1085 //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1086 /* offset is greater than
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 */
1105 DEBUGpic14_emitcode (";", "%d", __LINE__
);
1106 return popGetImmd (aop
->aopu
.aop_immd
, offset
, 0, 0);
1109 return popRegFromString (aop
->aopu
.aop_dir
, aop
->size
, offset
);
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
);
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);
1138 return newpCodeOpLit (pic14aopLiteral (aop
->aopu
.aop_lit
, offset
));
1141 DEBUGpic14_emitcode (";", "%d %s", __LINE__
, aop
->aopu
.aop_str
[offset
]);
1142 return newpCodeOpRegFromStr (aop
->aopu
.aop_str
[offset
]);
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
)
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;
1159 pcop
= pCodeOpCopy (aop
->aopu
.pcop
);
1160 PCOR (pcop
)->instance
= offset
;
1163 assert (!"unhandled pCode type");
1169 werror (E_INTERNAL_ERROR
, __FILE__
, __LINE__
, "popGet got unsupported aop->type");
1173 /*-----------------------------------------------------------------*/
1174 /* popGetAddr - access the low/high word of a symbol (immediate) */
1175 /* (for non-PO_IMMEDIATEs this is the same as popGet) */
1176 /*-----------------------------------------------------------------*/
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 */
1188 pcop
= popGetLit (aop
->code
? GPTRTAG_CODE
: GPTRTAG_DATA
);
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);
1202 return popGet (aop
, offset
+ index
);
1206 /*-----------------------------------------------------------------*/
1207 /* aopPut - puts a string for a aop */
1208 /*-----------------------------------------------------------------*/
1210 aopPut (asmop
* aop
, const char *s
, int offset
)
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");
1222 /* will assign value to value */
1223 /* depending on where it is ofcourse */
1229 SNPRINTF(buffer
, sizeof(buffer
), "(%s + %d)", aop
->aopu
.aop_dir
, offset
);
1230 fprintf (stderr
, "oops aopPut:AOP_DIR did this %s\n", s
);
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
));
1253 emitpcode (POC_MOVFW
, popGetImmd (s
, 0, offset
, 0));
1256 emitpcode (POC_MOVWF
, popGet (aop
, offset
));
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
));
1293 emitpcode (POC_MOVWF
, popGet (aop
, offset
));
1299 if (strcmp (s
, "a") == 0)
1300 pic14_emitcode ("push", "acc");
1302 pic14_emitcode ("push", "%s", s
);
1306 /* if bit variable */
1307 if (!aop
->aopu
.aop_dir
)
1309 pic14_emitcode ("clr", "a");
1310 pic14_emitcode ("rlc", "a");
1315 pic14_emitcode ("clr", "%s", aop
->aopu
.aop_dir
);
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
);
1322 lbl
= newiTempLabel (NULL
);
1324 if (strcmp (s
, "a"))
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
);
1340 if (strcmp (aop
->aopu
.aop_str
[offset
], s
))
1341 pic14_emitcode ("mov", "%s,%s ; %d", aop
->aopu
.aop_str
[offset
], s
, __LINE__
);
1345 werror (E_INTERNAL_ERROR
, __FILE__
, __LINE__
, "aopPut got unsupported aop->type");
1350 /*-----------------------------------------------------------------*/
1351 /* mov2w_op - generate either a MOVLW or MOVFW based operand type */
1352 /*-----------------------------------------------------------------*/
1354 mov2w_op (operand
* op
, int offset
)
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
));
1372 emitpcode (POC_MOVLW
, popGetLit (0));
1375 emitpcode (POC_MOVLW
, popGetAddr (AOP (op
), offset
, 0));
1379 /* access value stored in op */
1380 mov2w (AOP (op
), offset
);
1385 /*-----------------------------------------------------------------*/
1386 /* mov2w - generate either a MOVLW or MOVFW based operand type */
1387 /*-----------------------------------------------------------------*/
1389 mov2w (asmop
* aop
, int offset
)
1395 DEBUGpic14_emitcode ("; ***", "%s %d offset=%d", __FUNCTION__
, __LINE__
, offset
);
1397 if (aop_isLitLike (aop
))
1398 emitpcode (POC_MOVLW
, popGetAddr (aop
, offset
, 0));
1400 emitpcode (POC_MOVFW
, popGet (aop
, offset
));
1405 movwf (asmop
* op
, int offset
)
1407 emitpcode (POC_MOVWF
, popGet (op
, offset
));
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));
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));
1425 pass_argument (operand
* op
, int offset
, int idx
)
1428 mov2w_op (op
, offset
);
1430 emitpcode (POC_MOVWF
, get_argument_pcop (idx
));
1434 get_returnvalue (operand
* op
, int offset
, int idx
)
1437 emitpcode (POC_MOVFW
, get_return_val_pcop (idx
));
1438 movwf (AOP (op
), offset
);
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
)
1460 size
= AOP_SIZE (op
);
1464 /*-----------------------------------------------------------------*/
1465 /* pic14_outAcc - output Acc */
1466 /*-----------------------------------------------------------------*/
1468 pic14_outAcc (operand
* result
)
1471 DEBUGpic14_emitcode ("; ***", "%s %d - ", __FUNCTION__
, __LINE__
);
1472 DEBUGpic14_AopType (__LINE__
, NULL
, NULL
, result
);
1475 size
= pic14_getDataSize (result
);
1478 emitpcode (POC_MOVWF
, popGet (AOP (result
), 0));
1481 /* unsigned or positive */
1483 emitpcode (POC_CLRF
, popGet (AOP (result
), offset
++));
1488 /*-----------------------------------------------------------------*/
1489 /* pic14_outBitC - output a bit C */
1490 /*-----------------------------------------------------------------*/
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);
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 /*-----------------------------------------------------------------*/
1511 pic14_toBoolean (operand
* oper
)
1513 int size
= AOP_SIZE (oper
);
1515 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
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));
1530 if (op_isLitLike (oper
))
1531 emitpcode (POC_IORLW
, popGetAddr (AOP (oper
), size
, 0));
1533 emitpcode (POC_IORFW
, popGet (AOP (oper
), size
));
1535 /* Z is set iff (oper == 0) */
1539 /*-----------------------------------------------------------------*/
1540 /* genNot - generate code for ! operation */
1541 /*-----------------------------------------------------------------*/
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));
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));
1573 size
= AOP_SIZE (IC_LEFT (ic
));
1574 mov2w (AOP (IC_LEFT (ic
)), 0);
1577 if (op_isLitLike (IC_LEFT (ic
)))
1578 emitpcode (POC_IORLW
, popGetAddr (AOP (IC_LEFT (ic
)), size
, 0));
1580 emitpcode (POC_IORFW
, popGet (AOP (IC_LEFT (ic
)), size
));
1582 emitpcode (POC_MOVLW
, popGetLit (0));
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
));
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 /*-----------------------------------------------------------------*/
1606 operand
*left
, *result
;
1607 int size
, offset
= 0;
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
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
);
1626 size
= AOP_SIZE (result
);
1627 if (AOP_SIZE (left
) < size
)
1628 size
= AOP_SIZE (left
);
1631 emitpcode (POC_COMFW
, popGet (AOP (left
), offset
));
1632 emitpcode (POC_MOVWF
, popGet (AOP (result
), offset
));
1635 addSign (result
, AOP_SIZE (left
), !SPEC_USIGN (operandType (result
)));
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 /*-----------------------------------------------------------------*/
1648 genUminusFloat (operand
* op
, operand
* result
)
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
);
1665 mov2w_op (op
, size
);
1666 movwf (AOP (result
), size
);
1670 /*-----------------------------------------------------------------*/
1671 /* genUminus - unary minus code generation */
1672 /*-----------------------------------------------------------------*/
1674 genUminus (iCode
* ic
)
1681 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
1683 aopOp (IC_LEFT (ic
), ic
, FALSE
);
1684 aopOp (IC_RESULT (ic
), ic
, TRUE
);
1686 /* if both in bit space then special
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));
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
));
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
));
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
++)
1725 emitpcode (POC_INCF
, popGet (AOP (IC_RESULT (ic
)), i
));
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 /*-----------------------------------------------------------------*/
1738 saverbank (int bank
, iCode
* ic
, bool pushPsw
)
1742 DEBUGpic14_emitcode ("; ***", "%s %d - WARNING no code generated", __FUNCTION__
, __LINE__
);
1748 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
1749 if (options
.useXstack
)
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
);
1768 pic14_emitcode ("push", ""); // "(%s+%d)",
1769 //regspic14[i].base,8*bank+regspic14[i].offset);
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
);
1784 pic14_emitcode ("push", "psw");
1786 pic14_emitcode ("mov", "psw,#0x%02x", (bank
<< 3) & 0x00ff);
1792 /*-----------------------------------------------------------------*/
1793 /* saveRegisters - will look for a call and save the registers */
1794 /*-----------------------------------------------------------------*/
1796 saveRegisters (iCode
* lic
)
1804 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
1807 for (ic
= lic
; ic
; ic
= ic
->next
)
1808 if (ic
->op
== CALL
|| ic
->op
== PCALL
)
1813 fprintf (stderr
, "found parameter push with no function call\n");
1817 /* if the registers have been saved already then do nothing */
1818 if (ic
->regsSaved
|| IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic
))->type
))
1821 /* find the registers in use at this time
1822 and push them away to safety */
1823 bitVectCplAnd (bitVectCopy (ic
->rMask
), ic
->rUsed
);
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
);
1838 /*-----------------------------------------------------------------*/
1839 /* unsaveRegisters - pop the pushed registers */
1840 /*-----------------------------------------------------------------*/
1842 unsaveRegisters (iCode
* ic
)
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
);
1870 //for (i = pic14_nRegs ; i >= 0 ; i--) {
1871 // if (bitVectBitValue(rsave,i))
1872 // pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1879 /*-----------------------------------------------------------------*/
1881 /*-----------------------------------------------------------------*/
1883 pushSide (operand
* oper
, int size
)
1887 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
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");
1897 pic14_emitcode ("push", "%s", l
);
1902 /*-----------------------------------------------------------------*/
1903 /* assignResultValue - */
1904 /*-----------------------------------------------------------------*/
1906 assignResultValue (iCode
*ic
)
1908 operand
* oper
= IC_RESULT(ic
);
1909 int size
= AOP_SIZE (oper
);
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
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);
1924 offset
+= rsize
- size
;
1925 DEBUGpic14_emitcode ("; ***", "%s %d ret-size=%d op-size=%d offset=%d", __FUNCTION__
, __LINE__
, rsize
,size
,offset
);
1931 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
1933 DEBUGpic14_AopType (__LINE__
, oper
, NULL
, NULL
);
1935 /* assign MSB first (passed via WREG) */
1938 get_returnvalue (oper
, size
, offset
+ GpseudoStkPtr
);
1944 /*-----------------------------------------------------------------*/
1945 /* genIpush - genrate code for pushing this gets a little complex */
1946 /*-----------------------------------------------------------------*/
1948 genIpush (iCode
* ic
)
1952 DEBUGpic14_emitcode ("; ***", "%s %d - WARNING no code generated", __FUNCTION__
, __LINE__
);
1954 int size
, offset
= 0;
1958 /* if this is not a parm push : ie. it is spill push
1959 and spill push is always done on the local stack */
1963 /* and the item is spilt then do nothing */
1964 if (OP_SYMBOL (IC_LEFT (ic
))->isspilt
)
1967 aopOp (IC_LEFT (ic
), ic
, FALSE
);
1968 size
= AOP_SIZE (IC_LEFT (ic
));
1969 /* push it on the stack */
1972 l
= aopGet (AOP (IC_LEFT (ic
)), offset
++, FALSE
, TRUE
);
1978 pic14_emitcode ("push", "%s", l
);
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 */
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
));
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");
2004 pic14_emitcode ("push", "%s", l
);
2007 freeAsmop (IC_LEFT (ic
), NULL
, ic
, TRUE
);
2011 /*-----------------------------------------------------------------*/
2012 /* genIpop - recover the registers: can happen only for spilling */
2013 /*-----------------------------------------------------------------*/
2015 genIpop (iCode
* ic
)
2019 DEBUGpic14_emitcode ("; ***", "%s %d - WARNING no code generated", __FUNCTION__
, __LINE__
);
2020 assert (!"genIpop -- unimplemented");
2025 /* if the temp was not pushed then */
2026 if (OP_SYMBOL (IC_LEFT (ic
))->isspilt
)
2029 aopOp (IC_LEFT (ic
), ic
, FALSE
);
2030 size
= AOP_SIZE (IC_LEFT (ic
));
2031 offset
= (size
- 1);
2033 pic14_emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic
)), offset
--, FALSE
, TRUE
));
2035 freeAsmop (IC_LEFT (ic
), NULL
, ic
, TRUE
);
2039 /*-----------------------------------------------------------------*/
2040 /* unsaverbank - restores the resgister bank from stack */
2041 /*-----------------------------------------------------------------*/
2043 unsaverbank (int bank
, iCode
* ic
, bool popPsw
)
2047 DEBUGpic14_emitcode ("; ***", "%s %d - WARNING no code generated", __FUNCTION__
, __LINE__
);
2053 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
2056 if (options
.useXstack
)
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
);
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
);
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
);
2097 /*-----------------------------------------------------------------*/
2098 /* genCall - generates a call statement */
2099 /*-----------------------------------------------------------------*/
2101 genCall (iCode
* ic
)
2103 sym_link
*dtype
, *etype
;
2105 char *name
, buf
[20];
2110 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
2112 /* if caller saves & we have not saved then */
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 */
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
));
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
2166 emitpcode (POC_MOVWF
, popRegFromIdx (Gstack_base_addr
- --pseudoStkPtr
));
2169 firstTimeThruLoop
= 0;
2171 mov2w_op (IC_LEFT (sic
), offset
);
2174 freeAsmop (IC_LEFT (sic
), NULL
, sic
, TRUE
);
2179 if (IS_LITERAL(etype
))
2181 SNPRINTF(buf
,sizeof(buf
),"0x%04X", (unsigned)ulFromVal(OP_VALUE(IC_LEFT(ic
))));
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
;
2204 /* Extern functions and ISRs maybe on a different page;
2205 * must call pagesel */
2207 emitpcode (POC_PAGESEL
, popGetWithString (name
, 1));
2212 if (!strcmp(name
, "___memcpy"))
2213 emitpcode (POC_CALL
, popGetExternal (name
, 0));
2215 emitpcode (POC_CALL
, popGetWithString (name
, isExtern
));
2219 /* May have returned from a different page;
2220 * must use pagesel to restore PCLATH before next
2221 * goto or call instruction */
2223 emitpcode (POC_PAGESEL
, popGetWithString ("$", 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
)))
2233 aopOp (IC_RESULT (ic
), ic
, FALSE
);
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 */
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 /*-----------------------------------------------------------------*/
2256 genPcall (iCode
* ic
)
2259 symbol
*albl
= newiTempLabel (NULL
);
2260 symbol
*blbl
= newiTempLabel (NULL
);
2267 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
2268 /* if caller saves & we have not saved then */
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 */
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) {
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)));
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
)))
2331 aopOp (IC_RESULT (ic
), ic
, FALSE
);
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
2348 unsaveRegisters (ic
);
2351 /*-----------------------------------------------------------------*/
2352 /* resultRemat - result is rematerializable */
2353 /*-----------------------------------------------------------------*/
2355 resultRemat (iCode
* ic
)
2357 // DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2360 if (SKIP_IC (ic
) || ic
->op
== IFX
)
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
))
2373 /*-----------------------------------------------------------------*/
2374 /* genFunction - generated code for function entry */
2375 /*-----------------------------------------------------------------*/
2377 genFunction (iCode
* ic
)
2384 DEBUGpic14_emitcode ("; ***", "%s %d curr label offset=%dprevious max_key=%d ", __FUNCTION__
, __LINE__
, labelOffset
,
2387 labelOffset
+= (max_key
+ 4);
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;
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 */
2415 if (FUNC_REGBANK (ftype
) != rbank
)
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
);
2425 pic14_emitcode ("", "%s = %s + 0x%02x", regspic14
[i
].dname
, regspic14
[i
].base
, 8 * rbank
+ regspic14
[i
].offset
);
2430 /* if this is an interrupt service routine */
2432 if (IFFUNC_ISISR (sym
->type
))
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
));
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
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;
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
))
2479 /* if any registers used */
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);
2495 /* if critical function then turn interrupts off */
2496 if (IFFUNC_ISCRITICAL (ftype
))
2499 if (IFFUNC_ARGS (sym
->type
))
2501 fprintf (stderr
, "PIC14: Functions with __critical (%s) must not have arguments for now.\n", sym
->name
);
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
);
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 */
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");
2549 pic14_emitcode ("inc", "sp");
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 /*-----------------------------------------------------------------*/
2566 genEndFunction (iCode
* ic
)
2568 symbol
*sym
= OP_SYMBOL (IC_LEFT (ic
));
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
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
);
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
);
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
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
))
2632 /* if any registers used */
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);
2648 /* this function has a function call; cannot
2649 determines register usage so we will have the
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
);
2681 if (IFFUNC_ISCRITICAL (sym
->type
))
2682 pic14_emitcode ("setb", "ea");
2684 if (IFFUNC_CALLEESAVES (sym
->type
))
2688 /* if any registers used */
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 /*-----------------------------------------------------------------*/
2723 int size
, offset
= 0;
2727 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
2728 /* if we have no return value then
2729 just generate the "ret" */
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
);
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
;
2759 genCritical (iCode
* ic
)
2761 pCodeOp
*saved_intcon
;
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
));
2778 genEndCritical (iCode
* ic
)
2780 pCodeOp
*saved_intcon
= NULL
;
2784 saved_intcon
= getSet (&critical_temps
);
2787 fprintf (stderr
, "Critical section left, but none entered -- ignoring for now.\n");
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 /*-----------------------------------------------------------------*/
2800 genLabel (iCode
* ic
)
2804 /* special case never generate */
2805 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
2806 if (IC_LABEL (ic
) == entryLabel
)
2809 emitpLabel (IC_LABEL (ic
)->key
);
2810 pic14_emitcode ("", "_%05d_DS_:", labelKey2num (IC_LABEL (ic
)->key
+ labelOffset
));
2813 /*-----------------------------------------------------------------*/
2814 /* genGoto - generates a goto */
2815 /*-----------------------------------------------------------------*/
2818 genGoto (iCode
* ic
)
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 /*-----------------------------------------------------------------*/
2831 genMultbits (operand
* left
, operand
* right
, operand
* result
)
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 /*-----------------------------------------------------------------*/
2850 genMultOneByte (operand
* left
, operand
* right
, operand
* result
)
2852 char *func
[] = { NULL
, "__mulchar", "__mulint", NULL
, "__mullong" };
2855 int size
, offset
, i
;
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
)
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
));
2885 /* pass left operand as argument */
2886 for (i
= 0; i
< size
; i
++)
2888 mov2w (AOP (left
), i
);
2890 emitpcode (POC_MOVWF
, popRegFromIdx (++offset
));
2892 assert (offset
== Gstack_base_addr
);
2894 /* call library routine */
2895 assert (size
> 0 && size
<= 4);
2896 call_libraryfunc (func
[size
]);
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
);
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 /*-----------------------------------------------------------------*/
2914 genMult (iCode
* ic
)
2916 operand
*left
= IC_LEFT (ic
);
2917 operand
*right
= IC_RIGHT (ic
);
2918 operand
*result
= IC_RESULT (ic
);
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 */
2932 if (AOP_TYPE (left
) == AOP_CRY
&& AOP_TYPE (right
) == AOP_CRY
)
2934 genMultbits (left
, right
, result
);
2938 /* if both are of size == 1 */
2939 if (AOP_SIZE (left
) == 1 && AOP_SIZE (right
) == 1)
2941 genMultOneByte (left
, right
, result
);
2945 /* should have been converted to function call */
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 /*-----------------------------------------------------------------*/
2958 genDivbits (operand
* left
, operand
* right
, operand
* result
)
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
);
2972 pic14_emitcode ("div", "ab");
2973 pic14_emitcode ("rrc", "a");
2974 aopPut (AOP (result
), "c", 0);
2977 /*-----------------------------------------------------------------*/
2978 /* genDivOneByte : 8 bit division */
2979 /*-----------------------------------------------------------------*/
2981 genDivOneByte (operand
* left
, operand
* right
, operand
* result
)
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 */
3000 /* unsigned division */
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);
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
3020 movwf temp // temp <-- left
3021 movf right,W // W <-- right
3025 subwf temp,F // temp <-- temp - W
3026 skipNC // subwf clears CARRY (i.e. sets BORROW) if temp < W
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
);
3044 if (pic
->isEnhancedCore
)
3046 emitpcode (POC_BRA
, popGetLabel (lbl
->key
));
3050 emitpcode (POC_GOTO
, popGetLabel (lbl
->key
));
3053 emitpcode (POC_DECF
, popGet (AOP (result
), 0));
3054 popReleaseTempReg (temp
);
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 /*-----------------------------------------------------------------*/
3077 operand
*left
= IC_LEFT (ic
);
3078 operand
*right
= IC_RIGHT (ic
);
3079 operand
*result
= IC_RESULT (ic
);
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 */
3090 if (AOP_TYPE (left
) == AOP_CRY
&& AOP_TYPE (right
) == AOP_CRY
)
3092 genDivbits (left
, right
, result
);
3096 /* if both are of size == 1 */
3097 if (AOP_SIZE (left
) == 1 && AOP_SIZE (right
) == 1)
3099 genDivOneByte (left
, right
, result
);
3103 /* should have been converted to function call */
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 /*-----------------------------------------------------------------*/
3115 genModOneByte (operand
* left
, operand
* right
, operand
* result
)
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 */
3134 /* unsigned division */
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);
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
3155 movwf result // result <-- left
3156 movf right,W // W <-- right
3158 subwf result,F // result <-- result - W
3159 skipNC // subwf clears CARRY (i.e. sets BORROW) if result < W
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));
3178 if (pic
->isEnhancedCore
)
3180 emitpcode (POC_BRA
, popGetLabel (lbl
->key
));
3184 emitpcode (POC_GOTO
, popGetLabel (lbl
->key
));
3187 emitpcode (POC_ADDWF
, popGet (AOP (result
), 0));
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 /*-----------------------------------------------------------------*/
3210 operand
*left
= IC_LEFT (ic
);
3211 operand
*right
= IC_RIGHT (ic
);
3212 operand
*result
= IC_RESULT (ic
);
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
);
3228 /* should have been converted to function call */
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.
3244 genIfxJump (iCode
* ic
, char *jval
)
3248 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
3249 /* if true label then we jump if condition
3254 if (strcmp (jval
, "a") == 0)
3256 else if (strcmp (jval
, "c") == 0)
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
));
3270 /* false label is present */
3271 if (strcmp (jval
, "a") == 0)
3273 else if (strcmp (jval
, "c") == 0)
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 /*-----------------------------------------------------------------*/
3293 /*-----------------------------------------------------------------*/
3295 genSkipc (resolvedIfx
* rifx
)
3301 if (rifx
->condition
)
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 /*-----------------------------------------------------------------*/
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));
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 */
3342 genCmp (operand
* left
, operand
* right
, operand
* result
, iCode
* ifx
, int sign
)
3352 int invert_result
= 0;
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)
3366 resolveIfx (&rIfx
, ifx
);
3368 /**********************************************************************
3369 * handle bits - bit compares are promoted to int compares seemingly! *
3370 **********************************************************************/
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
);
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
;
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
3410 goto correct_result_in_carry
;
3413 // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3414 // that's why we handled it above.
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
);
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
))
3439 // unsigned comparison to a literal
3440 DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt
? "<" : ">=", lit
, lit
, size
+ 1);
3443 // unsigned left < 0? always false
3448 goto correct_result_in_carry
;
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,
3456 if ((lit
& mask
) == ((0x80 << (size
* 8)) & mask
))
3458 // signed left < 0x80000000? always false
3463 goto correct_result_in_carry
;
3467 // compare left < 0; set CARRY if SIGNBIT(left) is set
3472 emitpcode (POC_BTFSS
, newpCodeOpBit (aopGet (AOP (left
), size
, FALSE
, FALSE
), 7, 0));
3477 goto correct_result_in_carry
;
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);
3490 // unsigned comparison
3491 pic14_mov2w_regOrLit (AOP (right
), lit
, size
);
3492 emitpcode (POC_SUBFW
, popGet (AOP (left
), size
));
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
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));
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
);
3531 // compare remaining bytes (treat as unsigned case from above)
3532 templbl
= newiTempLabel (NULL
);
3536 //DEBUGpc ("comparing bytes at offset %d", offs);
3539 if (pic
->isEnhancedCore
)
3541 emitpcode (POC_BRA
, popGetLabel (templbl
->key
));
3545 emitpcode (POC_GOTO
, popGetLabel (templbl
->key
));
3548 pic14_mov2w_regOrLit (AOP (right
), lit
, offs
);
3549 emitpcode (POC_SUBFW
, popGet (AOP (left
), offs
));
3551 emitpLabel (templbl
->key
);
3552 goto 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 ****************************************************/
3566 // value will be used in the following genSkipc ()
3567 rIfx
.condition
^= TRUE
;
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
);
3579 emitpcode (POC_CLRF
, popGet (AOP (result
), size
));
3584 emitpcode (POC_BSF
, newpCodeOpBit (aopGet (AOP (result
), 0, FALSE
, FALSE
), 0, 0));
3588 emitpcode (POC_RLF
, popGet (AOP (result
), 0));
3591 /* Result is expected to be in CARRY by genSkipc () below. */
3592 emitpcode (POC_RRFW
, popGet (AOP (result
), 0));
3597 // perform conditional jump
3600 //DEBUGpc ("generate control flow");
3602 ifx
->generated
= TRUE
;
3606 /*-----------------------------------------------------------------*/
3607 /* genCmpGt :- greater than comparison */
3608 /*-----------------------------------------------------------------*/
3610 genCmpGt (iCode
* ic
, iCode
* ifx
)
3612 operand
*left
, *right
, *result
;
3613 sym_link
*letype
, *retype
;
3617 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
3618 left
= IC_LEFT (ic
);
3619 right
= IC_RIGHT (ic
);
3620 result
= IC_RESULT (ic
);
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 /*-----------------------------------------------------------------*/
3646 genCmpLt (iCode
* ic
, iCode
* ifx
)
3648 operand
*left
, *right
, *result
;
3649 sym_link
*letype
, *retype
;
3653 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
3654 left
= IC_LEFT (ic
);
3655 right
= IC_RIGHT (ic
);
3656 result
= IC_RESULT (ic
);
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 /*-----------------------------------------------------------------*/
3682 genCmpEq (iCode
* ic
, iCode
* ifx
)
3684 operand
*left
, *right
, *result
;
3686 symbol
*false_label
= NULL
;
3687 symbol
*true_label
= NULL
;
3690 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
3693 DEBUGpic14_emitcode ("; ifx is non-null", "");
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
;
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 */
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
);
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' */
3747 true_label
= newiTempLabel (NULL
);
3748 emitpcode (POC_GOTO
, popGetLabel (true_label
->key
));
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' */
3761 false_label
= newiTempLabel (NULL
);
3762 emitpcode (POC_GOTO
, popGetLabel (false_label
->key
));
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' */
3773 false_label
= newiTempLabel (NULL
);
3774 emitpcode (POC_GOTO
, popGetLabel (false_label
->key
));
3781 /* right is no literal */
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' */
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' */
3805 false_label
= newiTempLabel (NULL
);
3806 emitpcode (POC_GOTO
, popGetLabel (false_label
->key
));
3810 /* if we reach here, left == right */
3814 emitpLabel (true_label
->key
);
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
);
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 /*-----------------------------------------------------------------*/
3843 genAndOp (iCode
* ic
)
3845 operand
*left
, *right
, *result
;
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); */
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); */
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 /*-----------------------------------------------------------------*/
3889 modified this code, but it doesn't appear to ever get called
3893 genOrOp (iCode
* ic
)
3895 operand
*left
, *right
, *result
;
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 */
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
));
3915 tlbl
= newiTempLabel (NULL
);
3916 pic14_toBoolean (left
);
3918 emitpcode (POC_GOTO
, popGetLabel (tlbl
->key
));
3919 pic14_toBoolean (right
);
3920 emitpLabel (tlbl
->key
);
3921 /* here Z is clear IFF `left || right' */
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 /*-----------------------------------------------------------------*/
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
3947 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
3948 for (idx
= 0; idx
< 32; idx
++)
3954 /*-----------------------------------------------------------------*/
3955 /* continueIfTrue - */
3956 /*-----------------------------------------------------------------*/
3958 continueIfTrue (iCode
* ic
)
3961 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
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 /*-----------------------------------------------------------------*/
3972 /*-----------------------------------------------------------------*/
3974 jumpIfTrue (iCode
* ic
)
3977 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
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 /*-----------------------------------------------------------------*/
3990 jmpTrueOrFalse (iCode
* ic
, symbol
* tlbl
)
3993 // ugly but optimized by peephole
3994 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
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
));
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 /*-----------------------------------------------------------------*/
4015 genAnd (iCode
* ic
, iCode
* ifx
)
4017 operand
*left
, *right
, *result
;
4018 int size
, offset
= 0;
4019 unsigned long lit
= 0L;
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
;
4039 /* if result = right then exchange them */
4040 if (pic14_sameRegs (AOP (result
), AOP (right
)))
4042 operand
*tmp
= right
;
4047 /* if right is bit then exchange them */
4048 if (AOP_TYPE (right
) == AOP_CRY
&& AOP_TYPE (left
) != AOP_CRY
)
4050 operand
*tmp
= right
;
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
);
4062 // result = bit & yy;
4063 if (AOP_TYPE (left
) == AOP_CRY
)
4065 // c = bit & literal;
4066 if (AOP_TYPE (right
) == AOP_LIT
)
4070 if (size
&& pic14_sameRegs (AOP (result
), AOP (left
)))
4073 pic14_emitcode ("mov", "c,%s", AOP (left
)->aopu
.aop_dir
);
4078 if (size
&& (AOP_TYPE (result
) == AOP_CRY
))
4080 pic14_emitcode ("clr", "%s", AOP (result
)->aopu
.aop_dir
);
4083 if ((AOP_TYPE (result
) == AOP_CRY
) && ifx
)
4088 pic14_emitcode ("clr", "c");
4093 if (AOP_TYPE (right
) == AOP_CRY
)
4096 pic14_emitcode ("mov", "c,%s", AOP (right
)->aopu
.aop_dir
);
4097 pic14_emitcode ("anl", "c,%s", AOP (left
)->aopu
.aop_dir
);
4102 MOVA (aopGet (AOP (right
), 0, FALSE
, FALSE
));
4104 pic14_emitcode ("rrc", "a");
4105 pic14_emitcode ("anl", "c,%s", AOP (left
)->aopu
.aop_dir
);
4111 pic14_outBitC (result
);
4113 else if ((AOP_TYPE (result
) == AOP_CRY
) && ifx
)
4114 genIfxJump (ifx
, "c");
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
);
4127 //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4130 pic14_emitcode ("mov", "c,acc.%d", posbit
& 0x07);
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
;
4153 symbol
*tlbl
= newiTempLabel (NULL
);
4154 int sizel
= AOP_SIZE (left
);
4156 pic14_emitcode ("setb", "c");
4159 if ((bytelit
= ((lit
>> (offset
* 8)) & 0x0FFL
)) != 0x0L
)
4162 if ((posbit
= isLiteralBit (bytelit
)) != 0)
4164 emitpcode (POC_BTFSC
,
4165 newpCodeOpBit (aopGet (AOP (left
), offset
, FALSE
, FALSE
), posbit
- 1, 0));
4169 mov2w (AOP (left
), offset
);
4170 emitpcode (POC_ANDLW
, newpCodeOpLit (bytelit
& 0x0ff));
4173 emitpcode (POC_GOTO
, popGetLabel (rIfx
.condition
?
4174 rIfx
.lbl
->key
: tlbl
->key
));
4178 if (!rIfx
.condition
)
4180 emitpcode (POC_GOTO
, popGetLabel (rIfx
.lbl
->key
));
4182 emitpLabel(tlbl
->key
);
4183 ifx
->generated
= TRUE
;
4184 // bit = left & literal
4187 pic14_emitcode ("clr", "c");
4188 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl
->key
));
4190 // if(left & literal)
4194 jmpTrueOrFalse (ifx
, tlbl
);
4198 pic14_outBitC (result
);
4202 /* if left is same as result */
4203 if (pic14_sameRegs (AOP (result
), AOP (left
)))
4206 for (; size
--; offset
++, lit
>>= 8)
4208 if (AOP_TYPE (right
) == AOP_LIT
)
4213 /* and'ing with 0 has clears the result */
4214 emitpcode (POC_CLRF
, popGet (AOP (result
), offset
));
4217 /* and'ing with 0xff is a nop when the result and left are the same */
4222 int p
= my_powof2 ((~lit
) & 0xff);
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));
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
));
4241 emitpcode (POC_MOVFW
, popGet (AOP (right
), offset
));
4242 emitpcode (POC_ANDWF
, popGet (AOP (left
), offset
));
4249 // left & result in different registers
4250 if (AOP_TYPE (result
) == AOP_CRY
)
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
));
4258 pic14_emitcode ("setb", "c");
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
));
4269 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl
->key
));
4270 pic14_outBitC (result
);
4273 jmpTrueOrFalse (ifx
, tlbl
);
4277 for (; (size
--); offset
++)
4280 // result = left & right
4281 if (AOP_TYPE (right
) == AOP_LIT
)
4283 int t
= (lit
>> (offset
* 8)) & 0x0FFL
;
4287 emitpcode (POC_CLRF
, popGet (AOP (result
), offset
));
4290 emitpcode (POC_MOVFW
, popGet (AOP (left
), offset
));
4291 emitpcode (POC_MOVWF
, popGet (AOP (result
), offset
));
4294 emitpcode (POC_MOVLW
, popGetLit (t
));
4295 emitpcode (POC_ANDFW
, popGet (AOP (left
), offset
));
4296 emitpcode (POC_MOVWF
, popGet (AOP (result
), offset
));
4301 emitpcode (POC_MOVFW
, popGet (AOP (right
), offset
));
4302 emitpcode (POC_ANDFW
, popGet (AOP (left
), offset
));
4303 emitpcode (POC_MOVWF
, popGet (AOP (result
), offset
));
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 /*-----------------------------------------------------------------*/
4318 genOr (iCode
* ic
, iCode
* ifx
)
4320 operand
*left
, *right
, *result
;
4321 int size
, offset
= 0;
4322 unsigned long lit
= 0L;
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
;
4341 /* if result = right then exchange them */
4342 if (pic14_sameRegs (AOP (result
), AOP (right
)))
4344 operand
*tmp
= right
;
4349 /* if right is bit then exchange them */
4350 if (AOP_TYPE (right
) == AOP_CRY
&& AOP_TYPE (left
) != AOP_CRY
)
4352 operand
*tmp
= right
;
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
);
4366 if (AOP_TYPE (left
) == AOP_CRY
)
4368 if (AOP_TYPE (right
) == AOP_LIT
)
4370 // c = bit & literal;
4373 // lit != 0 => result = 1
4374 if (AOP_TYPE (result
) == AOP_CRY
)
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);
4382 continueIfTrue (ifx
);
4388 // lit == 0 => result = left
4389 if (size
&& pic14_sameRegs (AOP (result
), AOP (left
)))
4391 pic14_emitcode (";XXX mov", "c,%s %s,%d", AOP (left
)->aopu
.aop_dir
, __FILE__
, __LINE__
);
4396 if (AOP_TYPE (right
) == AOP_CRY
)
4398 if (pic14_sameRegs (AOP (result
), AOP (left
)))
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
);
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));
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
);
4439 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl
->key
));
4446 pic14_outBitC (result
);
4448 else if ((AOP_TYPE (result
) == AOP_CRY
) && ifx
)
4449 genIfxJump (ifx
, "c");
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
))
4459 pic14_emitcode (";XXX ", " %s,%d", __FILE__
, __LINE__
);
4462 pic14_emitcode (";XXX setb", "%s", AOP (result
)->aopu
.aop_dir
);
4464 continueIfTrue (ifx
);
4469 pic14_emitcode (";XXX ", " %s,%d", __FILE__
, __LINE__
);
4470 // lit = 0, result = boolean(left)
4472 pic14_emitcode (";XXX setb", "c");
4473 pic14_toBoolean (left
);
4476 symbol
*tlbl
= newiTempLabel (NULL
);
4477 pic14_emitcode (";XXX jnz", "%05d_DS_", labelKey2num (tlbl
->key
));
4479 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl
->key
));
4483 genIfxJump (ifx
, "a");
4487 pic14_outBitC (result
);
4491 /* if left is same as result */
4492 if (pic14_sameRegs (AOP (result
), AOP (left
)))
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 */
4504 int p
= my_powof2 (lit
& 0xff);
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));
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
));
4522 emitpcode (POC_MOVFW
, popGet (AOP (right
), offset
));
4523 emitpcode (POC_IORWF
, popGet (AOP (left
), offset
));
4529 // left & result in different registers
4530 if (AOP_TYPE (result
) == AOP_CRY
)
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__
);
4541 pic14_emitcode (";XXX setb", "c");
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
));
4552 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl
->key
));
4553 pic14_outBitC (result
);
4556 jmpTrueOrFalse (ifx
, tlbl
);
4559 for (; (size
--); offset
++)
4562 // result = left | right
4563 if (AOP_TYPE (right
) == AOP_LIT
)
4565 int t
= (lit
>> (offset
* 8)) & 0x0FFL
;
4569 emitpcode (POC_MOVFW
, popGet (AOP (left
), offset
));
4570 emitpcode (POC_MOVWF
, popGet (AOP (result
), offset
));
4574 emitpcode (POC_MOVLW
, popGetLit (t
));
4575 emitpcode (POC_IORFW
, popGet (AOP (left
), offset
));
4576 emitpcode (POC_MOVWF
, popGet (AOP (result
), offset
));
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
));
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 /*-----------------------------------------------------------------*/
4599 genXor (iCode
* ic
, iCode
* ifx
)
4601 operand
*left
, *right
, *result
;
4602 int size
, offset
= 0;
4603 unsigned long lit
= 0L;
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
;
4624 /* if result = right then exchange them */
4625 if (pic14_sameRegs (AOP (result
), AOP (right
)))
4627 operand
*tmp
= right
;
4632 /* if right is bit then exchange them */
4633 if (AOP_TYPE (right
) == AOP_CRY
&& AOP_TYPE (left
) != AOP_CRY
)
4635 operand
*tmp
= right
;
4639 if (AOP_TYPE (right
) == AOP_LIT
)
4640 lit
= ulFromVal (AOP (right
)->aopu
.aop_lit
);
4642 size
= AOP_SIZE (result
);
4646 if (AOP_TYPE (left
) == AOP_CRY
)
4648 if (AOP_TYPE (right
) == AOP_LIT
)
4650 // c = bit & literal;
4653 // lit>>1 != 0 => result = 1
4654 if (AOP_TYPE (result
) == AOP_CRY
)
4658 emitpcode (POC_BSF
, popGet (AOP (result
), offset
));
4659 pic14_emitcode ("setb", "%s", AOP (result
)->aopu
.aop_dir
);
4662 continueIfTrue (ifx
);
4665 pic14_emitcode ("setb", "c");
4672 // lit == 0, result = left
4673 if (size
&& pic14_sameRegs (AOP (result
), AOP (left
)))
4675 pic14_emitcode ("mov", "c,%s", AOP (left
)->aopu
.aop_dir
);
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
);
4689 assert (!"incomplete genXor");
4690 pic14_emitcode ("mov", "c,%s", AOP (left
)->aopu
.aop_dir
);
4691 pic14_emitcode ("cpl", "c");
4700 symbol
*tlbl
= newiTempLabel (NULL
);
4701 if (AOP_TYPE (right
) == AOP_CRY
)
4704 pic14_emitcode ("mov", "c,%s", AOP (right
)->aopu
.aop_dir
);
4708 int sizer
= AOP_SIZE (right
);
4710 // if val>>1 != 0, result = 1
4711 pic14_emitcode ("setb", "c");
4714 MOVA (aopGet (AOP (right
), sizer
- 1, FALSE
, FALSE
));
4716 // test the msb of the lsb
4717 pic14_emitcode ("anl", "a,#0xfe");
4718 pic14_emitcode ("jnz", "%05d_DS_", labelKey2num (tlbl
->key
));
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
)));
4731 pic14_outBitC (result
);
4733 else if ((AOP_TYPE (result
) == AOP_CRY
) && ifx
)
4734 genIfxJump (ifx
, "c");
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
;
4750 emitpcode (POC_MOVLW
, popGetLit (t
));
4751 emitpcode (POC_XORWF
, popGet (AOP (left
), offset
));
4756 emitpcode (POC_MOVFW
, popGet (AOP (right
), offset
));
4757 emitpcode (POC_XORWF
, popGet (AOP (left
), offset
));
4763 // left & result in different registers
4764 if (AOP_TYPE (result
) == AOP_CRY
)
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
));
4772 pic14_emitcode ("setb", "c");
4775 if ((AOP_TYPE (right
) == AOP_LIT
) && (((lit
>> (offset
* 8)) & 0x0FFL
) == 0x00L
))
4777 MOVA (aopGet (AOP (left
), offset
, FALSE
, FALSE
));
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
;
4791 emitpcode (POC_MOVFW
, popGet (AOP (left
), offset
));
4794 emitpcode (POC_COMFW
, popGet (AOP (left
), offset
));
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
));
4811 emitpcode (POC_MOVFW
, popGet (AOP (right
), offset
));
4812 emitpcode (POC_XORFW
, popGet (AOP (left
), offset
));
4816 emitpcode (POC_GOTO
, popGetLabel (rIfx
.condition
?
4817 rIfx
.lbl
->key
: tlbl
->key
));
4820 if (!rIfx
.condition
)
4822 emitpcode (POC_GOTO
, popGetLabel (rIfx
.lbl
->key
));
4824 emitpLabel(tlbl
->key
);
4825 ifx
->generated
= TRUE
;
4829 pic14_emitcode ("", "%05d_DS_:", labelKey2num (tlbl
->key
));
4830 pic14_outBitC (result
);
4833 jmpTrueOrFalse (ifx
, tlbl
);
4836 for (; (size
--); offset
++)
4839 // result = left & right
4840 if (AOP_TYPE (right
) == AOP_LIT
)
4842 int t
= (lit
>> (offset
* 8)) & 0x0FFL
;
4846 emitpcode (POC_MOVFW
, popGet (AOP (left
), offset
));
4847 emitpcode (POC_MOVWF
, popGet (AOP (result
), offset
));
4850 emitpcode (POC_COMFW
, popGet (AOP (left
), offset
));
4851 emitpcode (POC_MOVWF
, popGet (AOP (result
), offset
));
4854 emitpcode (POC_MOVLW
, popGetLit (t
));
4855 emitpcode (POC_XORFW
, popGet (AOP (left
), offset
));
4856 emitpcode (POC_MOVWF
, popGet (AOP (result
), offset
));
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
));
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 /*-----------------------------------------------------------------*/
4879 pic14_genInline (iCode
* ic
)
4881 char *buffer
, *bp
, *bp1
;
4882 bool inComment
= FALSE
;
4885 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
4887 genLine
.lineElement
.isInline
+= (!options
.asmpeep
);
4889 buffer
= bp
= bp1
= Safe_strdup (IC_INLINE (ic
));
4905 addpCode2pBlock (pb
, newpCodeAsmDir (bp1
, NULL
)); // inline directly, no process
4910 /* Add \n for labels, not dirs such as c:\mydir */
4911 if (!inComment
&& (*bp
== ':') && (isspace ((unsigned char) bp
[1])))
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
4926 if ((bp1
!= bp
) && *bp1
)
4927 addpCode2pBlock (pb
, newpCodeAsmDir (bp1
, NULL
)); // inline directly, no process
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 /*-----------------------------------------------------------------*/
4943 operand
*left
, *result
;
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));
4966 emitpcode (POC_RRF
, popGet (AOP (left
), size
));
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 /*-----------------------------------------------------------------*/
4985 operand
*left
, *result
;
4986 int size
, offset
= 0;
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));
5013 emitpcode (POC_RLF
, popGet (AOP (left
), offset
));
5017 emitpcode (POC_RLFW
, popGet (AOP (left
), offset
));
5018 emitpcode (POC_MOVWF
, popGet (AOP (result
), offset
));
5025 freeAsmop (left
, NULL
, ic
, TRUE
);
5026 freeAsmop (result
, NULL
, ic
, TRUE
);
5030 genGetABit (iCode
* ic
)
5032 operand
*left
, *right
, *result
;
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;
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 */
5057 /* nothing more to do */
5060 /* keep W==0, force W=0x01 otherwise */
5062 emitpcode (POC_MOVLW
, popGetLit (1));
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
));
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 /*-----------------------------------------------------------------*/
5084 AccLsh (pCodeOp
* pcop
, int shCount
)
5087 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
5088 shCount
&= 0x0007; // shCount : 0..7
5096 emitpcode (POC_RLF
, pcop
);
5100 emitpcode (POC_RLF
, pcop
);
5101 emitpcode (POC_RLF
, pcop
);
5104 emitpcode (POC_RLF
, pcop
);
5105 emitpcode (POC_RLF
, pcop
);
5106 emitpcode (POC_RLF
, pcop
);
5109 emitpcode (POC_SWAPF
, pcop
);
5112 emitpcode (POC_SWAPF
, pcop
);
5113 emitpcode (POC_RLF
, pcop
);
5116 emitpcode (POC_SWAPF
, pcop
);
5117 emitpcode (POC_RLF
, pcop
);
5118 emitpcode (POC_RLF
, pcop
);
5121 emitpcode (POC_RRFW
, pcop
);
5122 emitpcode (POC_RRF
, pcop
);
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 /*-----------------------------------------------------------------*/
5138 AccRsh (pCodeOp
* pcop
, int shCount
, int mask_mode
)
5141 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
5142 shCount
&= 0x0007; // shCount : 0..7
5149 /* load sign if needed */
5151 emitpcode (POC_RLFW
, pcop
);
5152 else if (mask_mode
== 1)
5154 emitpcode (POC_RRF
, pcop
);
5158 /* load sign if needed */
5160 emitpcode (POC_RLFW
, pcop
);
5161 emitpcode (POC_RRF
, pcop
);
5162 /* load sign if needed */
5164 emitpcode (POC_RLFW
, pcop
);
5165 emitpcode (POC_RRF
, pcop
);
5170 /* load sign if needed */
5172 emitpcode (POC_RLFW
, pcop
);
5173 emitpcode (POC_RRF
, pcop
);
5174 /* load sign if needed */
5176 emitpcode (POC_RLFW
, pcop
);
5177 emitpcode (POC_RRF
, pcop
);
5178 /* load sign if needed */
5180 emitpcode (POC_RLFW
, pcop
);
5181 emitpcode (POC_RRF
, pcop
);
5186 emitpcode (POC_SWAPF
, pcop
);
5189 emitpcode (POC_SWAPF
, pcop
);
5190 emitpcode (POC_RRF
, pcop
);
5193 emitpcode (POC_SWAPF
, pcop
);
5194 emitpcode (POC_RRF
, pcop
);
5195 emitpcode (POC_RRF
, pcop
);
5201 emitpcode (POC_RLFW
, pcop
);
5202 emitpcode (POC_CLRF
, pcop
);
5204 emitpcode (POC_COMF
, pcop
);
5209 emitpcode (POC_RLFW
, pcop
);
5210 emitpcode (POC_RLF
, pcop
);
5217 /* leave invalid bits undefined */
5221 /* clear invalid bits -- zero-extend */
5222 emitpcode (POC_MOVLW
, popGetLit (0x00ff >> shCount
));
5223 emitpcode (POC_ANDWF
, pcop
);
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 /*-----------------------------------------------------------------*/
5238 movLeft2Result (operand
* left
, int offl
, operand
* result
, int offr
)
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 /*-----------------------------------------------------------------*/
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
));
5267 shCount
= shCount
& 0x07;
5279 case 0: /* takes 0 or 2N cycles (for offr==0) */
5282 for (i
= size
- 1; i
>= 0; i
--)
5283 movLeft2Result (left
, i
, result
, offr
+ i
);
5287 case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
5290 shiftLeft_Left2ResultLit (left
, result
, 8 * offr
);
5291 shiftLeft_Left2ResultLit (result
, result
, shCount
);
5292 return; /* prevent clearing result again */
5296 if (pic
->isEnhancedCore
)
5298 for (i
= 0; i
< size
; i
++)
5304 emitpcode (POC_LSLF
, popGet (AOP (left
), i
));
5308 emitpcode (POC_RLF
, popGet (AOP (left
), i
));
5315 emitpcode (POC_LSLFW
, popGet (AOP (left
), i
));
5319 emitpcode (POC_RLFW
, popGet (AOP (left
), i
));
5322 emitpcode (POC_MOVWF
, popGet (AOP (result
), i
+ offr
));
5329 for (i
= 0; i
< size
; i
++)
5333 emitpcode (POC_RLF
, popGet (AOP (left
), i
));
5337 emitpcode (POC_RLFW
, popGet (AOP (left
), i
));
5338 emitpcode (POC_MOVWF
, popGet (AOP (result
), i
+ offr
));
5341 } // if (pic->isEnhancedCore)
5342 } // if (same && offr)
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
));
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));
5369 emitpcode (POC_CLRF
, popGet (AOP (result
), offr
));
5370 emitpcode (POC_RRF
, popGet (AOP (result
), offr
));
5374 shiftLeft_Left2ResultLit (left
, result
, offr
* 8 + shCount
- 1);
5375 shiftLeft_Left2ResultLit (result
, result
, 1);
5376 return; /* prevent clearing result again */
5383 emitpcode (POC_CLRF
, popGet (AOP (result
), offr
));
5387 /*-----------------------------------------------------------------*/
5388 /* shiftRight_Left2ResultLit - shift right by known count */
5389 /*-----------------------------------------------------------------*/
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
));
5403 shCount
= shCount
& 0x07;
5407 size
= AOP_SIZE (result
);
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));
5415 emitpcode (POC_MOVWF
, popGet (AOP (result
), size
));
5422 emitpcode (POC_CLRF
, popGet (AOP (result
), size
));
5432 case 0: /* takes 0 or 2N cycles (for offr==0) */
5435 for (i
= 0; i
< size
; i
++)
5436 movLeft2Result (left
, i
+ offr
, result
, i
);
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
,
5445 shiftRight_Left2ResultLit (left
, result
, 8 * offr
, sign
);
5446 shiftRight_Left2ResultLit (result
, result
, shCount
, sign
);
5447 return; /* prevent sign-extending result again */
5451 if (pic
->isEnhancedCore
)
5453 for (i
= size
- 1; i
>= 0; i
--)
5457 if (i
== (size
- 1))
5461 emitpcode (POC_ASRF
, popGet (AOP (left
), i
));
5465 emitpcode (POC_LSRF
, popGet (AOP (left
), i
));
5470 emitpcode (POC_RRF
, popGet (AOP (left
), i
));
5475 if (i
== (size
- 1))
5479 emitpcode (POC_ASRFW
, popGet (AOP (left
), i
+ offr
));
5483 emitpcode (POC_LSRFW
, popGet (AOP (left
), i
+ offr
));
5488 emitpcode (POC_RRFW
, popGet (AOP (left
), i
+ offr
));
5491 emitpcode (POC_MOVWF
, popGet (AOP (result
), i
));
5492 } // if (same && !offr)
5500 emitpcode (POC_BTFSC
, newpCodeOpBit (aopGet (AOP (left
), AOP_SIZE (left
) - 1, FALSE
, FALSE
), 7, 0));
5504 for (i
= size
- 1; i
>= 0; i
--)
5508 emitpcode (POC_RRF
, popGet (AOP (left
), i
));
5512 emitpcode (POC_RRFW
, popGet (AOP (left
), i
+ offr
));
5513 emitpcode (POC_MOVWF
, popGet (AOP (result
), i
));
5516 } // if (pic->isEnhancedCore)
5517 } // if (same && offr)
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
));
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));
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
));
5551 emitpcode (POC_CLRF
, popGet (AOP (result
), size
- 1));
5554 emitpcode (POC_RLF
, popGet (AOP (result
), size
- 1));
5559 emitpcode (POC_DECF
, popGet (AOP (result
), size
- 1));
5564 shiftRight_Left2ResultLit (left
, result
, offr
* 8 + shCount
- 1, sign
);
5565 shiftRight_Left2ResultLit (result
, result
, 1, sign
);
5566 return; /* prevent sign extending result again */
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 *-----------------------------------------------------------------*/
5580 genMultiAsm (PIC_OPCODE poc
, operand
* reg
, int size
, int endian
)
5586 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
5603 emitpcode (poc
, popGet (AOP (reg
), offset
));
5609 /*-----------------------------------------------------------------*/
5610 /* loadSignToC - load the operand's sign bit into CARRY */
5611 /*-----------------------------------------------------------------*/
5614 loadSignToC (operand
* op
)
5617 assert (op
&& AOP (op
) && AOP_SIZE (op
));
5620 emitpcode (POC_BTFSC
, newpCodeOpBit (aopGet (AOP (op
), AOP_SIZE (op
) - 1, FALSE
, FALSE
), 7, 0));
5624 /*-----------------------------------------------------------------*/
5625 /* genRightShift - generate code for right shifting */
5626 /*-----------------------------------------------------------------*/
5628 genGenericShift (iCode
* ic
, int shiftRight
)
5630 operand
*right
, *left
, *result
;
5632 symbol
*tlbl
, *tlbl1
, *inverselbl
;
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
);
5662 shiftRight
= !shiftRight
;
5666 shiftRight_Left2ResultLit (left
, result
, lit
, !SPEC_USIGN (operandType (left
)));
5668 shiftLeft_Left2ResultLit (left
, result
, lit
);
5669 //genRightShiftLiteral (left,right,result,ic, 0);
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
5684 if (!pic14_sameRegs (AOP (left
), AOP (result
)))
5686 size
= min (AOP_SIZE (result
), AOP_SIZE (left
));
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
);
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
));
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' */
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) */
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
)))
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));
5741 emitpcode (POC_GOTO
, popGetLabel (inv_loop
->key
));
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 /*-----------------------------------------------------------------*/
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)
5762 else if (IS_OP_LITERAL (right
) && operandLitValueUll (right
) % lbits
== lbits
- 1)
5765 wassertl (0, "Unsupported rotation.");
5769 genRightShift (iCode
* ic
)
5771 genGenericShift (ic
, 1);
5775 genLeftShift (iCode
* ic
)
5777 genGenericShift (ic
, 0);
5780 /*-----------------------------------------------------------------*/
5781 /* SetIrp - Set IRP bit */
5782 /*-----------------------------------------------------------------*/
5784 SetIrp (operand
* result
)
5787 if (AOP_TYPE (result
) == AOP_LIT
)
5789 unsigned lit
= (unsigned) double2ul (operandLitValue (result
));
5795 else if ((AOP_TYPE (result
) == AOP_PCODE
) && (AOP (result
)->aopu
.pcop
->type
== PO_LITERAL
))
5797 int addrs
= PCOL (AOP (result
)->aopu
.pcop
)->lit
;
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));
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));
5823 setup_fsr (operand
* ptr
)
5825 if (pic
->isEnhancedCore
)
5828 emitpcode (POC_MOVWF
, popCopyReg (&pc_fsr0l
));
5830 emitpcode (POC_MOVWF
, popCopyReg (&pc_fsr0h
));
5835 emitpcode (POC_MOVWF
, popCopyReg (&pc_fsr
));
5837 /* also setup-up IRP */
5847 /* Nothing to do. */
5851 if (pic
->isEnhancedCore
)
5853 if (pic14_options
.no_ext_instr
)
5856 * Not sure if we may modify W here, so implement this without
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.
5866 emitpcode (POC_INCFSZ
, popCopyReg (&pc_fsr0l
));
5867 emitpcode (POC_DECF
, popCopyReg (&pc_fsr0h
));
5868 emitpcode (POC_INCF
, popCopyReg (&pc_fsr0h
));
5873 addpCode2pBlock (pb
, newpCodeAsmDir("MOVF", "FSR0L, 1"));
5875 emitpcode (POC_DECF
, popCopyReg (&pc_fsr0h
));
5876 emitpcode (POC_DECF
, popCopyReg (&pc_fsr0l
));
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
));
5892 emitpcode (POC_INCF
, popCopyReg (&pc_fsr
));
5897 emitpcode (POC_DECF
, popCopyReg (&pc_fsr
));
5903 /*-----------------------------------------------------------------*/
5904 /* emitPtrByteGet - emits code to get a byte into WREG from an */
5905 /* arbitrary pointer (__code, __data, generic) */
5906 /*-----------------------------------------------------------------*/
5908 emitPtrByteGet (operand
* src
, int p_type
, bool alreadyAddressed
)
5915 if (!alreadyAddressed
)
5917 emitpcode (POC_MOVFW
, popCopyReg (pc_indf
));
5921 assert (AOP_SIZE (src
) == 2);
5923 emitpcode (POC_MOVWF
, popRegFromIdx (Gstack_base_addr
- 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");
5931 assert (AOP_SIZE (src
) == 3);
5933 emitpcode (POC_MOVWF
, popRegFromIdx (Gstack_base_addr
- 1));
5935 emitpcode (POC_MOVWF
, popRegFromIdx (Gstack_base_addr
));
5937 call_libraryfunc ("__gptrget1");
5941 assert (!"unhandled pointer type");
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 /*-----------------------------------------------------------------*/
5951 emitPtrByteSet (operand
* dst
, int p_type
, bool alreadyAddressed
)
5958 if (!alreadyAddressed
)
5960 emitpcode (POC_MOVWF
, popCopyReg (pc_indf
));
5964 assert (!"trying to assign to __code pointer");
5968 emitpcode (POC_MOVWF
, popRegFromIdx (Gstack_base_addr
- 2));
5970 emitpcode (POC_MOVWF
, popRegFromIdx (Gstack_base_addr
- 1));
5972 emitpcode (POC_MOVWF
, popRegFromIdx (Gstack_base_addr
));
5974 call_libraryfunc ("__gptrput1");
5978 assert (!"unhandled pointer type");
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.
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" };
6000 size
= AOP_SIZE(result
);
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 */
6011 /* bits to mask in the last byte */
6017 mask
= (((1UL << blen
) - 1) << bstr
) & 0x00ff;
6022 assert (size
> 0 && size
<= 4);
6029 emitpcode (POC_MOVFW
, popGet (AOP (left
), offset
));
6031 emitpcode (POC_ANDLW
, popGetLit (mask
));
6032 movwf (AOP (result
), offset
);
6040 assert (AOP_SIZE (left
) == 2);
6044 emitpcode (POC_MOVFW
, popCopyReg (pc_indf
));
6046 emitpcode (POC_ANDLW
, popGetLit (mask
));
6047 movwf (AOP (result
), offset
);
6057 assert (AOP_SIZE (left
) == 3);
6059 emitpcode (POC_MOVWF
, popRegFromIdx (Gstack_base_addr
- 1));
6061 emitpcode (POC_MOVWF
, popRegFromIdx (Gstack_base_addr
));
6066 /* special case: assign from __code */
6067 assert (OP_IN_CODE_SPACE(left
) || AOP_SIZE (left
) == 2);
6069 emitpcode (POC_MOVWF
, popRegFromIdx (Gstack_base_addr
- 1));
6071 emitpcode (POC_MOVWF
, popRegFromIdx (Gstack_base_addr
));
6072 emitpcode (POC_MOVLW
, popGetLit (GPTRTAG_CODE
)); /* GPOINTER tag for __code space */
6076 assert (!"unhandled pointer type");
6079 /* This is for GPOINTER and CPOINTER only */
6081 call_libraryfunc (func
[size
]);
6084 emitpcode (POC_ANDLW
, popGetLit (mask
));
6087 movwf (AOP (result
), --size
);
6090 emitpcode (POC_MOVFW
, popRegFromIdx (Gstack_base_addr
- offset
++));
6091 movwf (AOP (result
), size
);
6096 /* This is for all pointers */
6098 /* Handle the partial byte at the end */
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 /*-----------------------------------------------------------------*/
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 */
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 */
6138 /* that is for an if statement */
6142 resolveIfx (&rIfx
, ifx
);
6143 if (ptype
== -1) /* direct */
6144 pcop
= newpCodeOpBit (aopGet (AOP (left
), 0, FALSE
, FALSE
), bstr
, 0);
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
;
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
);
6165 assert (!pic14_sameRegs (AOP (result
), AOP (left
)));
6166 emitpcode (POC_CLRF
, popGet (AOP (result
), 0));
6172 emitpcode (POC_BTFSC
, newpCodeOpBit (aopGet (AOP (left
), 0, FALSE
, FALSE
), bstr
, 0));
6173 /* If haveResult, adjust result below, otherwise: */
6176 /* Dummy instruction to allow bit-test above (volatile dummy bitfield read). */
6177 emitpcode (POC_MOVLW
, popGetLit (0));
6185 emitPtrByteGet (left
, ptype
, FALSE
);
6188 emitpcode (POC_ANDLW
, popGetLit (1UL << bstr
));
6190 /* adjust result below */
6195 assert (!"unhandled pointer type");
6198 /* move sign-/zero extended bit to result */
6201 if (SPEC_USIGN (OP_SYM_ETYPE (left
)))
6202 emitpcode (POC_INCF
, popGet (AOP (result
), 0));
6204 emitpcode (POC_DECF
, popGet (AOP (result
), 0));
6205 addSign (result
, 1, !SPEC_USIGN (OP_SYM_ETYPE (left
)));
6211 emitPtrGet (result
, left
, ptype
, blen
, bstr
);
6216 /*-----------------------------------------------------------------*/
6217 /* genDataPointerGet - generates code when ptr offset is known */
6218 /*-----------------------------------------------------------------*/
6220 genDataPointerGet (operand
* left
, operand
* result
, iCode
* ic
)
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
6233 aopOp (result
, ic
, TRUE
);
6235 if (pic14_sameRegs (AOP (left
), AOP (result
)))
6238 DEBUGpic14_AopType (__LINE__
, left
, NULL
, result
);
6240 //emitpcode(POC_MOVFW, popGet(AOP(left),0));
6242 size
= AOP_SIZE (result
);
6247 emitpcode (POC_MOVFW
, popGet (AOP (left
), offset
));
6248 emitpcode (POC_MOVWF
, popGet (AOP (result
), offset
));
6253 freeAsmop (left
, NULL
, ic
, TRUE
);
6254 freeAsmop (result
, NULL
, ic
, TRUE
);
6258 /*-----------------------------------------------------------------*/
6259 /* genNearPointerGet - pic14_emitcode for near pointer fetch */
6260 /*-----------------------------------------------------------------*/
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 */
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
);
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
))
6295 if (IS_BITFIELD (getSpec (operandType (result
))))
6297 genUnpackBits (result
, left
, direct
? -1 : POINTER
, ifxForOp (IC_RESULT (ic
), ic
));
6301 emitPtrGet (result
, left
, direct
? -1 : POINTER
, 0, 0);
6305 freeAsmop (left
, NULL
, ic
, TRUE
);
6306 freeAsmop (result
, NULL
, ic
, TRUE
);
6310 /*-----------------------------------------------------------------*/
6311 /* genGenPointerGet - gget value from generic pointer space */
6312 /*-----------------------------------------------------------------*/
6314 genGenPointerGet (operand
* left
, operand
* result
, iCode
* ic
)
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
));
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 /*-----------------------------------------------------------------*/
6342 genConstPointerGet (operand
* left
, operand
* result
, iCode
* ic
)
6344 //sym_link *retype = getSpec(operandType(result));
6346 symbol
*albl
, *blbl
; //, *clbl;
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
));
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 /*-----------------------------------------------------------------*/
6377 genPointerGet (iCode
* ic
)
6379 operand
*left
, *result
;
6380 sym_link
*type
, *etype
;
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
);
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; */
6422 DEBUGpic14_emitcode ("; ***", "%d - pointer", __LINE__
);
6423 /* p_type = POINTER ; */
6426 /* now that we have the pointer type we assign
6427 the pointer values */
6434 genNearPointerGet (left
, result
, ic
);
6438 genPagedPointerGet(left,result,ic);
6442 genFarPointerGet (left,result,ic);
6446 genConstPointerGet (left
, result
, ic
);
6450 genGenPointerGet (left
, result
, ic
);
6453 assert (!"unhandled pointer type");
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.
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" };
6472 pCodeOp
*temp
= NULL
;
6473 int litval
= 0; /* source literal value (if AOP_LIT) */
6474 unsigned char mask
= 0; /* bitmask within current byte */
6480 size
= AOP_SIZE(right
);
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 */
6491 /* bits to mask in the last byte */
6494 /* If there was a partial byte at the end */
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
);
6505 litval
>>= 8 * size
;
6506 litval
&= (~mask
) & 0xff;
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
);
6517 AccLsh (temp
, bstr
);
6520 /* Include the last byte into the size count */
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
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'.
6534 //assert (size == getSize(OP_SYM_ETYPE(result)));
6535 assert (size
> 0 && size
<= 4);
6544 if (AOP_TYPE (right
) == AOP_LIT
)
6545 emitpcode (POC_MOVLW
, popGet (AOP (right
), offset
));
6547 emitpcode (POC_MOVFW
, popGet (AOP (right
), offset
));
6548 movwf (AOP (result
), offset
);
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
));
6560 emitpcode (POC_IORLW
, popGetLit (litval
));
6564 emitpcode (POC_ANDLW
, popGetLit (mask
));
6565 emitpcode (POC_IORFW
, temp
);
6567 movwf (AOP (result
), offset
);
6573 /* GPOINTER should point to data space, because code space is not writeable */
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) */
6586 mov2w_op (right
, off
);
6587 emitpcode (POC_MOVWF
, popRegFromIdx (Gstack_base_addr
- idx
++));
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
]);
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));
6607 if (pic
->isEnhancedCore
)
6608 emitpcode (POC_BRA
, popGetLabel (lbl
->key
));
6610 emitpcode (POC_GOTO
, popGetLabel (lbl
->key
));
6619 if (AOP_TYPE (right
) == AOP_LIT
)
6620 emitpcode (POC_MOVLW
, popGet (AOP (right
), offset
));
6622 emitpcode (POC_MOVFW
, popGet (AOP (right
), offset
));
6623 emitpcode (POC_MOVWF
, popCopyReg (pc_indf
));
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
));
6638 emitpcode (POC_IORLW
, popGetLit (litval
));
6642 emitpcode (POC_ANDLW
, popGetLit (mask
));
6643 emitpcode (POC_IORFW
, temp
);
6645 emitpcode (POC_MOVWF
, popCopyReg (pc_indf
));
6649 emitpLabel (lbl
->key
);
6653 assert (!"trying to assign via pointer to __code space");
6657 assert (!"unhandled pointer type");
6661 popReleaseTempReg (temp
);
6664 /*-----------------------------------------------------------------*/
6665 /* genPackBits - generates code for packed bit storage */
6666 /*-----------------------------------------------------------------*/
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 */
6674 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
6676 blen
= SPEC_BLEN (etype
);
6677 bstr
= SPEC_BSTR (etype
);
6679 /* single bit field case */
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
);
6692 if (AOP (result
)->type
== AOP_PCODE
)
6693 pcop
= newpCodeOpBit (aopGet (AOP (result
), 0, FALSE
, FALSE
), bstr
, 0);
6695 pcop
= popGet (AOP (result
), 0);
6696 emitpcode (lit
? POC_BSF
: POC_BCF
, pcop
);
6702 emitpcode (lit
? POC_BSF
: POC_BCF
, newpCodeOpBit (PCOP (pc_indf
)->name
, bstr
, 0));
6706 assert (!"trying to assign to bitfield via pointer to __code space");
6710 emitPtrByteGet (result
, p_type
, FALSE
);
6713 emitpcode (POC_IORLW
, newpCodeOpLit (1UL << bstr
));
6717 emitpcode (POC_ANDLW
, newpCodeOpLit ((~(1UL << bstr
)) & 0x0ff));
6719 emitPtrByteSet (result
, p_type
, TRUE
);
6723 assert (!"unhandled pointer type");
6725 } // switch (p_type)
6729 /* right is no literal */
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);
6739 pcop
= popGet (AOP (result
), 0);
6740 emitpcode (POC_RRFW
, popGet (AOP (right
), 0));
6742 emitpcode (POC_BCF
, pcop
);
6744 emitpcode (POC_BSF
, pcop
);
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
);
6759 assert (!"trying to assign to bitfield via pointer to __code space");
6763 assert (!"unhandled pointer type");
6766 } // if (AOP(right)->type != AOP_LIT)
6770 emitPtrPut (right
, result
, p_type
, blen
, bstr
);
6774 /*-----------------------------------------------------------------*/
6775 /* genDataPointerSet - remat pointer to data space */
6776 /*-----------------------------------------------------------------*/
6778 genDataPointerSet (operand
* right
, operand
* result
, iCode
* ic
)
6782 sym_link
*rtype
= operandType(right
);
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
))
6803 emitpcode(POC_MOVLW
, popGetAddr(AOP(right
), size
, 0));
6804 emitpcode(POC_MOVWF
, popGet(AOP(result
), size
));
6809 // tsd, was l+1 - the underline `_' prefix was being stripped
6812 emitpComment ("%s:%u: size=%d, offset=%d, AOP_TYPE(res)=%d", __FILE__
, __LINE__
, size
, offset
,
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);
6821 emitpcode (POC_MOVLW
, popGetLit (lit
& 0xff));
6822 emitpcode (POC_MOVWF
, popGet (AOP (result
), offset
));
6826 emitpcode (POC_CLRF
, popGet (AOP (result
), offset
));
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
));
6839 freeAsmop (right
, NULL
, ic
, TRUE
);
6840 freeAsmop (result
, NULL
, ic
, TRUE
);
6843 /*-----------------------------------------------------------------*/
6844 /* genNearPointerSet - pic14_emitcode for near pointer put */
6845 /*-----------------------------------------------------------------*/
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
);
6856 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
6857 aopOp (result
, ic
, FALSE
);
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
);
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
))
6880 if (IS_BITFIELD (letype
))
6882 genPackBits (letype
, result
, right
, direct
? -1 : POINTER
);
6886 emitPtrPut (right
, result
, direct
? -1 : POINTER
, 0, 0);
6889 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
6892 freeAsmop (right
, NULL
, ic
, TRUE
);
6893 freeAsmop (result
, NULL
, ic
, TRUE
);
6896 /*-----------------------------------------------------------------*/
6897 /* genGenPointerSet - set value from generic pointer space */
6898 /*-----------------------------------------------------------------*/
6900 genGenPointerSet (operand
* right
, operand
* result
, iCode
* ic
)
6902 sym_link
*retype
= getSpec (operandType (result
));
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
);
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 /*-----------------------------------------------------------------*/
6929 genPointerSet (iCode
* ic
)
6931 operand
*right
, *result
;
6932 sym_link
*type
, *etype
;
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
);
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 ; */
6959 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6960 /* p_type = FPOINTER ; */
6962 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6963 /* p_type = PPOINTER ; */
6965 /* if (SPEC_OCLS(etype) == idata ) */
6966 /* p_type = IPOINTER ; */
6968 /* p_type = POINTER ; */
6971 /* now that we have the pointer type we assign
6972 the pointer values */
6978 genNearPointerSet (right
, result
, ic
);
6982 genPagedPointerSet (right,result,ic);
6986 genFarPointerSet (right,result,ic);
6990 genGenPointerSet (right
, result
, ic
);
6994 werror (E_INTERNAL_ERROR
, __FILE__
, __LINE__
, "genPointerSet: illegal pointer type");
6999 /*-----------------------------------------------------------------*/
7000 /* genIfx - generate code for Ifx statement */
7001 /*-----------------------------------------------------------------*/
7003 genIfx (iCode
* ic
, iCode
* popIc
)
7005 operand
*cond
= IC_COND (ic
);
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
);
7019 /* if there was something to be popped then do it */
7025 /* This assumes that CARRY is set iff cond is true */
7028 assert (!IC_FALSE (ic
));
7029 emitpcode (POC_BTFSC
, popGet (AOP (cond
), 0));
7031 emitpcode (POC_GOTO
, popGetLabel (IC_TRUE (ic
)->key
));
7035 assert (IC_FALSE (ic
));
7036 emitpcode (POC_BTFSS
, popGet (AOP (cond
), 0));
7038 emitpcode (POC_GOTO
, popGetLabel (IC_FALSE (ic
)->key
));
7042 static int hasWarned
= 0;
7045 fprintf (stderr
, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n",
7046 ic
->filename
, ic
->lineno
);
7053 /* now Z is set iff !cond */
7056 assert (!IC_FALSE (ic
));
7058 emitpcode (POC_GOTO
, popGetLabel (IC_TRUE (ic
)->key
));
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 /*-----------------------------------------------------------------*/
7077 genAddrOf (iCode
* ic
)
7079 operand
*right
, *result
, *left
;
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. */
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
)));
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
)))
7132 if (size
> GPTRSIZE
- 1)
7133 size
= GPTRSIZE
- 1;
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
));
7144 emitpcode (POC_MOVLW
, popGet (AOP (left
), offset
));
7145 emitpcode (POC_MOVWF
, popGet (AOP (result
), 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 /*-----------------------------------------------------------------*/
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
);
7177 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
7179 /* if they are the same */
7180 if (operandsEqu (IC_RESULT (ic
), IC_RIGHT (ic
)))
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
)))
7192 /* special case: assign from __code */
7193 if (OP_IN_CODE_SPACE(right
))
7195 emitpComment ("genAssign from CODESPACE");
7196 genConstPointerGet (right
, result
, ic
);
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
);
7220 pic14_emitcode ("bcf", "(%s >> 3),(%s & 7)", AOP (result
)->aopu
.aop_dir
, AOP (result
)->aopu
.aop_dir
);
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
);
7238 emitpcode (POC_BCF
, popGet (AOP (result
), 0));
7239 pic14_toBoolean (right
);
7241 emitpcode (POC_BSF
, popGet (AOP (result
), 0));
7242 //aopPut(AOP(result),"a",0);
7246 /* bit variables done */
7248 size
= AOP_SIZE (result
);
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
));
7261 DEBUGpic14_emitcode ("; WARNING", "%s %d ignoring register storage", __FUNCTION__
, __LINE__
);
7264 if (size
> AOP_SIZE(right
))
7265 size
= AOP_SIZE(right
);
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;
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
));
7282 emitpcode (POC_CLRF
, popGet (AOP (result
), offset
));
7285 else if (AOP_TYPE (right
) == AOP_CRY
)
7287 emitpcode (POC_CLRF
, popGet (AOP (result
), offset
));
7290 emitpcode (POC_BTFSS
, popGet (AOP (right
), 0));
7291 emitpcode (POC_INCF
, popGet (AOP (result
), 0));
7296 mov2w_op (right
, offset
);
7297 emitpcode (POC_MOVWF
, popGet (AOP (result
), 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
)));
7308 freeAsmop (right
, NULL
, ic
, FALSE
);
7309 freeAsmop (result
, NULL
, ic
, TRUE
);
7312 /*-----------------------------------------------------------------*/
7313 /* genJumpTab - generates code for jump table */
7314 /*-----------------------------------------------------------------*/
7316 genJumpTab (iCode
* ic
)
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
);
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));
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 /*-----------------------------------------------------------------*/
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
);
7371 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
7372 /* if they are equivalent then do nothing */
7373 if (operandsEqu (IC_RESULT (ic
), IC_RIGHT (ic
)))
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
))
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));
7399 emitpcode (POC_CLRF
, popGet (AOP (result
), offset
++));
7404 if (IS_BOOL (operandType (result
)))
7406 pic14_toBoolean (right
);
7408 emitpcode (POC_MOVLW
, popGetLit (1));
7409 emitpcode (POC_MOVWF
, popGet (AOP (result
), 0));
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__);
7433 if ((IS_SYMOP(right
) && OP_SYMBOL(right
)->remat
) || IS_FUNC(operandType(right
)))
7440 mov2w_op (right
, size
);
7442 emitpcode (POC_MOVFW
, popGet (AOP (right
), size
));
7443 movwf (AOP (result
), size
);
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__);
7457 switch (DCL_TYPE (rtype
))
7459 case POINTER
: /* __data */
7460 case FPOINTER
: /* __data */
7461 assert (AOP_SIZE (right
) == 2);
7465 case CPOINTER
: /* __code */
7466 assert (AOP_SIZE (right
) == 2);
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
)
7480 assert (!"unhandled pointer type");
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
)
7490 DEBUGpic14_emitcode ("; ***", "%s %d (tag=%d)", __FUNCTION__
, __LINE__
, tag
);
7494 /* convert other values into pointers to __data space */
7496 DEBUGpic14_emitcode ("; ***", "%s %d (tag=%d)", __FUNCTION__
, __LINE__
, tag
);
7501 emitpcode (POC_CLRF
, popGet (AOP (result
), size
++));
7505 emitpcode (POC_MOVLW
, popGetLit (tag
));
7506 movwf (AOP (result
), size
++);
7509 addSign (result
, size
, 0);
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
)))
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__
);
7540 /* if they in different places then copy */
7541 size
= AOP_SIZE (result
);
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),
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
);
7566 emitpcode (POC_MOVFW
, popGet (AOP (right
), offset
));
7567 emitpcode (POC_MOVWF
, popGet (AOP (result
), offset
));
7571 addSign (result
, AOP_SIZE (right
), !SPEC_USIGN (rtype
));
7574 freeAsmop (right
, NULL
, ic
, TRUE
);
7575 freeAsmop (result
, NULL
, ic
, TRUE
);
7579 /*-----------------------------------------------------------------*/
7580 /* genDjnz - generate decrement & jump if not zero instruction */
7581 /*-----------------------------------------------------------------*/
7583 genDjnz (iCode
* ic
, iCode
* ifx
)
7586 DEBUGpic14_emitcode ("; ***", "%s %d", __FUNCTION__
, __LINE__
);
7591 /* if the if condition has a false label
7592 then we cannot save */
7596 /* if the minus is not of the form
7598 if (!isOperandEqual (IC_RESULT (ic
), IC_LEFT (ic
)) || !IS_OP_LITERAL (IC_RIGHT (ic
)))
7601 if (operandLitValue (IC_RIGHT (ic
)) != 1)
7604 /* if the size of this greater than one then no
7606 if (getSize (operandType (IC_RESULT (ic
))) > 1)
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
;
7620 /*-----------------------------------------------------------------*/
7621 /* genReceive - generate code for a receive iCode */
7622 /*-----------------------------------------------------------------*/
7624 genReceive (iCode
* ic
)
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
;
7636 pic14_emitcode ("push", "%s", (strcmp (fReturn
[fReturnSizePic
- offset
- 1], "a") ?
7637 fReturn
[fReturnSizePic
- offset
- 1] : "acc"));
7640 aopOp (IC_RESULT (ic
), ic
, FALSE
);
7641 size
= AOP_SIZE (IC_RESULT (ic
));
7645 pic14_emitcode ("pop", "acc");
7646 aopPut (AOP (IC_RESULT (ic
)), "a", offset
++);
7653 aopOp (IC_RESULT (ic
), ic
, FALSE
);
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 /*-----------------------------------------------------------------*/
7666 genDummyRead (iCode
* ic
)
7669 pic14_emitcode ("; genDummyRead", "");
7670 pic14_emitcode ("; not implemented", "");
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 *-----------------------------------------------------------------*/
7688 genpic14Code (iCode
* lic
)
7696 pic
= pic14_getPIC();
7698 pb
= newpCodeChain (GcurMemmap
, 0, newpCodeCharP ("; Starting pCode block"));
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
))
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
));
7734 /* if the result is marked as
7735 spilt and rematerializable or code for
7736 this has already been generated then
7738 if (resultRemat (ic
) || ic
->generated
)
7741 /* depending on the operation */
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
);
7786 genEndFunction (ic
);
7806 if (!genDjnz (ic
, ifxForOp (IC_RESULT (ic
), ic
)))
7823 genCmpGt (ic
, ifxForOp (IC_RESULT (ic
), ic
));
7827 genCmpLt (ic
, ifxForOp (IC_RESULT (ic
), ic
));
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");
7841 genCmpEq (ic
, ifxForOp (IC_RESULT (ic
), ic
));
7853 genXor (ic
, ifxForOp (IC_RESULT (ic
), ic
));
7857 genOr (ic
, ifxForOp (IC_RESULT (ic
), ic
));
7861 genAnd (ic
, ifxForOp (IC_RESULT (ic
), ic
));
7865 pic14_genInline (ic
);
7884 case GET_VALUE_AT_ADDRESS
:
7889 if (POINTER_SET (ic
))
7916 addSet (&_G
.sendSet
, ic
);
7919 case DUMMY_READ_VOLATILE
:
7928 genEndCritical (ic
);
7932 fprintf (stderr
, "UNHANDLED iCode: ");
7933 piCode (ic
, stderr
);
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
);
7950 DFPRINTF ((stderr
, "printing pBlock\n\n"));
7951 printpBlock (stdout
, pb
);
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. */
7962 aop_isLitLike (asmop
* aop
)
7965 if (aop
->type
== AOP_LIT
)
7967 if (aop
->type
== AOP_IMMD
)
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) */
7981 op_isLitLike (operand
* op
)
7984 if (aop_isLitLike (AOP (op
)))
7986 if (IS_SYMOP (op
) && IS_FUNC (OP_SYM_TYPE (op
)))
7988 if (IS_SYMOP (op
) && IS_PTR (OP_SYM_TYPE (op
)) && (AOP_TYPE (op
) == AOP_PCODE
) && (AOP (op
)->aopu
.pcop
->type
== PO_IMMEDIATE
))