PeepHoleOpt::Changed PeepHoleOpt::handleInst_SSEXor(Inst* inst)
{
    assert(inst->getMnemonic() == Mnemonic_XORPS || 
           inst->getMnemonic() == Mnemonic_XORPD);
           
    if (inst->getOpndCount() != 2) {
        // Expected only XORPS/PD a, b
        assert(false);
        return Changed_Nothing;
    }
    
    Opnd* dst = inst->getOpnd(0);
    Opnd* src = inst->getOpnd(1);
    
    if (isReg(dst) && isReg(src, dst->getRegName())) {
        /*what: XORPS/XORPD regN, regN => PXOR regN, regN
          why: XORPS/PD used for zero-ing register, but PXOR is faster 
               (2 ticks on PXOR vs 4 ticks for XORPS/XORPD)
        */
        // FIXME: replacing operands on 1 instruction only 
        // will fail liveness verification if their refcount > 1
        //dst = convertToXmmReg64(dst);
        //src = convertToXmmReg64(src);
        //Inst* ii = irManager->newInst(Mnemonic_PXOR, dst, src);
        //replaceInst(inst, ii);
        //return Changed_Inst;
    }
    return Changed_Nothing;
}
示例#2
0
bool Opnd::isMem() {
    
    if (isReg() == false)          return false;
    if (value < S_BASE)            return false;
    if (value >= LOCATION_INVALID) return false;
    return true;
    
    return true;
}
示例#3
0
	bool Operand6502::isDPReg(char *str)
	{
		int reg;

		if (isReg(str, &reg))
			if (reg==16)
				return true;
		return false;
	}
