import com.android.dx.util.Hex;
import com.android.dx.util.TwoColumnOutput;
+import java.util.BitSet;
+
/**
* Base class for Dalvik instructions.
*/
/**
* Gets the minimum distinct registers required for this instruction.
+ * Uses the given BitSet to determine which registers require
+ * replacement, and ignores registers that are already compatible.
* This assumes that the result (if any) can share registers with the
* sources (if any), that each source register is unique, and that
* (to be explicit here) category-2 values take up two consecutive
* registers.
*
+ * @param compatRegs {@code non-null;} set of compatible registers
* @return {@code >= 0;} the minimum distinct register requirement
*/
- public final int getMinimumRegisterRequirement() {
+ public final int getMinimumRegisterRequirement(BitSet compatRegs) {
boolean hasResult = hasResult();
int regSz = registers.size();
- int resultRequirement = hasResult ? registers.get(0).getCategory() : 0;
+ int resultRequirement = 0;
int sourceRequirement = 0;
+ if (hasResult && !compatRegs.get(0)) {
+ resultRequirement = registers.get(0).getCategory();
+ }
+
for (int i = hasResult ? 1 : 0; i < regSz; i++) {
- sourceRequirement += registers.get(i).getCategory();
+ if (!compatRegs.get(i)) {
+ sourceRequirement += registers.get(i).getCategory();
+ }
}
return Math.max(sourceRequirement, resultRequirement);
}
/**
- * Gets the instruction prefix required, if any, to use in a high
- * register transformed version of this instance.
+ * Gets the instruction that is equivalent to this one, except that
+ * it uses sequential registers starting at {@code 0} (storing
+ * the result, if any, in register {@code 0} as well).
*
- * @see #hrVersion
+ * @return {@code non-null;} the replacement
+ */
+ public DalvInsn getLowRegVersion() {
+ RegisterSpecList regs =
+ registers.withExpandedRegisters(0, hasResult(), null);
+ return withRegisters(regs);
+ }
+
+ /**
+ * Gets the instruction prefix required, if any, to use in an expanded
+ * version of this instance. Will not generate moves for registers
+ * marked compatible to the format by the given BitSet.
+ *
+ * @see #expandedVersion
*
+ * @param compatRegs {@code non-null;} set of compatible registers
* @return {@code null-ok;} the prefix, if any
*/
- public DalvInsn hrPrefix() {
+ public DalvInsn expandedPrefix(BitSet compatRegs) {
RegisterSpecList regs = registers;
- int sz = regs.size();
+ boolean firstBit = compatRegs.get(0);
- if (hasResult()) {
- if (sz == 1) {
- return null;
- }
- regs = regs.withoutFirst();
- } else if (sz == 0) {
- return null;
- }
+ if (hasResult()) compatRegs.set(0);
+
+ regs = regs.subset(compatRegs);
+
+ if (hasResult()) compatRegs.set(0, firstBit);
+
+ if (regs.size() == 0) return null;
return new HighRegisterPrefix(position, regs);
}
/**
- * Gets the instruction suffix required, if any, to use in a high
- * register transformed version of this instance.
+ * Gets the instruction suffix required, if any, to use in an expanded
+ * version of this instance. Will not generate a move for a register
+ * marked compatible to the format by the given BitSet.
*
- * @see #hrVersion
+ * @see #expandedVersion
*
+ * @param compatRegs {@code non-null;} set of compatible registers
* @return {@code null-ok;} the suffix, if any
*/
- public DalvInsn hrSuffix() {
- if (hasResult()) {
+ public DalvInsn expandedSuffix(BitSet compatRegs) {
+ if (hasResult() && !compatRegs.get(0)) {
RegisterSpec r = registers.get(0);
return makeMove(position, r, r.withReg(0));
} else {
/**
* Gets the instruction that is equivalent to this one, except that
- * uses sequential registers starting at {@code 0} (storing
- * the result, if any, in register {@code 0} as well). The
- * sequence of instructions from {@link #hrPrefix} and {@link
- * #hrSuffix} (if non-null) surrounding the result of a call to
- * this method are the high register transformation of this
- * instance, and it is guaranteed that the number of low registers
- * used will be the number returned by {@link
- * #getMinimumRegisterRequirement}.
+ * it replaces incompatible registers with sequential registers
+ * starting at {@code 0} (storing the result, if any, in register
+ * {@code 0} as well). The sequence of instructions from
+ * {@link #expandedPrefix} and {@link #expandedSuffix} (if non-null)
+ * surrounding the result of a call to this method are the expanded
+ * transformation of this instance, and it is guaranteed that the
+ * number of low registers used will be the number returned by
+ * {@link #getMinimumRegisterRequirement}.
*
+ * @param compatRegs {@code non-null;} set of compatible registers
* @return {@code non-null;} the replacement
*/
- public DalvInsn hrVersion() {
+ public DalvInsn expandedVersion(BitSet compatRegs) {
RegisterSpecList regs =
- registers.withSequentialRegisters(0, hasResult());
+ registers.withExpandedRegisters(0, hasResult(), compatRegs);
return withRegisters(regs);
}
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.Hex;
+import java.util.BitSet;
+
/**
* Base class for all instruction format handlers. Instruction format
* handlers know how to translate {@link DalvInsn} instances into
public abstract boolean isCompatible(DalvInsn insn);
/**
+ * Returns which of a given instruction's registers will fit in
+ * this instance's format.
+ *
+ * <p>The default implementation of this method always returns
+ * an empty BitSet. Subclasses must override this method if they
+ * have registers.</p>
+ *
+ * @param insn {@code non-null;} the instruction to check
+ * @return {@code non-null;} a BitSet flagging registers in the
+ * register list that are compatible to this format
+ */
+ public BitSet compatibleRegs(DalvInsn insn) {
+ return new BitSet();
+ }
+
+ /**
* Returns whether or not the given instruction's branch offset will
* fit in this instance's format. This always returns {@code false}
* for formats that don't include a branch offset.
import com.android.dx.rop.type.Type;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.HashSet;
/**
Dop originalOpcode = opcodes[i];
Dop newOpcode = findOpcodeForInsn(insn, originalOpcode);
- if (originalOpcode == newOpcode) {
- continue;
- }
-
if (newOpcode == null) {
/*
- * The instruction will need to be expanded, so reserve
- * registers for it.
+ * The instruction will need to be expanded, so find the
+ * expanded opcode and reserve registers for it.
*/
- int reserve = insn.getMinimumRegisterRequirement();
+ Dop expandedOp = findExpandedOpcodeForInsn(insn);
+ BitSet compatRegs = expandedOp.getFormat().compatibleRegs(insn);
+ int reserve = insn.getMinimumRegisterRequirement(compatRegs);
if (reserve > newReservedCount) {
newReservedCount = reserve;
}
+ } else if (originalOpcode == newOpcode) {
+ continue;
}
opcodes[i] = newOpcode;
}
/**
+ * Finds the proper opcode for the given instruction, ignoring
+ * register constraints.
+ *
+ * @param insn {@code non-null;} the instruction in question
+ * @return {@code non-null;} the opcode that fits
+ */
+ private Dop findExpandedOpcodeForInsn(DalvInsn insn) {
+ return findOpcodeForInsn(insn.getLowRegVersion(), insn.getOpcode());
+ }
+
+ /**
* Helper for {@link #finishProcessingAndGetList}, which goes
* through each instruction in the output, making sure its opcode
* can accomodate its arguments. In cases where the opcode is
suffix = null;
} else {
// Expansion is required.
- prefix = insn.hrPrefix();
- suffix = insn.hrSuffix();
-
- /*
- * Get the initial guess as to the hr version, but then
- * let findOpcodeForInsn() pick a better format, if any.
- */
- insn = insn.hrVersion();
- originalOpcode = insn.getOpcode();
- currentOpcode = findOpcodeForInsn(insn, originalOpcode);
+ currentOpcode = findExpandedOpcodeForInsn(insn);
+ BitSet compatRegs =
+ currentOpcode.getFormat().compatibleRegs(insn);
+ prefix = insn.expandedPrefix(compatRegs);
+ suffix = insn.expandedSuffix(compatRegs);
+
+ // Expand necessary registers to fit the new format
+ insn = insn.expandedVersion(compatRegs);
}
if (prefix != null) {
* subsequent block in the case of synchronized methods.
*/
method.getBlocks().forEachInsn(new Insn.BaseVisitor() {
+ @Override
public void visitPlainCstInsn(PlainCstInsn insn) {
if (insn.getOpcode().getOpcode()== RegOps.MOVE_PARAM) {
int param =
import com.android.dx.rop.cst.CstLiteralBits;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 11n}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(1);
+
+ bits.set(0, unsignedFitsInNibble(regs.get(0).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
int value =
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 11x}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(1);
+
+ bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
write(out, opcodeUnit(insn, regs.get(0).getReg()));
package com.android.dx.dex.code.form;
import com.android.dx.dex.code.DalvInsn;
-import com.android.dx.dex.code.HighRegisterPrefix;
import com.android.dx.dex.code.InsnFormat;
import com.android.dx.dex.code.SimpleInsn;
import com.android.dx.rop.code.RegisterSpec;
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 12x}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(2);
+
+ bits.set(0, unsignedFitsInNibble(regs.get(0).getReg()));
+ bits.set(1, unsignedFitsInNibble(regs.get(1).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
int sz = regs.size();
import com.android.dx.rop.cst.CstType;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 21c}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ int sz = regs.size();
+ BitSet bits = new BitSet(sz);
+ boolean compat = unsignedFitsInByte(regs.get(0).getReg());
+
+ if (sz == 1) {
+ bits.set(0, compat);
+ } else {
+ if (regs.get(0).getReg() == regs.get(1).getReg()) {
+ bits.set(0, compat);
+ bits.set(1, compat);
+ }
+ }
+
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
int cpi = ((CstInsn) insn).getIndex();
import com.android.dx.rop.cst.CstLiteralBits;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 21h}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(1);
+
+ bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
CstLiteralBits cb = (CstLiteralBits) ((CstInsn) insn).getConstant();
import com.android.dx.rop.cst.CstLiteralBits;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 21s}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(1);
+
+ bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
int value =
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 21t}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(1);
+
+ bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public boolean branchFits(TargetInsn insn) {
int offset = insn.getTargetOffset();
import com.android.dx.rop.cst.CstLiteralBits;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 22b}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(2);
+
+ bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+ bits.set(1, unsignedFitsInByte(regs.get(1).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
int value =
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 22c}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(2);
+
+ bits.set(0, unsignedFitsInNibble(regs.get(0).getReg()));
+ bits.set(1, unsignedFitsInNibble(regs.get(1).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
int cpi = ((CstInsn) insn).getIndex();
import com.android.dx.rop.cst.CstLiteralBits;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 22s}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(2);
+
+ bits.set(0, unsignedFitsInNibble(regs.get(0).getReg()));
+ bits.set(1, unsignedFitsInNibble(regs.get(1).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
int value =
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 22t}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(2);
+
+ bits.set(0, unsignedFitsInNibble(regs.get(0).getReg()));
+ bits.set(1, unsignedFitsInNibble(regs.get(1).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public boolean branchFits(TargetInsn insn) {
int offset = insn.getTargetOffset();
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 22x}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(2);
+
+ bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+ bits.set(1, unsignedFitsInShort(regs.get(1).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
write(out,
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 23x}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(3);
+
+ bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+ bits.set(1, unsignedFitsInByte(regs.get(1).getReg()));
+ bits.set(2, unsignedFitsInByte(regs.get(2).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
write(out,
import com.android.dx.rop.cst.CstType;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 31c}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ int sz = regs.size();
+ BitSet bits = new BitSet(sz);
+ boolean compat = unsignedFitsInByte(regs.get(0).getReg());
+
+ if (sz == 1) {
+ bits.set(0, compat);
+ } else {
+ if (regs.get(0).getReg() == regs.get(1).getReg()) {
+ bits.set(0, compat);
+ bits.set(1, compat);
+ }
+ }
+
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
int cpi = ((CstInsn) insn).getIndex();
import com.android.dx.rop.cst.CstLiteralBits;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 31i}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(1);
+
+ bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
int value =
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 31t}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(1);
+
+ bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public boolean branchFits(TargetInsn insn) {
return true;
}
import com.android.dx.rop.cst.CstLiteralBits;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 32s}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(2);
+
+ bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+ bits.set(1, unsignedFitsInByte(regs.get(1).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
int value =
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 32x}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(2);
+
+ bits.set(0, unsignedFitsInShort(regs.get(0).getReg()));
+ bits.set(1, unsignedFitsInShort(regs.get(1).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 33x}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(3);
+
+ bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+ bits.set(1, unsignedFitsInByte(regs.get(1).getReg()));
+ bits.set(2, unsignedFitsInShort(regs.get(2).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
write(out,
import com.android.dx.rop.type.Type;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 35c}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ int sz = regs.size();
+ BitSet bits = new BitSet(sz);
+
+ for (int i = 0; i < sz; i++) {
+ RegisterSpec reg = regs.get(i);
+ /*
+ * The check below adds (category - 1) to the register, to
+ * account for the fact that the second half of a
+ * category-2 register has to be represented explicitly in
+ * the result.
+ */
+ bits.set(i, unsignedFitsInNibble(reg.getReg() +
+ reg.getCategory() - 1));
+ }
+
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
int cpi = ((CstInsn) insn).getIndex();
RegisterSpecList regs = explicitize(insn.getRegisters());
import com.android.dx.dex.code.CstInsn;
import com.android.dx.dex.code.DalvInsn;
import com.android.dx.dex.code.InsnFormat;
-import com.android.dx.rop.code.RegisterSpec;
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.CstMethodRef;
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 41c}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ int sz = regs.size();
+ BitSet bits = new BitSet(sz);
+ boolean compat = unsignedFitsInByte(regs.get(0).getReg());
+
+ if (sz == 1) {
+ bits.set(0, compat);
+ } else {
+ if (regs.get(0).getReg() == regs.get(1).getReg()) {
+ bits.set(0, compat);
+ bits.set(1, compat);
+ }
+ }
+
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
int cpi = ((CstInsn) insn).getIndex();
import com.android.dx.rop.cst.CstLiteralBits;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 51l}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(1);
+
+ bits.set(0, unsignedFitsInByte(regs.get(0).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
long value =
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.CstFieldRef;
-import com.android.dx.rop.cst.CstString;
import com.android.dx.rop.cst.CstType;
import com.android.dx.util.AnnotatedOutput;
+import java.util.BitSet;
+
/**
* Instruction format {@code 52c}. See the instruction format spec
* for details.
/** {@inheritDoc} */
@Override
+ public BitSet compatibleRegs(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ BitSet bits = new BitSet(2);
+
+ bits.set(0, unsignedFitsInShort(regs.get(0).getReg()));
+ bits.set(1, unsignedFitsInShort(regs.get(1).getReg()));
+ return bits;
+ }
+
+ /** {@inheritDoc} */
+ @Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
int cpi = ((CstInsn) insn).getIndex();
import com.android.dx.dex.code.CstInsn;
import com.android.dx.dex.code.DalvInsn;
import com.android.dx.dex.code.InsnFormat;
-import com.android.dx.rop.code.RegisterSpec;
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.rop.cst.Constant;
import com.android.dx.rop.cst.CstMethodRef;
import com.android.dx.rop.type.TypeList;
import com.android.dx.util.FixedSizeList;
+import java.util.BitSet;
+
/**
* List of {@link RegisterSpec} instances.
*/
}
/**
+ * Returns a new instance, which contains a subset of the elements
+ * specified by the given BitSet. Indexes in the BitSet with a zero
+ * are included, while indexes with a one are excluded. Mutability
+ * of the result is inherited from the original.
+ *
+ * @param exclusionSet {@code non-null;} set of registers to exclude
+ * @return {@code non-null;} an appropriately-constructed instance
+ */
+ public RegisterSpecList subset(BitSet exclusionSet) {
+ int newSize = size() - exclusionSet.cardinality();
+
+ if (newSize == 0) {
+ return EMPTY;
+ }
+
+ RegisterSpecList result = new RegisterSpecList(newSize);
+
+ int newIndex = 0;
+ for (int oldIndex = 0; oldIndex < size(); oldIndex++) {
+ if (!exclusionSet.get(oldIndex)) {
+ result.set0(newIndex, get0(oldIndex));
+ newIndex++;
+ }
+ }
+
+ if (isImmutable()) {
+ result.setImmutable();
+ }
+
+ return result;
+ }
+
+ /**
* Returns an instance that is identical to this one, except that
* all register numbers are offset by the given amount. Mutability
* of the result is inherited from the original.
/**
* Returns an instance that is identical to this one, except that
- * all register numbers are renumbered sequentially from the given
- * base, with the first number duplicated if indicated.
+ * all incompatible register numbers are renumbered sequentially from
+ * the given base, with the first number duplicated if indicated. If
+ * a null BitSet is given, it indicates all registers are compatible.
*
* @param base the base register number
* @param duplicateFirst whether to duplicate the first number
+ * @param compatRegs {@code null-ok;} either a {@code non-null} set of
+ * compatible registers, or {@code null} to indicate all registers are
+ * compatible
* @return {@code non-null;} an appropriately-constructed instance
*/
- public RegisterSpecList withSequentialRegisters(int base,
- boolean duplicateFirst) {
+ public RegisterSpecList withExpandedRegisters(int base,
+ boolean duplicateFirst,
+ BitSet compatRegs) {
int sz = size();
if (sz == 0) {
for (int i = 0; i < sz; i++) {
RegisterSpec one = (RegisterSpec) get0(i);
- result.set0(i, one.withReg(base));
+ boolean replace = (compatRegs == null) ? true : !compatRegs.get(i);
+
+ if (replace) {
+ result.set0(i, one.withReg(base));
+ if (!duplicateFirst) {
+ base += one.getCategory();
+ }
+ } else {
+ result.set0(i, one);
+ }
+
if (duplicateFirst) {
duplicateFirst = false;
- } else {
- base += one.getCategory();
}
}
return result;
}
-
}
import com.android.dx.rop.code.BasicBlock;
import com.android.dx.rop.code.BasicBlockList;
-import com.android.dx.rop.code.CstInsn;
import com.android.dx.rop.code.InsnList;
-import com.android.dx.rop.code.RegOps;
import com.android.dx.rop.code.RegisterSpec;
import com.android.dx.rop.code.RegisterSpecList;
+import com.android.dx.rop.code.Rop;
import com.android.dx.rop.code.RopMethod;
import com.android.dx.rop.code.Rops;
-import com.android.dx.rop.code.Rop;
-import com.android.dx.rop.cst.CstInteger;
-import com.android.dx.ssa.NormalSsaInsn;
import com.android.dx.ssa.BasicRegisterMapper;
import com.android.dx.ssa.PhiInsn;
import com.android.dx.ssa.RegisterMapper;
import com.android.dx.ssa.SsaBasicBlock;
import com.android.dx.ssa.SsaInsn;
import com.android.dx.ssa.SsaMethod;
-import com.android.dx.util.IntList;
import com.android.dx.util.Hex;
+import com.android.dx.util.IntList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
/**
* Converts a method in SSA form to ROP form.