Inching closer to having extended opcodes in the vm.
Change-Id: If6578a0686ac8fe5e6d1a26509d8a5c748bed179
diff --git a/opcode-gen/opcode-gen.awk b/opcode-gen/opcode-gen.awk
index 20e1a36..3d52968 100644
--- a/opcode-gen/opcode-gen.awk
+++ b/opcode-gen/opcode-gen.awk
@@ -16,11 +16,13 @@
BEGIN {
MAX_OPCODE = 65535;
- MAX_LIBDEX_OPCODE = 255; # TODO: Will not be true for long!
+ MAX_PACKED_OPCODE = 511;
+ MAX_PACKED_OPCODE = 255; # TODO: Not for long!
initIndexTypes();
initFlags();
if (readBytecodes()) exit 1;
deriveOpcodeChains();
+ createPackedTables();
consumeUntil = "";
}
@@ -96,20 +98,20 @@
consumeUntil = "END(libcore-opcodes)";
print;
- for (i = 0; i <= MAX_LIBDEX_OPCODE; i++) {
- if (isUnusedByte(i) || isOptimized(i)) continue;
+ for (i = 0; i <= MAX_OPCODE; i++) {
+ if (isUnused(i) || isOptimized(i)) continue;
printf(" int OP_%-28s = 0x%02x;\n", constName[i], i);
}
next;
}
-/BEGIN\(libcore-maximum-value\)/ {
- consumeUntil = "END(libcore-maximum-value)";
+/BEGIN\(libcore-maximum-values\)/ {
+ consumeUntil = "END(libcore-maximum-values)";
print;
- # TODO: Make this smarter.
- printf(" MAXIMUM_VALUE = %d;\n", MAX_LIBDEX_OPCODE);
+ printf(" MAXIMUM_VALUE = %d;\n", MAX_OPCODE);
+ printf(" MAXIMUM_PACKED_VALUE = %d;\n", MAX_PACKED_OPCODE);
next;
}
@@ -118,8 +120,8 @@
consumeUntil = "END(libdex-opcode-enum)";
print;
- for (i = 0; i <= MAX_LIBDEX_OPCODE; i++) {
- printf(" OP_%-28s = 0x%02x,\n", constNameOrUnusedByte(i), i);
+ for (i = 0; i <= MAX_PACKED_OPCODE; i++) {
+ printf(" OP_%-28s = 0x%02x,\n", packedConstName[i], i);
}
next;
@@ -129,8 +131,8 @@
consumeUntil = "END(libdex-goto-table)";
print;
- for (i = 0; i <= MAX_LIBDEX_OPCODE; i++) {
- content = sprintf(" H(OP_%s),", constNameOrUnusedByte(i));
+ for (i = 0; i <= MAX_PACKED_OPCODE; i++) {
+ content = sprintf(" H(OP_%s),", packedConstName[i]);
printf("%-78s\\\n", content);
}
@@ -141,8 +143,8 @@
consumeUntil = "END(libdex-opcode-names)";
print;
- for (i = 0; i <= MAX_LIBDEX_OPCODE; i++) {
- printf(" \"%s\",\n", nameOrUnusedByte(i));
+ for (i = 0; i <= MAX_PACKED_OPCODE; i++) {
+ printf(" \"%s\",\n", packedName[i]);
}
next;
@@ -153,9 +155,9 @@
print;
col = 1;
- for (i = 0; i <= MAX_LIBDEX_OPCODE; i++) {
- value = sprintf("%d,", isUnusedByte(i) ? 0 : width[i]);
- col = colPrint(value, (i == MAX_LIBDEX_OPCODE), col, 16, 2, " ");
+ for (i = 0; i <= MAX_PACKED_OPCODE; i++) {
+ value = sprintf("%d,", packedWidth[i]);
+ col = colPrint(value, (i == MAX_PACKED_OPCODE), col, 16, 2, " ");
}
next;
@@ -165,8 +167,8 @@
consumeUntil = "END(libdex-flags)";
print;
- for (i = 0; i <= MAX_LIBDEX_OPCODE; i++) {
- value = flagsToC(isUnusedByte(i) ? 0 : flags[i]);
+ for (i = 0; i <= MAX_PACKED_OPCODE; i++) {
+ value = flagsToC(packedFlags[i]);
printf(" %s,\n", value);
}
@@ -178,9 +180,9 @@
print;
col = 1;
- for (i = 0; i <= MAX_LIBDEX_OPCODE; i++) {
- value = sprintf("kFmt%s,", isUnusedByte(i) ? "00x" : format[i]);
- col = colPrint(value, (i == MAX_LIBDEX_OPCODE), col, 7, 9, " ");
+ for (i = 0; i <= MAX_PACKED_OPCODE; i++) {
+ value = sprintf("kFmt%s,", packedFormat[i]);
+ col = colPrint(value, (i == MAX_PACKED_OPCODE), col, 7, 9, " ");
}
next;
@@ -191,10 +193,9 @@
print;
col = 1;
- for (i = 0; i <= MAX_LIBDEX_OPCODE; i++) {
- value = isUnusedByte(i) ? "unknown" : indexType[i];
- value = sprintf("%s,", indexTypeValues[value]);
- col = colPrint(value, (i == MAX_LIBDEX_OPCODE), col, 3, 19, " ");
+ for (i = 0; i <= MAX_PACKED_OPCODE; i++) {
+ value = sprintf("%s,", indexTypeValues[packedIndexType[i]]);
+ col = colPrint(value, (i == MAX_PACKED_OPCODE), col, 3, 19, " ");
}
next;
@@ -367,6 +368,74 @@
return -1;
}
+# Construct the tables of info indexed by packed opcode. The packed opcode
+# values are in the range 0-0x1ff, whereas the unpacked opcodes sparsely
+# span the range 0-0xffff.
+function createPackedTables(i, op) {
+ # locals: i, op
+ for (i = 0; i <= MAX_PACKED_OPCODE; i++) {
+ op = unpackOpcode(i);
+ if (i == 255) {
+ # Special case: This is the low-opcode slot for a would-be
+ # extended opcode dispatch implementation.
+ packedName[i] = "dispatch-ff";
+ packedConstName[i] = "DISPATCH_FF";
+ packedFormat[i] = "00x";
+ packedFlags[i] = 0;
+ packedWidth[i] = 0;
+ packedIndexType[i] = "unknown";
+ } else if (isUnused(op)) {
+ packedName[i] = unusedName(op);
+ packedConstName[i] = unusedConstName(op);
+ packedFormat[i] = "00x";
+ packedFlags[i] = 0;
+ packedWidth[i] = 0;
+ packedIndexType[i] = "unknown";
+ } else {
+ packedName[i] = name[op];
+ packedConstName[i] = constName[op];
+ packedFormat[i] = format[op];
+ packedFlags[i] = flags[op];
+ packedWidth[i] = width[op];
+ packedIndexType[i] = indexType[op];
+ }
+ }
+}
+
+# Given a packed opcode, returns the raw (unpacked) opcode value.
+function unpackOpcode(idx) {
+ # Note: This must be the inverse of the corresponding code in
+ # libdex/DexOpcodes.h.
+ if (idx <= 255) {
+ return idx;
+ } else {
+ return (idx * 256) + 255;
+ }
+}
+
+# Returns the "unused" name of the given opcode (by index).
+# That is, this is the human-oriented name to use for an opcode
+# definition in cases
+# where the opcode isn't used.
+function unusedName(idx) {
+ if (idx <= 255) {
+ return sprintf("unused-%02x", idx);
+ } else {
+ return sprintf("unused-%04x", idx);
+ }
+}
+
+# Returns the "unused" constant name of the given opcode (by index).
+# That is, this is the name to use for a constant definition in cases
+# where the opcode isn't used.
+function unusedConstName(idx) {
+ if (idx <= 255) {
+ return toupper(sprintf("UNUSED_%02x", idx));
+ } else {
+ return toupper(sprintf("UNUSED_%04x", idx));
+ }
+}
+
# Convert a hex value to an int.
function parseHex(hex, result, chars, count, c, i) {
# locals: result, chars, count, c, i
@@ -434,17 +503,6 @@
return result;
}
-# Given a packed opcode, returns the raw (unpacked) opcode value.
-function unpackOpcode(idx) {
- # Note: This must be the inverse of the corresponding code in
- # libdex/DexOpcodes.h.
- if (idx <= 0xff) {
- return idx;
- } else {
- return (idx * 0x100) + 0xff;
- }
-}
-
# Returns true if the given opcode (by index) is an "optimized" opcode.
function isOptimized(idx, parts, f) {
# locals: parts, f
@@ -459,33 +517,3 @@
function isUnused(idx) {
return (name[idx] == "");
}
-
-# Returns true if there is no definition for the given opcode (by
-# index), taken as a single-byte opcode. The odd case for this
-# function is 255, which is the first extended (two-byte) opcode. For
-# the purposes of this function, it is considered unused. (This is
-# meant as a stop-gap measure for code that is not yet prepared to
-# deal with extended opcodes.)
-function isUnusedByte(idx) {
- return (idx == 255) || (name[idx] == "");
-}
-
-# Returns the constant name of the given single-byte opcode (by index)
-# or the string "UNUSED_XX" (where XX is the index in hex) if the
-# opcode is unused. See isUnusedByte(), above, for more info.
-function constNameOrUnusedByte(idx) {
- if (isUnusedByte(idx)) {
- return toupper(sprintf("UNUSED_%02x", idx));
- }
- return constName[idx];
-}
-
-# Returns the (human-oriented) name of the given single-byte opcode
-# (by index) or the string "unused-xx" (where xx is the index in hex)
-# if the opcode is unused. See isUnusedByte(), above, for more info.
-function nameOrUnusedByte(idx) {
- if (isUnusedByte(idx)) {
- return sprintf("unused-%02x", idx);
- }
- return name[idx];
-}