示例#4
0
int readReg(char * reg_name, int32_t* value) {		//Lit dans un registre a travers value
    int i=isReg(reg_name);
    if(i==-1) {								//test -1 et 0 non modifiable
        WARNING_MSG("%s isn't a valid register",reg_name);
        return -1;
    } else {
        *value=reg_mips[i];
        return 0;
    }
}
示例#5
0
int writeReg(char * reg_name, int32_t value) {		// Ecrit value dans un registre
    int i=isReg(reg_name);
    if(i<1) {								//test -1 et 0 non modifiable
        WARNING_MSG("%s isn't a valid register",reg_name);
        return -1;
    } else {
        reg_mips[i]=value;
        return i;
    }
}
示例#6
0
bool OpndUtils::isXmmReg(const Opnd* op, RegName what)
{
    if (!isReg(op)) {
        return false;
    }
    const RegName regName = op->getRegName();
    if (getRegKind(regName) != OpndKind_XMMReg) {
        return false;
    }
    if (what == RegName_Null) {
        return true; 
    }
    return regName == what;
}
示例#7
0
RVNGDirectoryStreamTest::RVNGDirectoryStreamTest()
	: m_dir(TEST_DIR)
	, m_file(TEST_DIR)
	, m_nonexistent(TEST_DIR)
{
	m_file.append("/");
	m_file.append(TEST_FILENAME);
	m_nonexistent.append("/");
	m_nonexistent.append(TEST_NONEXISTENT); // dir
	m_nonexistent.append("/");
	m_nonexistent.append(TEST_NONEXISTENT); // file
	// sanity check
	assert(isDir(m_dir.c_str()));
	assert(isReg(m_file.c_str()));
	assert(!exists(m_nonexistent.c_str()));
}
示例#8
0
void Tmp::dump(PrintStream& out) const
{
    if (!*this) {
        out.print("<none>");
        return;
    }

    if (isReg()) {
        out.print(reg());
        return;
    }

    if (isGP()) {
        out.print("%tmp", gpTmpIndex());
        return;
    }

    out.print("%ftmp", fpTmpIndex());
}
示例#9
0
bool
stm8notUsed (const char *what, lineNode *endPl, lineNode *head)
{
  lineNode *pl;
  if(strcmp(what, "x") == 0)
    return(stm8notUsed("xl", endPl, head) && stm8notUsed("xh", endPl, head));
  if(strcmp(what, "y") == 0)
    return(stm8notUsed("yl", endPl, head) && stm8notUsed("yh", endPl, head));

  if(!isReg(what))
    return FALSE;

  _G.head = head;

  unvisitLines (_G.head);

  pl = endPl->next;
  return (doTermScan (&pl, what));
}
PeepHoleOpt::Changed PeepHoleOpt::handleInst_CMP(Inst* inst) {
    assert(inst->getMnemonic()==Mnemonic_CMP);
    
    Inst::Opnds uses(inst, Inst::OpndRole_Explicit | Inst::OpndRole_Use);
    Opnd* src1 = inst->getOpnd(uses.begin());
    Opnd* src2 = inst->getOpnd(uses.next(uses.begin()));
    assert(src1!=NULL && src2!=NULL);

    if (isImm(src1)) {
        Opnd* tmp = src1; src1 = src2; src2 = tmp;
    }

    if (isImm(src2) && isReg(src1) && (int)src2->getImmValue() == 0) {
            if (Log::isEnabled()) Log::out()<<"I"<<inst->getId()<<" -> CMP with 0"<<std::endl;
            irManager->newInst(Mnemonic_TEST, src1, src1)->insertAfter(inst);
            inst->unlink();
            return Changed_Inst;
    }
    return Changed_Nothing;
}
示例#11
0
bool Opnd::isWritable() {
    if (isReg()      == false) return false;
    if (isConstant() == true)  return false;
    return true;
}
示例#12
0
static bool printAlias(MCInst *MI, SStream *OS)
{
	switch (MCInst_getOpcode(MI)) {
		case Mips_BEQ:
			// beq $zero, $zero, $L2 => b $L2
			// beq $r0, $zero, $L2 => beqz $r0, $L2
			return (isReg(MI, 0, Mips_ZERO) && isReg(MI, 1, Mips_ZERO) &&
					printAlias1("b", MI, 2, OS)) ||
				(isReg(MI, 1, Mips_ZERO) && printAlias2("beqz", MI, 0, 2, OS));
		case Mips_BEQ64:
			// beq $r0, $zero, $L2 => beqz $r0, $L2
			return isReg(MI, 1, Mips_ZERO_64) && printAlias2("beqz", MI, 0, 2, OS);
		case Mips_BNE:
			// bne $r0, $zero, $L2 => bnez $r0, $L2
			return isReg(MI, 1, Mips_ZERO) && printAlias2("bnez", MI, 0, 2, OS);
		case Mips_BNE64:
			// bne $r0, $zero, $L2 => bnez $r0, $L2
			return isReg(MI, 1, Mips_ZERO_64) && printAlias2("bnez", MI, 0, 2, OS);
		case Mips_BGEZAL:
			// bgezal $zero, $L1 => bal $L1
			return isReg(MI, 0, Mips_ZERO) && printAlias1("bal", MI, 1, OS);
		case Mips_BC1T:
			// bc1t $fcc0, $L1 => bc1t $L1
			return isReg(MI, 0, Mips_FCC0) && printAlias1("bc1t", MI, 1, OS);
		case Mips_BC1F:
			// bc1f $fcc0, $L1 => bc1f $L1
			return isReg(MI, 0, Mips_FCC0) && printAlias1("bc1f", MI, 1, OS);
		case Mips_JALR:
			// jalr $ra, $r1 => jalr $r1
			return isReg(MI, 0, Mips_RA) && printAlias1("jalr", MI, 1, OS);
		case Mips_JALR64:
			// jalr $ra, $r1 => jalr $r1
			return isReg(MI, 0, Mips_RA_64) && printAlias1("jalr", MI, 1, OS);
		case Mips_NOR:
		case Mips_NOR_MM:
			// nor $r0, $r1, $zero => not $r0, $r1
			return isReg(MI, 2, Mips_ZERO) && printAlias2("not", MI, 0, 1, OS);
		case Mips_NOR64:
			// nor $r0, $r1, $zero => not $r0, $r1
			return isReg(MI, 2, Mips_ZERO_64) && printAlias2("not", MI, 0, 1, OS);
		case Mips_OR:
			// or $r0, $r1, $zero => move $r0, $r1
			return isReg(MI, 2, Mips_ZERO) && printAlias2("move", MI, 0, 1, OS);
		default: return false;
	}
}
PeepHoleOpt::Changed PeepHoleOpt::handleInst_SSEMov(Inst* inst)
{
    assert(inst->getMnemonic() == Mnemonic_MOVSS || 
           inst->getMnemonic() == Mnemonic_MOVSD);
           
    const bool isDouble = inst->getMnemonic() == Mnemonic_MOVSD;

    if (inst->getOpndCount() != 2) {
        // Expected only MOVSS/SD a, b
        assert(false);
        return Changed_Nothing;
    }
    Opnd* dst = inst->getOpnd(0);
    Opnd* src = inst->getOpnd(1);
    //
    //
    if (isReg(dst) && equals(src, dst)) {
        // what: same register moved around
        // why:  useless thing
        inst->unlink();
        return Changed_Inst;
    }
    
    //
    //
    if (isReg(dst) && isMem(src)) {
        /* what: MOVSS/MOVSD xmmreg, [zero constant from memory] => PXOR xmmreg, xmmreg
           why:  shorter instruction; no memory access => faster
           nb:   only works with 64 XMMs
        */
        bool isZeroConstant = false;
        if (isDouble) {
            isZeroConstant = isFPConst(src, (double)0);
        }
        else {
            isZeroConstant = isFPConst(src, (float)0);
        }
        
        if (isZeroConstant) {
            // PXOR only accepts double registers, convert dst
            dst = convertToXmmReg64(dst);
            Inst* ii = irManager->newInst(Mnemonic_PXOR, dst, dst);
            replaceInst(inst, ii);
            return Changed_Inst;
        }
        //
        // fall through to process more
        // ||
        // vv
        
    }   // ~ movss xmm, 0 => pxor xmm,xmm
    
    if (isReg(dst) && isReg(src)) {
        /*what: MOVSS/MOVSD reg, reg => MOVQ reg, reg
          why: MOVSD has latency=6, MOVSS has latency=4, MOVQ's latency=2
          nb: MOVQ only works with 64 xmms
        */
        dst = convertToXmmReg64(dst);
        src = convertToXmmReg64(src);
        Inst* ii = irManager->newInst(Mnemonic_MOVQ, dst, src);
        replaceInst(inst, ii);
        return Changed_Inst;
    }
    
    // We just handled 'both regs' case above, the only possible variant:
    assert((isReg(dst)&&isMem(src)) || (isReg(src)&&isMem(dst)));
    if (false && isDouble) {
        //FIXME: MOVQ with memory gets encoded badly - need to fix in encoder
        /*
        what: MOVSD => MOVQ
        why:  faster (? actually, I hope so. Need to double check)
        nb:   only for xmm64
        */
        Inst* ii = irManager->newInst(Mnemonic_MOVQ, dst, src);
        replaceInst(inst, ii);
        return Changed_Inst;
    }
    
    return Changed_Nothing;
}
示例#14
0
	const char *Operand::string() const
	{
		static char string[256];

		if(isVoid(type))
		{
			return 0;
		}
		else if(isImm(type))
		{
			if(reference)
			{
				return reference;
			}
			else
			{
				if(value <= 127 && value >= -128)
				{
					snprintf(string, 255, "0x%0.2X", value & 0xFF);
				}
				else if(value <= 32767 && value -32768)
				{
					snprintf(string, 255, "0x%0.4X", value & 0xFFFF);
				}
				else
				{
					snprintf(string, 255, "0x%0.8X", value);
				}
			}
		}
		else if(isReg(type))
		{
			return regName();
		}
		else if(isMem(type))
		{
			switch(type)
			{
			case OPERAND_MEM8:
				snprintf(string, 255, "byte ptr [");
				break;
			case OPERAND_MEM16:
				snprintf(string, 255, "word ptr [");
				break;
			case OPERAND_MEM32:
				snprintf(string, 255, "dword ptr [");
				break;
			case OPERAND_MEM64:
				snprintf(string, 255, "qword ptr [");
				break;
			case OPERAND_MEM128:
				snprintf(string, 255, "xmmword ptr [");
				break;
			case OPERAND_MEM:
			default:
				snprintf(string, 255, "byte ptr [");
			}

			if(baseReg != Encoding::REG_UNKNOWN)
			{
				snprintf(string, 255, "%s%s", string, regName());

				if(indexReg != Encoding::REG_UNKNOWN)
				{
					snprintf(string, 255, "%s+", string);
				}
			}

			if(indexReg != Encoding::REG_UNKNOWN)
			{
				snprintf(string, 255, "%s%s", string, indexName());
			}

			switch(scale)
			{
			case 0:
			case 1:
				break;
			case 2:
				snprintf(string, 255, "%s*2", string);
				break;
			case 4:
				snprintf(string, 255, "%s*4", string);
				break;
			case 8:
				snprintf(string, 255, "%s*8", string);
				break;
			default:
				throw INTERNAL_ERROR;
			}

			if(displacement)
			{
				if(baseReg != Encoding::REG_UNKNOWN ||
				   indexReg != Encoding::REG_UNKNOWN)
				{
					snprintf(string, 255, "%s+", string);
				}

				if(reference)
				{
					snprintf(string, 255, "%s%s", string, reference);
				}
				else
				{
					if(displacement <= 32767 && displacement >= -32768)
					{
						snprintf(string, 255, "%s%d", string, displacement);
					}
					else
					{					
						snprintf(string, 255, "%s0x%0.8X", string, displacement);
					}
				}
			}

			snprintf(string, 255, "%s]", string);
		}
		else
		{
			throw INTERNAL_ERROR;
		}

		return strlwr(string);
	}
