Implement the new instruction formats.
I also refactored some of the old code in the process, to minimize
duplication, and I also did a minor cleanup of the format spec.
Change-Id: Ib07ea4ade52aa6ec4fa69000798e0cfb8f10c3a9
diff --git a/docs/instruction-formats.html b/docs/instruction-formats.html
index b936698..5db2dfd 100644
--- a/docs/instruction-formats.html
+++ b/docs/instruction-formats.html
@@ -326,7 +326,7 @@
<td>const-string/jumbo</td>
</tr>
<tr>
- <td>B|A|<i>op</i> CCCC G|F|E|D</td>
+ <td rowspan="2">B|A|<i>op</i> CCCC G|F|E|D</td>
<td>35c</td>
<td><i>[<code>B=5</code>] <code>op</code></i> {vD, vE, vF, vG, vA},
meth@CCCC<br/>
@@ -346,7 +346,6 @@
<td> </td>
</tr>
<tr>
- <td>B|A|<i>op</i> CCCC G|F|E|D</td>
<td>35ms</td>
<td><i>[<code>B=5</code>] <code>op</code></i> {vD, vE, vF, vG, vA},
@@ -365,7 +364,7 @@
</td>
</tr>
<tr>
- <td>AA|<i>op</i> BBBB CCCC</td>
+ <td rowspan="2">AA|<i>op</i> BBBB CCCC</td>
<td>3rc</td>
<td><i><code>op</code></i> {vCCCC .. vNNNN}, meth@BBBB<br/>
<i><code>op</code></i> {vCCCC .. vNNNN}, type@BBBB<br/>
@@ -376,7 +375,6 @@
<td> </td>
</tr>
<tr>
- <td>AA|<i>op</i> BBBB CCCC</td>
<td>3rms</td>
<td><i><code>op</code></i> {vCCCC .. vNNNN}, vtaboff@BBBB<br/>
<p><i>where <code>NNNN = CCCC+AA-1</code>, that is <code>A</code>
diff --git a/dx/src/com/android/dx/dex/code/InsnFormat.java b/dx/src/com/android/dx/dex/code/InsnFormat.java
index e7171c4..19b2151 100644
--- a/dx/src/com/android/dx/dex/code/InsnFormat.java
+++ b/dx/src/com/android/dx/dex/code/InsnFormat.java
@@ -16,6 +16,7 @@
package com.android.dx.dex.code;
+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.CstInteger;
@@ -182,6 +183,49 @@
}
/**
+ * Helper method to return a register range string.
+ *
+ * @param list {@code non-null;} the list of registers (which must be
+ * sequential)
+ * @return {@code non-null;} the string form
+ */
+ protected static String regRangeString(RegisterSpecList list) {
+ int size = list.size();
+ StringBuilder sb = new StringBuilder(30);
+
+ sb.append("{");
+
+ switch (size) {
+ case 0: {
+ // Nothing to do.
+ break;
+ }
+ case 1: {
+ sb.append(list.get(0).regString());
+ break;
+ }
+ default: {
+ RegisterSpec lastReg = list.get(size - 1);
+ if (lastReg.getCategory() == 2) {
+ /*
+ * Add one to properly represent a list-final
+ * category-2 register.
+ */
+ lastReg = lastReg.withOffset(1);
+ }
+
+ sb.append(list.get(0).regString());
+ sb.append("..");
+ sb.append(lastReg.regString());
+ }
+ }
+
+ sb.append("}");
+
+ return sb.toString();
+ }
+
+ /**
* Helper method to return a literal bits argument string.
*
* @param value the value
@@ -370,6 +414,34 @@
}
/**
+ * Helper method to determine if a list of registers are sequential,
+ * including degenerate cases for empty or single-element lists.
+ *
+ * @param list {@code non-null;} the list of registers
+ * @return {@code true} iff the list is sequentially ordered
+ */
+ protected static boolean isRegListSequential(RegisterSpecList list) {
+ int sz = list.size();
+
+ if (sz < 2) {
+ return true;
+ }
+
+ int first = list.get(0).getReg();
+ int next = first;
+
+ for (int i = 0; i < sz; i++) {
+ RegisterSpec one = list.get(i);
+ if (one.getReg() != next) {
+ return false;
+ }
+ next += one.getCategory();
+ }
+
+ return true;
+ }
+
+ /**
* Helper method to extract the callout-argument index from an
* appropriate instruction.
*
diff --git a/dx/src/com/android/dx/dex/code/form/Form21c.java b/dx/src/com/android/dx/dex/code/form/Form21c.java
index ed1ec3c..55979cd 100644
--- a/dx/src/com/android/dx/dex/code/form/Form21c.java
+++ b/dx/src/com/android/dx/dex/code/form/Form21c.java
@@ -103,12 +103,12 @@
CstInsn ci = (CstInsn) insn;
int cpi = ci.getIndex();
+ Constant cst = ci.getConstant();
if (! unsignedFitsInShort(cpi)) {
return false;
}
- Constant cst = ci.getConstant();
return (cst instanceof CstType) ||
(cst instanceof CstFieldRef) ||
(cst instanceof CstString);
diff --git a/dx/src/com/android/dx/dex/code/form/Form22c.java b/dx/src/com/android/dx/dex/code/form/Form22c.java
index 423ccc8..62809bc 100644
--- a/dx/src/com/android/dx/dex/code/form/Form22c.java
+++ b/dx/src/com/android/dx/dex/code/form/Form22c.java
@@ -92,7 +92,7 @@
/** {@inheritDoc} */
@Override
public InsnFormat nextUp() {
- return null;
+ return Form52c.THE_ONE;
}
/** {@inheritDoc} */
diff --git a/dx/src/com/android/dx/dex/code/form/Form22s.java b/dx/src/com/android/dx/dex/code/form/Form22s.java
index 5964217..15cf70d 100644
--- a/dx/src/com/android/dx/dex/code/form/Form22s.java
+++ b/dx/src/com/android/dx/dex/code/form/Form22s.java
@@ -89,7 +89,7 @@
/** {@inheritDoc} */
@Override
public InsnFormat nextUp() {
- return null;
+ return Form32s.THE_ONE;
}
/** {@inheritDoc} */
diff --git a/dx/src/com/android/dx/dex/code/form/Form31c.java b/dx/src/com/android/dx/dex/code/form/Form31c.java
index 60cc1b7..ef4f8dc 100644
--- a/dx/src/com/android/dx/dex/code/form/Form31c.java
+++ b/dx/src/com/android/dx/dex/code/form/Form31c.java
@@ -104,15 +104,15 @@
CstInsn ci = (CstInsn) insn;
Constant cst = ci.getConstant();
- return ((cst instanceof CstType) ||
- (cst instanceof CstFieldRef) ||
- (cst instanceof CstString));
+ return (cst instanceof CstType) ||
+ (cst instanceof CstFieldRef) ||
+ (cst instanceof CstString);
}
/** {@inheritDoc} */
@Override
public InsnFormat nextUp() {
- return null;
+ return Form41c.THE_ONE;
}
/** {@inheritDoc} */
diff --git a/dx/src/com/android/dx/dex/code/form/Form32s.java b/dx/src/com/android/dx/dex/code/form/Form32s.java
new file mode 100644
index 0000000..f55922e
--- /dev/null
+++ b/dx/src/com/android/dx/dex/code/form/Form32s.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dx.dex.code.form;
+
+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.RegisterSpecList;
+import com.android.dx.rop.cst.Constant;
+import com.android.dx.rop.cst.CstLiteralBits;
+import com.android.dx.util.AnnotatedOutput;
+
+/**
+ * Instruction format {@code 32s}. See the instruction format spec
+ * for details.
+ */
+public final class Form32s extends InsnFormat {
+ /** {@code non-null;} unique instance of this class */
+ public static final InsnFormat THE_ONE = new Form32s();
+
+ /**
+ * Constructs an instance. This class is not publicly
+ * instantiable. Use {@link #THE_ONE}.
+ */
+ private Form32s() {
+ // This space intentionally left blank.
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String insnArgString(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ CstLiteralBits value = (CstLiteralBits) ((CstInsn) insn).getConstant();
+
+ return regs.get(0).regString() + ", " + regs.get(1).regString()
+ + ", " + literalBitsString(value);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String insnCommentString(DalvInsn insn, boolean noteIndices) {
+ CstLiteralBits value = (CstLiteralBits) ((CstInsn) insn).getConstant();
+ return literalBitsComment(value, 16);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int codeSize() {
+ return 3;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isCompatible(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ if (!((insn instanceof CstInsn) &&
+ (regs.size() == 2) &&
+ unsignedFitsInByte(regs.get(0).getReg()) &&
+ unsignedFitsInByte(regs.get(1).getReg()))) {
+ return false;
+ }
+
+ CstInsn ci = (CstInsn) insn;
+ Constant cst = ci.getConstant();
+
+ if (!(cst instanceof CstLiteralBits)) {
+ return false;
+ }
+
+ CstLiteralBits cb = (CstLiteralBits) cst;
+
+ return cb.fitsInInt() && signedFitsInShort(cb.getIntBits());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public InsnFormat nextUp() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void writeTo(AnnotatedOutput out, DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ int value =
+ ((CstLiteralBits) ((CstInsn) insn).getConstant()).getIntBits();
+
+ write(out,
+ opcodeUnit(insn),
+ codeUnit(regs.get(0).getReg(), regs.get(1).getReg()),
+ (short) value);
+ }
+}
diff --git a/dx/src/com/android/dx/dex/code/form/Form32x.java b/dx/src/com/android/dx/dex/code/form/Form32x.java
index 4a981ee..0ae6f83 100644
--- a/dx/src/com/android/dx/dex/code/form/Form32x.java
+++ b/dx/src/com/android/dx/dex/code/form/Form32x.java
@@ -71,7 +71,7 @@
/** {@inheritDoc} */
@Override
public InsnFormat nextUp() {
- return null;
+ return Form33x.THE_ONE;
}
/** {@inheritDoc} */
diff --git a/dx/src/com/android/dx/dex/code/form/Form33x.java b/dx/src/com/android/dx/dex/code/form/Form33x.java
new file mode 100644
index 0000000..a8ea3af
--- /dev/null
+++ b/dx/src/com/android/dx/dex/code/form/Form33x.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dx.dex.code.form;
+
+import com.android.dx.dex.code.DalvInsn;
+import com.android.dx.dex.code.InsnFormat;
+import com.android.dx.dex.code.SimpleInsn;
+import com.android.dx.rop.code.RegisterSpecList;
+import com.android.dx.util.AnnotatedOutput;
+
+/**
+ * Instruction format {@code 33x}. See the instruction format spec
+ * for details.
+ */
+public final class Form33x extends InsnFormat {
+ /** {@code non-null;} unique instance of this class */
+ public static final InsnFormat THE_ONE = new Form33x();
+
+ /**
+ * Constructs an instance. This class is not publicly
+ * instantiable. Use {@link #THE_ONE}.
+ */
+ private Form33x() {
+ // This space intentionally left blank.
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String insnArgString(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ return regs.get(0).regString() + ", " + regs.get(1).regString() +
+ ", " + regs.get(2).regString();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String insnCommentString(DalvInsn insn, boolean noteIndices) {
+ // This format has no comment.
+ return "";
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int codeSize() {
+ return 3;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isCompatible(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+
+ return (insn instanceof SimpleInsn) &&
+ (regs.size() == 3) &&
+ unsignedFitsInByte(regs.get(0).getReg()) &&
+ unsignedFitsInByte(regs.get(1).getReg()) &&
+ unsignedFitsInShort(regs.get(2).getReg());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public InsnFormat nextUp() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void writeTo(AnnotatedOutput out, DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ write(out,
+ opcodeUnit(insn),
+ codeUnit(regs.get(0).getReg(), regs.get(1).getReg()),
+ (short) regs.get(2).getReg());
+ }
+}
diff --git a/dx/src/com/android/dx/dex/code/form/Form3rc.java b/dx/src/com/android/dx/dex/code/form/Form3rc.java
index 755ad76..dab3fba 100644
--- a/dx/src/com/android/dx/dex/code/form/Form3rc.java
+++ b/dx/src/com/android/dx/dex/code/form/Form3rc.java
@@ -45,41 +45,8 @@
/** {@inheritDoc} */
@Override
public String insnArgString(DalvInsn insn) {
- RegisterSpecList regs = insn.getRegisters();
- int size = regs.size();
- StringBuilder sb = new StringBuilder(30);
-
- sb.append("{");
-
- switch (size) {
- case 0: {
- // Nothing to do.
- break;
- }
- case 1: {
- sb.append(regs.get(0).regString());
- break;
- }
- default: {
- RegisterSpec lastReg = regs.get(size - 1);
- if (lastReg.getCategory() == 2) {
- /*
- * Add one to properly represent a list-final
- * category-2 register.
- */
- lastReg = lastReg.withOffset(1);
- }
-
- sb.append(regs.get(0).regString());
- sb.append("..");
- sb.append(lastReg.regString());
- }
- }
-
- sb.append("}, ");
- sb.append(cstString(insn));
-
- return sb.toString();
+ return regRangeString(insn.getRegisters()) + ", " +
+ cstString(insn);
}
/** {@inheritDoc} */
@@ -107,12 +74,12 @@
CstInsn ci = (CstInsn) insn;
int cpi = ci.getIndex();
+ Constant cst = ci.getConstant();
if (! unsignedFitsInShort(cpi)) {
return false;
}
- Constant cst = ci.getConstant();
if (!((cst instanceof CstMethodRef) ||
(cst instanceof CstType))) {
return false;
@@ -121,55 +88,26 @@
RegisterSpecList regs = ci.getRegisters();
int sz = regs.size();
- if (sz == 0) {
- return true;
- }
-
- int first = regs.get(0).getReg();
- int next = first;
-
- if (!unsignedFitsInShort(first)) {
- return false;
- }
-
- for (int i = 0; i < sz; i++) {
- RegisterSpec one = regs.get(i);
- if (one.getReg() != next) {
- return false;
- }
- next += one.getCategory();
- }
-
- return unsignedFitsInByte(next - first);
+ return (regs.size() == 0) ||
+ (isRegListSequential(regs) &&
+ unsignedFitsInShort(regs.get(0).getReg()) &&
+ unsignedFitsInByte(regs.getWordCount()));
}
/** {@inheritDoc} */
@Override
public InsnFormat nextUp() {
- return null;
+ return Form5rc.THE_ONE;
}
/** {@inheritDoc} */
@Override
public void writeTo(AnnotatedOutput out, DalvInsn insn) {
RegisterSpecList regs = insn.getRegisters();
- int sz = regs.size();
int cpi = ((CstInsn) insn).getIndex();
- int firstReg;
- int count;
+ int firstReg = (regs.size() == 0) ? 0 : regs.get(0).getReg();
+ int count = regs.getWordCount();
- if (sz == 0) {
- firstReg = 0;
- count = 0;
- } else {
- int lastReg = regs.get(sz - 1).getNextReg();
- firstReg = regs.get(0).getReg();
- count = lastReg - firstReg;
- }
-
- write(out,
- opcodeUnit(insn, count),
- (short) cpi,
- (short) firstReg);
+ write(out, opcodeUnit(insn, count), (short) cpi, (short) firstReg);
}
}
diff --git a/dx/src/com/android/dx/dex/code/form/Form41c.java b/dx/src/com/android/dx/dex/code/form/Form41c.java
new file mode 100644
index 0000000..1f02cb2
--- /dev/null
+++ b/dx/src/com/android/dx/dex/code/form/Form41c.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dx.dex.code.form;
+
+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.CstFieldRef;
+import com.android.dx.rop.cst.CstString;
+import com.android.dx.rop.cst.CstType;
+import com.android.dx.util.AnnotatedOutput;
+
+/**
+ * Instruction format {@code 41c}. See the instruction format spec
+ * for details.
+ */
+public final class Form41c extends InsnFormat {
+ /** {@code non-null;} unique instance of this class */
+ public static final InsnFormat THE_ONE = new Form41c();
+
+ /**
+ * Constructs an instance. This class is not publicly
+ * instantiable. Use {@link #THE_ONE}.
+ */
+ private Form41c() {
+ // This space intentionally left blank.
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String insnArgString(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ return regs.get(0).regString() + ", " + cstString(insn);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String insnCommentString(DalvInsn insn, boolean noteIndices) {
+ if (noteIndices) {
+ return cstComment(insn);
+ } else {
+ return "";
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int codeSize() {
+ return 4;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isCompatible(DalvInsn insn) {
+ if (!(insn instanceof CstInsn)) {
+ return false;
+ }
+
+ RegisterSpecList regs = insn.getRegisters();
+ RegisterSpec reg;
+
+ switch (regs.size()) {
+ case 1: {
+ reg = regs.get(0);
+ break;
+ }
+ case 2: {
+ /*
+ * This format is allowed for ops that are effectively
+ * 2-arg but where the two args are identical.
+ */
+ reg = regs.get(0);
+ if (reg.getReg() != regs.get(1).getReg()) {
+ return false;
+ }
+ break;
+ }
+ default: {
+ return false;
+ }
+ }
+
+ if (!unsignedFitsInShort(reg.getReg())) {
+ return false;
+ }
+
+ CstInsn ci = (CstInsn) insn;
+ Constant cst = ci.getConstant();
+
+ return (cst instanceof CstType) ||
+ (cst instanceof CstFieldRef);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public InsnFormat nextUp() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void writeTo(AnnotatedOutput out, DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ int cpi = ((CstInsn) insn).getIndex();
+
+ write(out, opcodeUnit(insn), cpi, (short) regs.get(0).getReg());
+ }
+}
diff --git a/dx/src/com/android/dx/dex/code/form/Form52c.java b/dx/src/com/android/dx/dex/code/form/Form52c.java
new file mode 100644
index 0000000..4fd3e66
--- /dev/null
+++ b/dx/src/com/android/dx/dex/code/form/Form52c.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dx.dex.code.form;
+
+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.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;
+
+/**
+ * Instruction format {@code 52c}. See the instruction format spec
+ * for details.
+ */
+public final class Form52c extends InsnFormat {
+ /** {@code non-null;} unique instance of this class */
+ public static final InsnFormat THE_ONE = new Form52c();
+
+ /**
+ * Constructs an instance. This class is not publicly
+ * instantiable. Use {@link #THE_ONE}.
+ */
+ private Form52c() {
+ // This space intentionally left blank.
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String insnArgString(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ return regs.get(0).regString() + ", " + regs.get(1).regString() +
+ ", " + cstString(insn);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String insnCommentString(DalvInsn insn, boolean noteIndices) {
+ if (noteIndices) {
+ return cstComment(insn);
+ } else {
+ return "";
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int codeSize() {
+ return 5;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isCompatible(DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ if (!((insn instanceof CstInsn) &&
+ (regs.size() == 2) &&
+ unsignedFitsInShort(regs.get(0).getReg()) &&
+ unsignedFitsInShort(regs.get(1).getReg()))) {
+ return false;
+ }
+
+ CstInsn ci = (CstInsn) insn;
+ Constant cst = ci.getConstant();
+
+ return (cst instanceof CstType) ||
+ (cst instanceof CstFieldRef);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public InsnFormat nextUp() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void writeTo(AnnotatedOutput out, DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ int cpi = ((CstInsn) insn).getIndex();
+
+ write(out,
+ opcodeUnit(insn),
+ cpi,
+ (short) regs.get(0).getReg(),
+ (short) regs.get(1).getReg());
+ }
+}
diff --git a/dx/src/com/android/dx/dex/code/form/Form5rc.java b/dx/src/com/android/dx/dex/code/form/Form5rc.java
new file mode 100644
index 0000000..668ef21
--- /dev/null
+++ b/dx/src/com/android/dx/dex/code/form/Form5rc.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dx.dex.code.form;
+
+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.cst.CstType;
+import com.android.dx.util.AnnotatedOutput;
+
+/**
+ * Instruction format {@code 5rc}. See the instruction format spec
+ * for details.
+ */
+public final class Form5rc extends InsnFormat {
+ /** {@code non-null;} unique instance of this class */
+ public static final InsnFormat THE_ONE = new Form5rc();
+
+ /**
+ * Constructs an instance. This class is not publicly
+ * instantiable. Use {@link #THE_ONE}.
+ */
+ private Form5rc() {
+ // This space intentionally left blank.
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String insnArgString(DalvInsn insn) {
+ return regRangeString(insn.getRegisters()) + ", " +
+ cstString(insn);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String insnCommentString(DalvInsn insn, boolean noteIndices) {
+ if (noteIndices) {
+ return cstComment(insn);
+ } else {
+ return "";
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int codeSize() {
+ return 5;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isCompatible(DalvInsn insn) {
+ if (!(insn instanceof CstInsn)) {
+ return false;
+ }
+
+ CstInsn ci = (CstInsn) insn;
+ Constant cst = ci.getConstant();
+
+ if (!((cst instanceof CstMethodRef) ||
+ (cst instanceof CstType))) {
+ return false;
+ }
+
+ RegisterSpecList regs = ci.getRegisters();
+ int sz = regs.size();
+
+ return (regs.size() == 0) ||
+ (isRegListSequential(regs) &&
+ unsignedFitsInShort(regs.get(0).getReg()) &&
+ unsignedFitsInShort(regs.getWordCount()));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public InsnFormat nextUp() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void writeTo(AnnotatedOutput out, DalvInsn insn) {
+ RegisterSpecList regs = insn.getRegisters();
+ int cpi = ((CstInsn) insn).getIndex();
+ int firstReg = (regs.size() == 0) ? 0 : regs.get(0).getReg();
+ int count = regs.getWordCount();
+
+ write(out, opcodeUnit(insn), cpi, (short) firstReg, (short) count);
+ }
+}