#include "SDCCpeeph.h"
#include "ralloc.h"
#include "pcode.h"
+#include "device.h"
#include "gen.h"
#include "genutils.h"
* result[AOP_CRY,AOP_REG] = ! left[AOP_CRY, AOP_REG]
*/
- DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
-
- /* assign asmOps to operand & result */
- pic16_aopOp (IC_LEFT(ic),ic,FALSE);
- pic16_aopOp (IC_RESULT(ic),ic,TRUE);
- DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
-
- /* if in bit space then a special case */
- if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
- if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
- pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
- pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
- } else {
- pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
- pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
- pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
- }
- goto release;
- }
-
- size = AOP_SIZE(IC_LEFT(ic));
+ FENTRY;
+
+ /* assign asmOps to operand & result */
+ pic16_aopOp (IC_LEFT(ic),ic,FALSE);
+ pic16_aopOp (IC_RESULT(ic),ic,TRUE);
+ DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
+
+ /* if in bit space then a special case */
+ if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
+ if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
+ pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
+ pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+ } else {
+ pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+ pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
+ pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+ }
+ goto release;
+ }
+
+ size = AOP_SIZE(IC_LEFT(ic));
#if 0
- if(size == 1) {
- pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
- pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
- pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
- goto release;
- }
+ if(size == 1) {
+ pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
+ pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
+ pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+ goto release;
+ }
#endif
- pic16_toBoolean( IC_LEFT(ic) );
- emitSETC;
- pic16_emitpcode(POC_TSTFSZ, pic16_popCopyReg( &pic16_pc_wreg ));
- emitCLRC;
- pic16_outBitC( IC_RESULT(ic) );
+ pic16_toBoolean( IC_LEFT(ic) );
+ emitSETC;
+ pic16_emitpcode(POC_TSTFSZ, pic16_popCopyReg( &pic16_pc_wreg ));
+ emitCLRC;
+ pic16_outBitC( IC_RESULT(ic) );
release:
- /* release the aops */
- pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
- pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+ /* release the aops */
+ pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
+ pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
}
#endif /* defined(GEN_Not) */
/*
* result[CRY,REG] = ~left[CRY,REG]
*/
-
-
- DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
- /* assign asmOps to operand & result */
- pic16_aopOp (IC_LEFT(ic),ic,FALSE);
- pic16_aopOp (IC_RESULT(ic),ic,TRUE);
- DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
-
- /* if both are in bit space then
- a special case */
- if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
- AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
-
- /* FIXME */
- pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
- pic16_emitcode("cpl","c");
- pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
- goto release;
- }
-
- size = AOP_SIZE(IC_RESULT(ic));
- while (size--) {
-
- if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
- pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
- } else {
- pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
- }
- offset++;
- }
+ FENTRY;
+
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+ /* assign asmOps to operand & result */
+ pic16_aopOp (IC_LEFT(ic),ic,FALSE);
+ pic16_aopOp (IC_RESULT(ic),ic,TRUE);
+ DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
+
+ /* if both are in bit space then
+ * a special case */
+ if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
+ && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
+
+ /* FIXME */
+ pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
+ pic16_emitcode("cpl","c");
+ pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
+ goto release;
+ }
+
+ size = AOP_SIZE(IC_RESULT(ic));
+ while (size--) {
+ if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+ pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
+ } else {
+ pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+ }
+ offset++;
+ }
release:
/* release the aops */
}
-//#define debugf(frm, rest) _debugf(__FILE__, __LINE__, frm, rest)
-
void _debugf(char *f, int l, char *frm, ...)
{
va_list ap;
gpsimio2_lit('\n');
}
+
+
+
+/* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
+static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
+ operand *result, int offset, int invert_op)
+{
+ /* add code here */
+
+ /* check condition, > or < ?? */
+ if(rIfx->condition != 0)invert_op ^= 1;
+
+ if(ifx && IC_FALSE(ifx))invert_op ^= 1;
+
+ if(!ifx)invert_op ^= 1;
+
+ DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
+ __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
+
+ /* do selection */
+ if(!invert_op)return POC_CPFSGT;
+ else return POC_CPFSLT;
+}
+
+/* return 1 if function handles compare, 0 otherwise */
+/* this functions handles special cases like:
+ * reg vs. zero
+ * reg vs. one
+ */
+int pic16_genCmp_special(operand *left, operand *right, operand *result,
+ iCode *ifx, resolvedIfx *rIfx, int sign)
+{
+ int size;
+ int offs=0;
+ symbol *tmplbl;
+ unsigned long lit;
+ int op, cmp_op=0, cond_pre;
+
+ FENTRY;
+
+ if(!(pic16_options.opt_flags & OF_OPTIMIZE_CMP))return 0;
+
+ size = max(AOP_SIZE(left), AOP_SIZE(right));
+
+ cond_pre = rIfx->condition; // must restore old value on return with 0!!!
+
+ if(!isAOP_REGlike(left)) {
+ operand *dummy;
+
+ dummy = left;
+ left = right;
+ right = dummy;
+
+ /* invert comparing operand */
+// cmp_op ^= 1;
+ rIfx->condition ^= 1;
+ }
+
+
+ if(isAOP_REGlike(left) && isAOP_LIT(right)) {
+ /* comparing register vs. literal */
+ lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
+
+
+ if(size == 1) {
+ op = selectCompareOp(rIfx, ifx, result, offs, cmp_op);
+
+ DEBUGpic16_emitcode("%%", "comparing operand %s, condition: %d", (op==POC_CPFSLT?"POC_CPFSLT":"POC_CPFSGT"), rIfx->condition);
+
+ if(!sign) {
+ /* unsigned compare */
+ switch( lit ) {
+ case 0:
+ if(ifx && IC_FALSE(ifx)) {
+ tmplbl = newiTempLabel( NULL );
+ pic16_emitpcode(POC_TSTFSZ, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_BRA, pic16_popGetLabel(tmplbl->key));
+ pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx->lbl->key));
+ pic16_emitpLabel(tmplbl->key);
+
+ ifx->generated = 1;
+ return 1;
+ }
+ break;
+ } /* switch */
+
+ } /* if(!sign) */
+
+ } /* if(size==1) */
+
+ } /* */
+
+ rIfx->condition = cond_pre;
+ return 0;
+}