示例#15
0
	bool Operand::isReg(const Operand &operand)
	{
		return isReg(operand.type);
	}
示例#16
0
int
stm8instructionSize(const lineNode *pl)
{
  char *operand;
  char *op1start;
  char *op2start;
  int i = 0;
  operand = nextToken(pl->line);
  op1start = nextToken(NULL);
  op2start = nextToken(NULL);
  //fprintf(stderr, "op1start=%s op2start=%s\n", op1start, op2start);
  while(op2start && isspace(*op2start)) op2start++;
  //printf("operand=%s op1start=%s op2start=%s\n", operand, op1start, op2start);

  /* arity=1 */
  if(EQUALS(operand, "clr")
                || EQUALS(operand, "dec")
                || EQUALS(operand, "inc")
                || EQUALS(operand, "push")
                || EQUALS(operand, "swap")
                || EQUALS(operand, "jp")
                || EQUALS(operand, "cpl")
                || EQUALS(operand, "tnz"))
  {
    if(!op1start)
      return(3);
    if(op1start[0] == 'a' || op1start[1] == 'x')
      return(1);
    if(op1start[1] == 'y')
      return(2);
    if(op1start[0] == '(')
      op1start++;
    if(strstr(op1start, ",y)"))
      i++; // costs extra byte for operating with y
    if(isLabel(op1start))
      return(3);
    if(readint(op1start) <= 0xFF)
      return(2+i);
    /* op1 > 0xFF */
    if(EQUALS(operand, "jp") && !strchr(op1start, 'y'))
      return(3);
    return(4);
  }
  if(EQUALS(operand, "exg"))
  {
    if(isReg(op2start))
      return(1);
    else
      return(3);
  }
  if(EQUALS(operand, "addw") || EQUALS(operand, "subw"))
  {
    if(isImmediate(op2start) && op1start[0] == 'y')
      return(4);
    if(isImmediate(op2start))
      return(3);
    if(isSpIndexed(op2start))
      return(3);
    if(isLongoff(op2start, "x"))
      return(4);
  }
  if(EQUALS(operand, "cplw"))
  {
    if(op1start[0] == 'y')
      return(2);
    else
      return(1);
  }
  if(EQUALS(operand, "ldf"))
  {
    if(isRelativeAddr(op1start, "y") || isRelativeAddr(op2start, "y"))
      return(5);
    else
      return(4);
  }
  /* Operations that costs 2 or 3 bytes for immediate */
  if(ISINST(operand, "ld")
                || EQUALS(operand, "cp")
                || EQUALS(operand, "cpw")
                || ISINST(operand, "adc")
                || EQUALS(operand, "add")
                || ISINST(operand, "and")
                || ISINST(operand, "bcp")
                || ISINST(operand, "call")
                || ISINST(operand, "callr")
                || ISINST(operand, "jr")
                || ISINST(operand, "or")
                || ISINST(operand, "sbc")
                || EQUALS(operand, "sub")
                || ISINST(operand, "xor"))
  {
    char suffix;

    if(!op1start || !op2start)
      return(4);
    suffix = operand[strlen(operand)-1];
    if(suffix == 'w' && isImmediate(op2start))
      i++; // costs extra byte
    if(isSpIndexed(op1start) || isSpIndexed(op2start))
      return(2);
    if(!strcmp(op1start, "(x)") || !strcmp(op2start, "(x)"))
      return(1);
    if(!strcmp(op1start, "(y)") || !strcmp(op2start, "(y)"))
      return(2);
    if(isLabel(op1start) || isLabel(op2start))
      return(3+i);
    if(isShortoff(op1start, "x") || isShortoff(op2start, "x"))
      return(2);
    if(isShortoff(op1start, "y") || isShortoff(op2start, "y"))
      return(3);
    if(isLongoff(op1start, "x") || isLongoff(op2start, "x"))
      return(3);
    if(isRelativeAddr(op1start, "y"))
      return(4);
    if(strchr(op1start, 'y') || (strchr(op2start, 'y') && !EQUALS(operand, "ldw")))
      i++; // costs extra byte for operating with y
    if(isReg(op1start) && isReg(op2start))
      return(1+i);
    if(op2start[0] == '#')
      return(2+i); // ld reg, #immd
    if(readint(op2start) <= 0xFF)
      return(2+i);
    return(3+i);
  }

  /* mov costs 3, 4 or 5 bytes depending on it's addressing mode */
  if(EQUALS(operand, "mov")) {
    if(op2start && op2start[0] == '#')
      return(4);
    if(op2start && isLabel(op2start))
      return(5);
    if(op2start && readint(op2start) <= 0xFF)
      return(3);
    if(op2start && readint(op2start) > 0xFF)
      return(5);
  }

  /* Operations that always costs 1 byte */
  if(EQUALS(operand, "ccf")
                || EQUALS(operand, "divw")
                || EQUALS(operand, "exgw")
                || EQUALS(operand, "iret")
                || EQUALS(operand, "nop")
                || EQUALS(operand, "rcf")
                || EQUALS(operand, "ret")
                || EQUALS(operand, "retf")
                || EQUALS(operand, "rvf")
                || EQUALS(operand, "scf"))
  {
    return(1);
  }
  /* Operations that costs 2 or 1 bytes depending on 
     is the Y or X register used */
  if(EQUALS(operand, "clrw")
                || EQUALS(operand, "decw")
                || EQUALS(operand, "div")
                || EQUALS(operand, "incw")
                || EQUALS(operand, "mul")
                || EQUALS(operand, "negw")
                || EQUALS(operand, "popw")
                || EQUALS(operand, "pushw")
                || EQUALS(operand, "rlcw")
                || EQUALS(operand, "rlwa")
                || EQUALS(operand, "rrcw")
                || EQUALS(operand, "rrwa")
                || EQUALS(operand, "sllw")
                || EQUALS(operand, "slaw")
                || EQUALS(operand, "sraw")
                || EQUALS(operand, "srlw")
                || EQUALS(operand, "swapw")
                || EQUALS(operand, "tnzw"))
  {
    if((op1start && !strcmp(op1start, "y")) || (op2start && !strcmp(op2start, "y")))
      return(2);
    else
      return(1);
  }
  return(4);
}
示例#17
0
int isReg(char* reg_name) {					//Test si une chaine de caractere est un registre valide
    if(reg_name[0]=='$') {
        return isReg(reg_name+1); 					//Prise en charge du $ pour les reg
    }
    char * string;

    int index=-1;
    index = strtol(reg_name,&string,10);
    //printf("reg_name= %s string =%s, index=%d\n",reg_name,string,index );

    if (isdigit(reg_name[0]) && index<NBREG && index > -1) {
        return index;
    }
    else if (!isdigit(reg_name[0])) {
        if (!strcmp(string,"zero")) {
            index=0;
        }
        else if (!strcmp(string,"at")) {
            index=1;
        }
        else if (!strcmp(string,"v0")) {
            index=2;
        }
        else if (!strcmp(string,"v1")) {
            index=3;
        }
        else if (!strcmp(string,"a0")) {
            index=4;
        }
        else if (!strcmp(string,"a1")) {
            index=5;
        }
        else if (!strcmp(string,"a2")) {
            index=6;
        }
        else if (!strcmp(string,"a3")) {
            index=7;
        }
        else if (!strcmp(string,"t0")) {
            index=8;
        }
        else if (!strcmp(string,"t1")) {
            index=9;
        }
        else if (!strcmp(string,"t2")) {
            index=10;
        }
        else if (!strcmp(string,"t3")) {
            index=11;
        }
        else if (!strcmp(string,"t4")) {
            index=12;
        }
        else if (!strcmp(string,"t5")) {
            index=13;
        }
        else if (!strcmp(string,"t6")) {
            index=14;
        }
        else if (!strcmp(string,"t7")) {
            index=15;
        }
        else if (!strcmp(string,"s0")) {
            index=16;
        }
        else if (!strcmp(string,"s1")) {
            index=17;
        }
        else if (!strcmp(string,"s2")) {
            index=18;
        }
        else if (!strcmp(string,"s3")) {
            index=19;
        }
        else if (!strcmp(string,"s4")) {
            index=20;
        }
        else if (!strcmp(string,"s5")) {
            index=21;
        }
        else if (!strcmp(string,"s6")) {
            index=22;
        }
        else if (!strcmp(string,"s7")) {
            index=23;
        }
        else if (!strcmp(string,"t8")) {
            index=24;
        }
        else if (!strcmp(string,"t9")) {
            index=25;
        }
        else if (!strcmp(string,"k0")) {
            index=26;
        }
        else if (!strcmp(string,"k1")) {
            index=27;
        }
        else if (!strcmp(string,"gp")) {
            index=28;
        }
        else if (!strcmp(string,"sp")) {
            index=29;
        }
        else if (!strcmp(string,"fp")) {
            index=30;
        }
        else if (!strcmp(string,"ra")) {
            index=31;
        }
        else if (!strcmp(string,"HI")) {
            index=32;
        }
        else if (!strcmp(string,"LO")) {
            index=33;
        }
        else if (!strcmp(string,"PC")) {
            index=34;
        }

        else index=-1;
        return index;
    }
    index=-1;
    return index;
}
PeepHoleOpt::Changed PeepHoleOpt::handleInst_SETcc(Inst* inst)
{
    if (((BasicBlock*)inst->getNode())->getLayoutSucc() == NULL)
    {
        Mnemonic mn = inst->getMnemonic();
        
        Inst* prev = inst->getPrevInst();
        Inst *next = inst->getNextInst();

        Node *currNode = inst->getNode();
        bool methodMarkerOccur = false;
        MethodMarkerPseudoInst* methodMarker = NULL;
        // ignoring instructions that have no effect and saving method markers to correct them during optimizations
        while (next == NULL || next->getKind() == Inst::Kind_MethodEndPseudoInst || next->getMnemonic() == Mnemonic_JMP)
        {
            if (next == NULL)
            {
                currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode();
                if (currNode->getKind() == Node::Kind_Exit)
                    return Changed_Nothing;
                next = (Inst*) currNode->getFirstInst();
            }
            else
            {
                if (next->getKind() == Inst::Kind_MethodEndPseudoInst)
                {
                    //max 1 saved method marker
                    if (methodMarkerOccur)
                    {
                        return Changed_Nothing;
                    }
                    methodMarker = (MethodMarkerPseudoInst*)next;
                    methodMarkerOccur = true;
                }
                next = next->getNextInst();
            }
        }

        Inst *next2 = next->getNextInst();

        bool step1 = true;
        currNode = inst->getNode();
        while (currNode != next->getNode())
        {
            currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode();
            if (currNode->getInDegree()!=1)
            {
                step1 = false;
                break;
            }
        }

        // step1:
        // ------------------------------------------
        // MOV opnd, 0                  MOV opnd2, 0
        // SETcc opnd           ->      SETcc opnd2
        // MOV opnd2, opnd
        // ------------------------------------------
        // nb: applicable if opnd will not be used further
        if (step1 && prev!= NULL && prev->getMnemonic() == Mnemonic_MOV &&
            next!= NULL && next->getMnemonic() == Mnemonic_MOV)
        {
            Opnd *prevopnd1, *prevopnd2, *nextopnd1, *nextopnd2, *setopnd;
            if (prev->getKind() == Inst::Kind_CopyPseudoInst)
            {
                prevopnd1 = prev->getOpnd(0);
                prevopnd2 = prev->getOpnd(1);
            }
            else
            {
                Inst::Opnds prevuses(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
                Inst::Opnds prevdefs(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
                prevopnd1 = prev->getOpnd(prevdefs.begin());
                prevopnd2 = prev->getOpnd(prevuses.begin());
            }
            if (next->getKind() == Inst::Kind_CopyPseudoInst)
            {
                nextopnd1 = next->getOpnd(0);
                nextopnd2 = next->getOpnd(1);
            }
            else
            {
                Inst::Opnds nextuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
                Inst::Opnds nextdefs(next, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
                nextopnd1 = next->getOpnd(nextdefs.begin());
                nextopnd2 = next->getOpnd(nextuses.begin());
            }
            Inst::Opnds setdefs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
            setopnd = inst->getOpnd(setdefs.begin());

            if (isReg(nextopnd1) &&
                prevopnd1->getId() == setopnd->getId() &&
                setopnd->getId() == nextopnd2->getId() &&
                isImm(prevopnd2) && prevopnd2->getImmValue() == 0
                )
            {
                BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount());
                irManager->updateLivenessInfo();
                irManager->getLiveAtExit(next->getNode(), ls);
                for (Inst* i = (Inst*)next->getNode()->getLastInst(); i!=next; i = i->getPrevInst()) {
                    irManager->updateLiveness(i, ls);
                }
                bool opndNotUsed = !ls.getBit(setopnd->getId());
                if (opndNotUsed)
                {
                    if (nextopnd1->getRegName() != RegName_Null &&
                        Constraint::getAliasRegName(nextopnd1->getRegName(), OpndSize_8) == RegName_Null)
                    {
                        nextopnd1->assignRegName(setopnd->getRegName());
                    }
                    irManager->newInst(Mnemonic_MOV, nextopnd1, prevopnd2)->insertBefore(inst);
                    irManager->newInst(mn, nextopnd1)->insertBefore(inst);
                    prev->unlink();
                    inst->unlink();
                    next->unlink();
                    return Changed_Node;
                }
            }
        }

        // step2:
        // --------------------------------------------------------------
        // MOV opnd, 0                  Jcc smwh                Jcc smwh
        // SETcc opnd           ->      BB1:            v       BB1:
        // CMP opnd, 0                  ...
        // Jcc smwh                     CMP opnd, 0
        // BB1:                         Jcc smwh
        // --------------------------------------------------------------
        // nb: applicable if opnd will not be used further
        // nb: conditions of new jumps are calculated from conditions of old jump and set instructions
	    if (prev!= NULL && prev->getMnemonic() == Mnemonic_MOV &&
            next!= NULL && (next->getMnemonic() == Mnemonic_CMP || next->getMnemonic() == Mnemonic_TEST) &&
            next2!= NULL && (next2->getMnemonic() == Mnemonic_JG || next2->getMnemonic() == Mnemonic_JE || next2->getMnemonic() == Mnemonic_JNE) )
	    {
            Opnd* movopnd1;
            Opnd* movopnd2;
            if (prev->getKind() == Inst::Kind_CopyPseudoInst)
            {
                movopnd1 = prev->getOpnd(0);
                movopnd2 = prev->getOpnd(1);
            }
            else
            {
                Inst::Opnds movuses(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
                Inst::Opnds movdefs(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
                movopnd1 = prev->getOpnd(movdefs.begin());
                movopnd2 = prev->getOpnd(movuses.begin());
            }
            Inst::Opnds cmpuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
            Opnd* cmpopnd1 = next->getOpnd(cmpuses.begin());
            Opnd* cmpopnd2 = next->getOpnd(cmpuses.next(cmpuses.begin()));

            if (
                isImm(movopnd2) && movopnd2->getImmValue() == 0 &&
                movopnd1->getId() == cmpopnd1->getId() &&
                //case CMP:
                (next->getMnemonic() != Mnemonic_CMP || (isImm(cmpopnd2) && cmpopnd2->getImmValue() == 0)) &&
                //case TEST:
                (next->getMnemonic() != Mnemonic_TEST || cmpopnd1->getId() == cmpopnd2->getId())
                )
            {
                BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount());
                irManager->updateLivenessInfo();
                irManager->getLiveAtExit(next2->getNode(), ls);
                bool opndNotUsed = !ls.getBit(movopnd1->getId());
                if (opndNotUsed)
                {
                    BranchInst* br = (BranchInst*) next2;

                    Mnemonic newjumpmn = Mnemonic_JZ;
                    if (next2->getMnemonic() == Mnemonic_JE)
                    {
                        switch (mn)
                        {
                        case Mnemonic_SETG:
                            newjumpmn = Mnemonic_JLE; break;
                        case Mnemonic_SETE:
                            newjumpmn = Mnemonic_JNE; break;
                        case Mnemonic_SETL:
                            newjumpmn = Mnemonic_JGE; break;
                        case Mnemonic_SETNE:
                            newjumpmn = Mnemonic_JE; break;
                        default:
                            assert(0); break;
                        }
                    }
                    else
                    {
                        switch (mn)
                        {
                        case Mnemonic_SETG:
                            newjumpmn = Mnemonic_JG; break;
                        case Mnemonic_SETE:
                            newjumpmn = Mnemonic_JE; break;
                        case Mnemonic_SETL:
                            newjumpmn = Mnemonic_JL; break;
                        case Mnemonic_SETNE:
                            newjumpmn = Mnemonic_JNE; break;
                        default:
                            assert(0); break;
                        }
                    }

                    if (inst->getNode()->getId() != next->getNode()->getId())
                    {
                        ControlFlowGraph* cfg = irManager->getFlowGraph();
                        cfg->removeEdge(inst->getNode()->getOutEdge(Edge::Kind_Unconditional));

                        double trueEdgeProb = next2->getNode()->getOutEdge(Edge::Kind_True)->getEdgeProb();
                        double falseEdgeProb = next2->getNode()->getOutEdge(Edge::Kind_False)->getEdgeProb();
                        cfg->addEdge(inst->getNode(), br->getTrueTarget(), trueEdgeProb);
                        cfg->addEdge(inst->getNode(), br->getFalseTarget(), falseEdgeProb);
                        irManager->newBranchInst(newjumpmn, br->getTrueTarget(), br->getFalseTarget())->insertAfter(inst);
                        if (methodMarkerOccur)
                        {
                            inst->getNode()->appendInst(irManager->newMethodEndPseudoInst(methodMarker->getMethodDesc()));
                        }
		                prev->unlink();
		                inst->unlink();
                        cfg->purgeUnreachableNodes();
                    }
                    else
                    {
                        irManager->newBranchInst(newjumpmn, br->getTrueTarget(), br->getFalseTarget())->insertAfter(next2);
                        prev->unlink();
		                inst->unlink();
		                next->unlink();
                        next2->unlink();
                    }
		            return Changed_Node;
                }// endif opndNotUsed
            }
        }
    }
	return Changed_Nothing;
}
示例#19
0
	bool Operand6502::isNdxReg(char *str, int *reg)
	{
		return (isReg(str, reg));
	}