Refactored ApfGenerator to support multiple immediates per instruction.
In APFv4, an instruction can only have at most one immediate. However,
this is not true in APFv6. As a result, the ApfGenerator code needed to
be refactored to support multiple immediates per instruction.
Bug: 293811969
Test: TH
Change-Id: I0ef2d233f10396daa4f29f1a8a2137d13a6e621d
diff --git a/src/android/net/apf/ApfGenerator.java b/src/android/net/apf/ApfGenerator.java
index 4e692af..4b261d2 100644
--- a/src/android/net/apf/ApfGenerator.java
+++ b/src/android/net/apf/ApfGenerator.java
@@ -16,12 +16,11 @@
package android.net.apf;
-import android.annotation.Nullable;
-
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
/**
* APF assembler/generator. A tool for generating an APF program.
@@ -116,8 +115,8 @@
private class Instruction {
private final byte mOpcode; // A "Opcode" value.
private final byte mRegister; // A "Register" value.
- @Nullable
- public Immediate mImm;
+ private final int mMaxSupportedImmediates;
+ public final List<Immediate> mImms = new ArrayList<>();
// When mOpcode is a jump:
private byte mTargetLabelSize;
private String mTargetLabel;
@@ -129,24 +128,34 @@
int offset;
Instruction(Opcodes opcode, Register register) {
- mOpcode = (byte)opcode.value;
- mRegister = (byte)register.value;
+ this(opcode, register, 1 /* mMaxSupportedImmediates */);
+ }
+
+ Instruction(Opcodes opcode, Register register, int maxSupportedImm) {
+ mOpcode = (byte) opcode.value;
+ mRegister = (byte) register.value;
+ mMaxSupportedImmediates = maxSupportedImm;
}
Instruction(Opcodes opcode) {
this(opcode, Register.R0);
}
- void setImm(int imm, boolean signed) {
- mImm = new Immediate(imm, signed);
+ void addImm(int imm, boolean signed) {
+ if (mImms.size() == mMaxSupportedImmediates) {
+ throw new IllegalArgumentException(
+ String.format("Opcode: %d only support at max: %d imms", mOpcode,
+ mMaxSupportedImmediates));
+ }
+ mImms.add(new Immediate(imm, signed));
}
- void setUnsignedImm(int imm) {
- setImm(imm, false);
+ void addUnsignedImm(int imm) {
+ addImm(imm, false);
}
- void setSignedImm(int imm) {
- setImm(imm, true);
+ void addSignedImm(int imm) {
+ addImm(imm, true);
}
void setLabel(String label) throws IllegalInstructionException {
@@ -180,9 +189,7 @@
return 0;
}
int size = 1;
- if (mImm != null) {
- size += generatedImmSize();
- }
+ size += mImms.size() * generatedImmSize();
if (mTargetLabel != null) {
size += generatedImmSize();
}
@@ -255,8 +262,8 @@
if (mTargetLabel != null) {
writingOffset = writeValue(calculateTargetLabelOffset(), bytecode, writingOffset);
}
- if (mImm != null) {
- writingOffset = writeValue(mImm.mValue, bytecode, writingOffset);
+ for (int i = 0; i < mImms.size(); ++i) {
+ writingOffset = writeValue(mImms.get(i).mValue, bytecode, writingOffset);
}
if (mCompareBytes != null) {
System.arraycopy(mCompareBytes, 0, bytecode, writingOffset, mCompareBytes.length);
@@ -269,19 +276,19 @@
}
/**
- * Calculate the size of either the immediate field or the target label field, if either is
- * present. Most instructions have either an immediate or a target label field, but for the
+ * Calculate the size of either the immediate fields or the target label field, if either is
+ * present. Most instructions have either immediates or a target label field, but for the
* instructions that have both, the size of the target label field must be the same as the
- * size of the immediate field, because there is only one length field in the instruction
- * byte, hence why this function simply takes the maximum of the two sizes, so neither is
+ * size of the immediate fields, because there is only one length field in the instruction
+ * byte, hence why this function simply takes the maximum of those sizes, so neither is
* truncated.
*/
private byte generatedImmSize() {
- if (mImm == null) {
- return mTargetLabelSize;
- } else {
- return mImm.mImmSize > mTargetLabelSize ? mImm.mImmSize : mTargetLabelSize;
+ byte maxSize = mTargetLabelSize;
+ for (int i = 0; i < mImms.size(); ++i) {
+ maxSize = (byte) Math.max(maxSize, mImms.get(i).mImmSize);
}
+ return maxSize;
}
private int calculateTargetLabelOffset() throws IllegalInstructionException {
@@ -435,7 +442,7 @@
*/
public ApfGenerator addLoad8(Register register, int offset) {
Instruction instruction = new Instruction(Opcodes.LDB, register);
- instruction.setUnsignedImm(offset);
+ instruction.addUnsignedImm(offset);
addInstruction(instruction);
return this;
}
@@ -446,7 +453,7 @@
*/
public ApfGenerator addLoad16(Register register, int offset) {
Instruction instruction = new Instruction(Opcodes.LDH, register);
- instruction.setUnsignedImm(offset);
+ instruction.addUnsignedImm(offset);
addInstruction(instruction);
return this;
}
@@ -457,7 +464,7 @@
*/
public ApfGenerator addLoad32(Register register, int offset) {
Instruction instruction = new Instruction(Opcodes.LDW, register);
- instruction.setUnsignedImm(offset);
+ instruction.addUnsignedImm(offset);
addInstruction(instruction);
return this;
}
@@ -469,7 +476,7 @@
*/
public ApfGenerator addLoad8Indexed(Register register, int offset) {
Instruction instruction = new Instruction(Opcodes.LDBX, register);
- instruction.setUnsignedImm(offset);
+ instruction.addUnsignedImm(offset);
addInstruction(instruction);
return this;
}
@@ -481,7 +488,7 @@
*/
public ApfGenerator addLoad16Indexed(Register register, int offset) {
Instruction instruction = new Instruction(Opcodes.LDHX, register);
- instruction.setUnsignedImm(offset);
+ instruction.addUnsignedImm(offset);
addInstruction(instruction);
return this;
}
@@ -493,7 +500,7 @@
*/
public ApfGenerator addLoad32Indexed(Register register, int offset) {
Instruction instruction = new Instruction(Opcodes.LDWX, register);
- instruction.setUnsignedImm(offset);
+ instruction.addUnsignedImm(offset);
addInstruction(instruction);
return this;
}
@@ -503,7 +510,7 @@
*/
public ApfGenerator addAdd(int value) {
Instruction instruction = new Instruction(Opcodes.ADD);
- instruction.setUnsignedImm(value);
+ instruction.addUnsignedImm(value);
addInstruction(instruction);
return this;
}
@@ -513,7 +520,7 @@
*/
public ApfGenerator addMul(int value) {
Instruction instruction = new Instruction(Opcodes.MUL);
- instruction.setUnsignedImm(value);
+ instruction.addUnsignedImm(value);
addInstruction(instruction);
return this;
}
@@ -523,7 +530,7 @@
*/
public ApfGenerator addDiv(int value) {
Instruction instruction = new Instruction(Opcodes.DIV);
- instruction.setUnsignedImm(value);
+ instruction.addUnsignedImm(value);
addInstruction(instruction);
return this;
}
@@ -533,7 +540,7 @@
*/
public ApfGenerator addAnd(int value) {
Instruction instruction = new Instruction(Opcodes.AND);
- instruction.setUnsignedImm(value);
+ instruction.addUnsignedImm(value);
addInstruction(instruction);
return this;
}
@@ -543,7 +550,7 @@
*/
public ApfGenerator addOr(int value) {
Instruction instruction = new Instruction(Opcodes.OR);
- instruction.setUnsignedImm(value);
+ instruction.addUnsignedImm(value);
addInstruction(instruction);
return this;
}
@@ -553,7 +560,7 @@
*/
public ApfGenerator addLeftShift(int value) {
Instruction instruction = new Instruction(Opcodes.SH);
- instruction.setSignedImm(value);
+ instruction.addSignedImm(value);
addInstruction(instruction);
return this;
}
@@ -564,7 +571,7 @@
*/
public ApfGenerator addRightShift(int value) {
Instruction instruction = new Instruction(Opcodes.SH);
- instruction.setSignedImm(-value);
+ instruction.addSignedImm(-value);
addInstruction(instruction);
return this;
}
@@ -631,7 +638,7 @@
*/
public ApfGenerator addLoadImmediate(Register register, int value) {
Instruction instruction = new Instruction(Opcodes.LI, register);
- instruction.setSignedImm(value);
+ instruction.addSignedImm(value);
addInstruction(instruction);
return this;
}
@@ -642,7 +649,7 @@
*/
public ApfGenerator addJumpIfR0Equals(int value, String target) {
Instruction instruction = new Instruction(Opcodes.JEQ);
- instruction.setUnsignedImm(value);
+ instruction.addUnsignedImm(value);
instruction.setTargetLabel(target);
addInstruction(instruction);
return this;
@@ -654,7 +661,7 @@
*/
public ApfGenerator addJumpIfR0NotEquals(int value, String target) {
Instruction instruction = new Instruction(Opcodes.JNE);
- instruction.setUnsignedImm(value);
+ instruction.addUnsignedImm(value);
instruction.setTargetLabel(target);
addInstruction(instruction);
return this;
@@ -666,7 +673,7 @@
*/
public ApfGenerator addJumpIfR0GreaterThan(int value, String target) {
Instruction instruction = new Instruction(Opcodes.JGT);
- instruction.setUnsignedImm(value);
+ instruction.addUnsignedImm(value);
instruction.setTargetLabel(target);
addInstruction(instruction);
return this;
@@ -678,7 +685,7 @@
*/
public ApfGenerator addJumpIfR0LessThan(int value, String target) {
Instruction instruction = new Instruction(Opcodes.JLT);
- instruction.setUnsignedImm(value);
+ instruction.addUnsignedImm(value);
instruction.setTargetLabel(target);
addInstruction(instruction);
return this;
@@ -690,7 +697,7 @@
*/
public ApfGenerator addJumpIfR0AnyBitsSet(int value, String target) {
Instruction instruction = new Instruction(Opcodes.JSET);
- instruction.setUnsignedImm(value);
+ instruction.addUnsignedImm(value);
instruction.setTargetLabel(target);
addInstruction(instruction);
return this;
@@ -761,7 +768,7 @@
throw new IllegalInstructionException("JNEBS fails with R1");
}
Instruction instruction = new Instruction(Opcodes.JNEBS, register);
- instruction.setUnsignedImm(bytes.length);
+ instruction.addUnsignedImm(bytes.length);
instruction.setTargetLabel(target);
instruction.setCompareBytes(bytes);
addInstruction(instruction);
@@ -778,7 +785,7 @@
throw new IllegalInstructionException("illegal memory slot number: " + slot);
}
Instruction instruction = new Instruction(Opcodes.EXT, register);
- instruction.setUnsignedImm(ExtendedOpcodes.LDM.value + slot);
+ instruction.addUnsignedImm(ExtendedOpcodes.LDM.value + slot);
addInstruction(instruction);
return this;
}
@@ -793,7 +800,7 @@
throw new IllegalInstructionException("illegal memory slot number: " + slot);
}
Instruction instruction = new Instruction(Opcodes.EXT, register);
- instruction.setUnsignedImm(ExtendedOpcodes.STM.value + slot);
+ instruction.addUnsignedImm(ExtendedOpcodes.STM.value + slot);
addInstruction(instruction);
return this;
}
@@ -803,7 +810,7 @@
*/
public ApfGenerator addNot(Register register) {
Instruction instruction = new Instruction(Opcodes.EXT, register);
- instruction.setUnsignedImm(ExtendedOpcodes.NOT.value);
+ instruction.addUnsignedImm(ExtendedOpcodes.NOT.value);
addInstruction(instruction);
return this;
}
@@ -813,7 +820,7 @@
*/
public ApfGenerator addNeg(Register register) {
Instruction instruction = new Instruction(Opcodes.EXT, register);
- instruction.setUnsignedImm(ExtendedOpcodes.NEG.value);
+ instruction.addUnsignedImm(ExtendedOpcodes.NEG.value);
addInstruction(instruction);
return this;
}
@@ -823,7 +830,7 @@
*/
public ApfGenerator addSwap() {
Instruction instruction = new Instruction(Opcodes.EXT);
- instruction.setUnsignedImm(ExtendedOpcodes.SWAP.value);
+ instruction.addUnsignedImm(ExtendedOpcodes.SWAP.value);
addInstruction(instruction);
return this;
}
@@ -834,7 +841,7 @@
*/
public ApfGenerator addMove(Register register) {
Instruction instruction = new Instruction(Opcodes.EXT, register);
- instruction.setUnsignedImm(ExtendedOpcodes.MOVE.value);
+ instruction.addUnsignedImm(ExtendedOpcodes.MOVE.value);
addInstruction(instruction);
return this;
}
@@ -847,7 +854,7 @@
public ApfGenerator addAlloc(Register register) throws IllegalInstructionException {
requireApfVersion(5);
Instruction instruction = new Instruction(Opcodes.EXT, register);
- instruction.setUnsignedImm(ExtendedOpcodes.ALLOC.value);
+ instruction.addUnsignedImm(ExtendedOpcodes.ALLOC.value);
addInstruction(instruction);
return this;
}
@@ -860,7 +867,7 @@
public ApfGenerator addTrans(Register register) throws IllegalInstructionException {
requireApfVersion(5);
Instruction instruction = new Instruction(Opcodes.EXT, register);
- instruction.setUnsignedImm(ExtendedOpcodes.TRANS.value);
+ instruction.addUnsignedImm(ExtendedOpcodes.TRANS.value);
addInstruction(instruction);
return this;
}
@@ -875,7 +882,7 @@
throws IllegalInstructionException {
requireApfVersion(3);
Instruction instruction = new Instruction(Opcodes.LDDW, destinationRegister);
- instruction.setSignedImm(offset);
+ instruction.addSignedImm(offset);
addInstruction(instruction);
return this;
}
@@ -890,7 +897,7 @@
throws IllegalInstructionException {
requireApfVersion(3);
Instruction instruction = new Instruction(Opcodes.STDW, sourceRegister);
- instruction.setSignedImm(offset);
+ instruction.addSignedImm(offset);
addInstruction(instruction);
return this;
}