Add more direct encode() and decode() methods.
Also, tweaked a couple messages in CodeReader to match newly-clarified
opcode names, while I was in the territory.
Change-Id: I7bad8be967a3ca9c69f0443d4387b927ccd56d16
diff --git a/dx/src/com/android/dx/io/CodeReader.java b/dx/src/com/android/dx/io/CodeReader.java
index 7ed4a59..a25cb7c 100644
--- a/dx/src/com/android/dx/io/CodeReader.java
+++ b/dx/src/com/android/dx/io/CodeReader.java
@@ -434,7 +434,7 @@
int offset = (instructions[i + 1] & 0xFFFF)
+ ((instructions[i + 2] & 0xFFFF) << 16);
if (instructions[i + offset] != 0x100) {
- throw new DexException("Expected packed-switch pseudo-opcode but was 0x"
+ throw new DexException("Expected packed-switch-payload opcode but was 0x"
+ Integer.toHexString(instructions[i + offset]));
}
short size = instructions[i + offset + 1];
@@ -450,7 +450,7 @@
int offset = (instructions[i + 1] & 0xFFFF)
+ ((instructions[i + 2] & 0xFFFF) << 16);
if (instructions[i + offset] != 0x200) {
- throw new DexException("Expected sparse-switch pseudo-opcode but was 0x"
+ throw new DexException("Expected sparse-switch-payload opcode but was 0x"
+ Integer.toHexString(instructions[i + offset]));
}
short size = instructions[i + offset + 1];
@@ -466,7 +466,7 @@
int offset = (instructions[i + 1] & 0xFFFF)
+ ((instructions[i + 2] & 0xFFFF) << 16);
if (instructions[i + offset] != 0x300) {
- throw new DexException("Expected fill-array-data pseudo-opcode but was 0x"
+ throw new DexException("Expected fill-array-data-payload opcode but was 0x"
+ Integer.toHexString(instructions[i + offset]));
}
int bytesPerElement = instructions[i + offset + 1];
diff --git a/dx/src/com/android/dx/io/DecodedInstruction.java b/dx/src/com/android/dx/io/DecodedInstruction.java
index 23426dd..4e5b337 100644
--- a/dx/src/com/android/dx/io/DecodedInstruction.java
+++ b/dx/src/com/android/dx/io/DecodedInstruction.java
@@ -16,6 +16,8 @@
package com.android.dx.io;
+import java.io.EOFException;
+
/**
* A decoded Dalvik instruction. This consists of a format codec, a
* numeric opcode, an optional index type, and any additional
@@ -74,6 +76,17 @@
private final int e;
/**
+ * Decodes an instruction from the given input source.
+ */
+ public static DecodedInstruction decode(CodeInput in) throws EOFException {
+ int opcodeUnit = in.read();
+ int opcode = Opcodes.extractOpcodeFromUnit(opcodeUnit);
+ InstructionCodec format = OpcodeInfo.getFormat(opcode);
+
+ return format.decode(opcodeUnit, in);
+ }
+
+ /**
* Constructs an instance. This is the base constructor that takes
* all arguments.
*/
@@ -232,7 +245,14 @@
}
/**
- * Return an instance just like this one, except with the index replaced
+ * Encodes this instance to the given output.
+ */
+ public void encode(CodeOutput out) {
+ format.encode(this, out);
+ }
+
+ /**
+ * Returns an instance just like this one, except with the index replaced
* with the given one.
*/
public DecodedInstruction withIndex(int newIndex) {
diff --git a/dx/src/com/android/dx/io/OpcodeInfo.java b/dx/src/com/android/dx/io/OpcodeInfo.java
index 7359dec..133e943 100644
--- a/dx/src/com/android/dx/io/OpcodeInfo.java
+++ b/dx/src/com/android/dx/io/OpcodeInfo.java
@@ -1364,6 +1364,14 @@
}
/**
+ * Gets the format (an {@link InstructionCodec}) for the given opcode
+ * value.
+ */
+ public static InstructionCodec getFormat(int opcode) {
+ return get(opcode).getFormat();
+ }
+
+ /**
* Puts the given opcode into the table of all ops.
*
* @param opcode non-null; the opcode
diff --git a/dx/src/com/android/dx/io/Opcodes.java b/dx/src/com/android/dx/io/Opcodes.java
index 9dda7a3..51d92c2 100644
--- a/dx/src/com/android/dx/io/Opcodes.java
+++ b/dx/src/com/android/dx/io/Opcodes.java
@@ -334,6 +334,12 @@
* possibly valid
*/
public static boolean isValidShape(int opcode) {
+ /*
+ * Note: This method bakes in knowledge that all opcodes are
+ * either single-byte or of the form ((byteValue << 8) |
+ * 0xff).
+ */
+
// Note: SPECIAL_FORMAT == NO_NEXT.
if ((opcode >= SPECIAL_FORMAT) && (opcode <= 0xff)) {
return true;
@@ -346,4 +352,19 @@
return false;
}
+
+ /**
+ * Gets the opcode out of an opcode unit, the latter of which may also
+ * include one or more argument values.
+ */
+ public static int extractOpcodeFromUnit(int opcodeUnit) {
+ /*
+ * Note: This method bakes in knowledge that all opcodes are
+ * either single-byte or of the form ((byteValue << 8) |
+ * 0xff).
+ */
+
+ int lowByte = opcodeUnit & 0xff;
+ return (lowByte == 0xff) ? opcodeUnit : lowByte;
+ }
}