1*055d4590SKeyi Gui# Copyright (C) 2007 The Android Open Source Project 2*055d4590SKeyi Gui# 3*055d4590SKeyi Gui# Licensed under the Apache License, Version 2.0 (the "License"); 4*055d4590SKeyi Gui# you may not use this file except in compliance with the License. 5*055d4590SKeyi Gui# You may obtain a copy of the License at 6*055d4590SKeyi Gui# 7*055d4590SKeyi Gui# http://www.apache.org/licenses/LICENSE-2.0 8*055d4590SKeyi Gui# 9*055d4590SKeyi Gui# Unless required by applicable law or agreed to in writing, software 10*055d4590SKeyi Gui# distributed under the License is distributed on an "AS IS" BASIS, 11*055d4590SKeyi Gui# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*055d4590SKeyi Gui# See the License for the specific language governing permissions and 13*055d4590SKeyi Gui# limitations under the License. 14*055d4590SKeyi Gui 15*055d4590SKeyi Gui# 16*055d4590SKeyi Gui# Awk helper script for opcode-gen. 17*055d4590SKeyi Gui# 18*055d4590SKeyi Gui 19*055d4590SKeyi Gui# 20*055d4590SKeyi Gui# Initialization. 21*055d4590SKeyi Gui# 22*055d4590SKeyi Gui 23*055d4590SKeyi GuiBEGIN { 24*055d4590SKeyi Gui MAX_OPCODE = 65535; 25*055d4590SKeyi Gui MAX_PACKED_OPCODE = 511; 26*055d4590SKeyi Gui MAX_PACKED_OPCODE = 255; # TODO: Not for long! 27*055d4590SKeyi Gui initIndexTypes(); 28*055d4590SKeyi Gui initFlags(); 29*055d4590SKeyi Gui if (readBytecodes()) exit 1; 30*055d4590SKeyi Gui deriveOpcodeChains(); 31*055d4590SKeyi Gui createPackedTables(); 32*055d4590SKeyi Gui consumeUntil = ""; 33*055d4590SKeyi Gui emission = ""; 34*055d4590SKeyi Gui} 35*055d4590SKeyi Gui 36*055d4590SKeyi Gui# 37*055d4590SKeyi Gui# General control (must appear above directive handlers). 38*055d4590SKeyi Gui# 39*055d4590SKeyi Gui 40*055d4590SKeyi Gui# Clear out the preexisting output within a directive section. 41*055d4590SKeyi GuiconsumeUntil != "" { 42*055d4590SKeyi Gui if (index($0, consumeUntil) != 0) { 43*055d4590SKeyi Gui consumeUntil = ""; 44*055d4590SKeyi Gui print; 45*055d4590SKeyi Gui } 46*055d4590SKeyi Gui 47*055d4590SKeyi Gui next; 48*055d4590SKeyi Gui} 49*055d4590SKeyi Gui 50*055d4590SKeyi Gui# Detect directives. 51*055d4590SKeyi Gui/BEGIN\([a-z-]*\)/ { 52*055d4590SKeyi Gui i = match($0, /BEGIN\([a-z-]*\)/); 53*055d4590SKeyi Gui emission = substr($0, i + 6, RLENGTH - 7); 54*055d4590SKeyi Gui consumeUntil = "END(" emission ")"; 55*055d4590SKeyi Gui emissionHandled = 0; 56*055d4590SKeyi Gui} 57*055d4590SKeyi Gui 58*055d4590SKeyi Gui# Most lines just get copied from the source as-is, including the start 59*055d4590SKeyi Gui# comment for directives. 60*055d4590SKeyi Gui{ 61*055d4590SKeyi Gui print; 62*055d4590SKeyi Gui} 63*055d4590SKeyi Gui 64*055d4590SKeyi Gui# 65*055d4590SKeyi Gui# Handlers for all of the directives. 66*055d4590SKeyi Gui# 67*055d4590SKeyi Gui 68*055d4590SKeyi Guiemission == "opcodes" { 69*055d4590SKeyi Gui emissionHandled = 1; 70*055d4590SKeyi Gui 71*055d4590SKeyi Gui for (i = 0; i <= MAX_OPCODE; i++) { 72*055d4590SKeyi Gui if (isUnused(i) || isOptimized(i)) continue; 73*055d4590SKeyi Gui printf(" public static final int %s = 0x%s;\n", 74*055d4590SKeyi Gui constName[i], hex[i]); 75*055d4590SKeyi Gui } 76*055d4590SKeyi Gui} 77*055d4590SKeyi Gui 78*055d4590SKeyi Guiemission == "first-opcodes" { 79*055d4590SKeyi Gui emissionHandled = 1; 80*055d4590SKeyi Gui 81*055d4590SKeyi Gui for (i = 0; i <= MAX_OPCODE; i++) { 82*055d4590SKeyi Gui if (isUnused(i) || isOptimized(i)) continue; 83*055d4590SKeyi Gui if (isFirst[i] == "true") { 84*055d4590SKeyi Gui printf(" // Opcodes.%s\n", constName[i]); 85*055d4590SKeyi Gui } 86*055d4590SKeyi Gui } 87*055d4590SKeyi Gui} 88*055d4590SKeyi Gui 89*055d4590SKeyi Guiemission == "dops" { 90*055d4590SKeyi Gui emissionHandled = 1; 91*055d4590SKeyi Gui 92*055d4590SKeyi Gui for (i = 0; i <= MAX_OPCODE; i++) { 93*055d4590SKeyi Gui if (isUnused(i) || isOptimized(i)) continue; 94*055d4590SKeyi Gui 95*055d4590SKeyi Gui nextOp = nextOpcode[i]; 96*055d4590SKeyi Gui nextOp = (nextOp == -1) ? "NO_NEXT" : constName[nextOp]; 97*055d4590SKeyi Gui 98*055d4590SKeyi Gui printf(" public static final Dop %s =\n" \ 99*055d4590SKeyi Gui " new Dop(Opcodes.%s, Opcodes.%s,\n" \ 100*055d4590SKeyi Gui " Opcodes.%s, Form%s.THE_ONE, %s);\n\n", 101*055d4590SKeyi Gui constName[i], constName[i], family[i], nextOp, format[i], 102*055d4590SKeyi Gui hasResult[i]); 103*055d4590SKeyi Gui } 104*055d4590SKeyi Gui} 105*055d4590SKeyi Gui 106*055d4590SKeyi Guiemission == "opcode-info-defs" { 107*055d4590SKeyi Gui emissionHandled = 1; 108*055d4590SKeyi Gui 109*055d4590SKeyi Gui for (i = 0; i <= MAX_OPCODE; i++) { 110*055d4590SKeyi Gui if (isUnused(i) || isOptimized(i)) continue; 111*055d4590SKeyi Gui 112*055d4590SKeyi Gui itype = toupper(indexType[i]); 113*055d4590SKeyi Gui gsub(/-/, "_", itype); 114*055d4590SKeyi Gui 115*055d4590SKeyi Gui printf(" public static final Info %s =\n" \ 116*055d4590SKeyi Gui " new Info(Opcodes.%s, \"%s\",\n" \ 117*055d4590SKeyi Gui " InstructionCodec.FORMAT_%s, IndexType.%s);\n\n", \ 118*055d4590SKeyi Gui constName[i], constName[i], name[i], toupper(format[i]), itype); 119*055d4590SKeyi Gui } 120*055d4590SKeyi Gui} 121*055d4590SKeyi Gui 122*055d4590SKeyi Guiemission == "dops-init" || emission == "opcode-info-init" { 123*055d4590SKeyi Gui emissionHandled = 1; 124*055d4590SKeyi Gui 125*055d4590SKeyi Gui for (i = 0; i <= MAX_OPCODE; i++) { 126*055d4590SKeyi Gui if (isUnused(i) || isOptimized(i)) continue; 127*055d4590SKeyi Gui printf(" set(%s);\n", constName[i]); 128*055d4590SKeyi Gui } 129*055d4590SKeyi Gui} 130*055d4590SKeyi Gui 131*055d4590SKeyi Guiemission == "libcore-opcodes" { 132*055d4590SKeyi Gui emissionHandled = 1; 133*055d4590SKeyi Gui 134*055d4590SKeyi Gui for (i = 0; i <= MAX_OPCODE; i++) { 135*055d4590SKeyi Gui if (isUnused(i) || isOptimized(i)) continue; 136*055d4590SKeyi Gui printf(" int OP_%-28s = 0x%04x;\n", constName[i], i); 137*055d4590SKeyi Gui } 138*055d4590SKeyi Gui} 139*055d4590SKeyi Gui 140*055d4590SKeyi Guiemission == "libcore-maximum-values" { 141*055d4590SKeyi Gui emissionHandled = 1; 142*055d4590SKeyi Gui 143*055d4590SKeyi Gui printf(" MAXIMUM_VALUE = %d;\n", MAX_OPCODE); 144*055d4590SKeyi Gui printf(" MAXIMUM_PACKED_VALUE = %d;\n", MAX_PACKED_OPCODE); 145*055d4590SKeyi Gui} 146*055d4590SKeyi Gui 147*055d4590SKeyi Guiemission == "libdex-maximum-values" { 148*055d4590SKeyi Gui emissionHandled = 1; 149*055d4590SKeyi Gui 150*055d4590SKeyi Gui printf("#define kMaxOpcodeValue 0x%x\n", MAX_OPCODE); 151*055d4590SKeyi Gui printf("#define kNumPackedOpcodes 0x%x\n", MAX_PACKED_OPCODE + 1); 152*055d4590SKeyi Gui} 153*055d4590SKeyi Gui 154*055d4590SKeyi Guiemission == "libdex-opcode-enum" { 155*055d4590SKeyi Gui emissionHandled = 1; 156*055d4590SKeyi Gui 157*055d4590SKeyi Gui for (i = 0; i <= MAX_PACKED_OPCODE; i++) { 158*055d4590SKeyi Gui printf(" OP_%-28s = 0x%02x,\n", packedConstName[i], i); 159*055d4590SKeyi Gui } 160*055d4590SKeyi Gui} 161*055d4590SKeyi Gui 162*055d4590SKeyi Guiemission == "libdex-goto-table" { 163*055d4590SKeyi Gui emissionHandled = 1; 164*055d4590SKeyi Gui 165*055d4590SKeyi Gui for (i = 0; i <= MAX_PACKED_OPCODE; i++) { 166*055d4590SKeyi Gui content = sprintf(" H(OP_%s),", packedConstName[i]); 167*055d4590SKeyi Gui printf("%-78s\\\n", content); 168*055d4590SKeyi Gui } 169*055d4590SKeyi Gui} 170*055d4590SKeyi Gui 171*055d4590SKeyi Guiemission == "libdex-opcode-names" { 172*055d4590SKeyi Gui emissionHandled = 1; 173*055d4590SKeyi Gui 174*055d4590SKeyi Gui for (i = 0; i <= MAX_PACKED_OPCODE; i++) { 175*055d4590SKeyi Gui printf(" \"%s\",\n", packedName[i]); 176*055d4590SKeyi Gui } 177*055d4590SKeyi Gui} 178*055d4590SKeyi Gui 179*055d4590SKeyi Guiemission == "libdex-widths" { 180*055d4590SKeyi Gui emissionHandled = 1; 181*055d4590SKeyi Gui 182*055d4590SKeyi Gui col = 1; 183*055d4590SKeyi Gui for (i = 0; i <= MAX_PACKED_OPCODE; i++) { 184*055d4590SKeyi Gui value = sprintf("%d,", packedWidth[i]); 185*055d4590SKeyi Gui col = colPrint(value, (i == MAX_PACKED_OPCODE), col, 16, 2, " "); 186*055d4590SKeyi Gui } 187*055d4590SKeyi Gui} 188*055d4590SKeyi Gui 189*055d4590SKeyi Guiemission == "libdex-flags" { 190*055d4590SKeyi Gui emissionHandled = 1; 191*055d4590SKeyi Gui 192*055d4590SKeyi Gui for (i = 0; i <= MAX_PACKED_OPCODE; i++) { 193*055d4590SKeyi Gui value = flagsToC(packedFlags[i]); 194*055d4590SKeyi Gui printf(" %s,\n", value); 195*055d4590SKeyi Gui } 196*055d4590SKeyi Gui} 197*055d4590SKeyi Gui 198*055d4590SKeyi Guiemission == "libdex-formats" { 199*055d4590SKeyi Gui emissionHandled = 1; 200*055d4590SKeyi Gui 201*055d4590SKeyi Gui col = 1; 202*055d4590SKeyi Gui for (i = 0; i <= MAX_PACKED_OPCODE; i++) { 203*055d4590SKeyi Gui value = sprintf("kFmt%s,", packedFormat[i]); 204*055d4590SKeyi Gui col = colPrint(value, (i == MAX_PACKED_OPCODE), col, 7, 9, " "); 205*055d4590SKeyi Gui } 206*055d4590SKeyi Gui} 207*055d4590SKeyi Gui 208*055d4590SKeyi Guiemission == "libdex-index-types" { 209*055d4590SKeyi Gui emissionHandled = 1; 210*055d4590SKeyi Gui 211*055d4590SKeyi Gui col = 1; 212*055d4590SKeyi Gui for (i = 0; i <= MAX_PACKED_OPCODE; i++) { 213*055d4590SKeyi Gui value = sprintf("%s,", indexTypeValues[packedIndexType[i]]); 214*055d4590SKeyi Gui col = colPrint(value, (i == MAX_PACKED_OPCODE), col, 3, 19, " "); 215*055d4590SKeyi Gui } 216*055d4590SKeyi Gui} 217*055d4590SKeyi Gui 218*055d4590SKeyi Gui# Handle the end of directive processing (must appear after the directive 219*055d4590SKeyi Gui# clauses). 220*055d4590SKeyi Guiemission != "" { 221*055d4590SKeyi Gui if (!emissionHandled) { 222*055d4590SKeyi Gui printf("WARNING: unknown tag \"%s\"\n", emission) >"/dev/stderr"; 223*055d4590SKeyi Gui consumeUntil = ""; 224*055d4590SKeyi Gui } 225*055d4590SKeyi Gui 226*055d4590SKeyi Gui emission = ""; 227*055d4590SKeyi Gui} 228*055d4590SKeyi Gui 229*055d4590SKeyi Gui# 230*055d4590SKeyi Gui# Helper functions. 231*055d4590SKeyi Gui# 232*055d4590SKeyi Gui 233*055d4590SKeyi Gui# Helper to print out an element in a multi-column fashion. It returns 234*055d4590SKeyi Gui# the (one-based) column number that the next element will be printed 235*055d4590SKeyi Gui# in. 236*055d4590SKeyi Guifunction colPrint(value, isLast, col, numCols, colWidth, linePrefix) { 237*055d4590SKeyi Gui isLast = (isLast || (col == numCols)); 238*055d4590SKeyi Gui printf("%s%-*s%s", 239*055d4590SKeyi Gui (col == 1) ? linePrefix : " ", 240*055d4590SKeyi Gui isLast ? 1 : colWidth, value, 241*055d4590SKeyi Gui isLast ? "\n" : ""); 242*055d4590SKeyi Gui 243*055d4590SKeyi Gui return (col % numCols) + 1; 244*055d4590SKeyi Gui} 245*055d4590SKeyi Gui 246*055d4590SKeyi Gui# Read the bytecode description file. 247*055d4590SKeyi Guifunction readBytecodes(i, parts, line, cmd, status, count) { 248*055d4590SKeyi Gui # locals: parts, line, cmd, status, count 249*055d4590SKeyi Gui for (;;) { 250*055d4590SKeyi Gui # Read a line. 251*055d4590SKeyi Gui status = getline line <bytecodeFile; 252*055d4590SKeyi Gui if (status == 0) break; 253*055d4590SKeyi Gui if (status < 0) { 254*055d4590SKeyi Gui print "trouble reading bytecode file"; 255*055d4590SKeyi Gui exit 1; 256*055d4590SKeyi Gui } 257*055d4590SKeyi Gui 258*055d4590SKeyi Gui # Clean up the line and extract the command. 259*055d4590SKeyi Gui gsub(/ */, " ", line); 260*055d4590SKeyi Gui sub(/ *#.*$/, "", line); 261*055d4590SKeyi Gui sub(/ $/, "", line); 262*055d4590SKeyi Gui sub(/^ /, "", line); 263*055d4590SKeyi Gui count = split(line, parts); 264*055d4590SKeyi Gui if (count == 0) continue; # Blank or comment line. 265*055d4590SKeyi Gui cmd = parts[1]; 266*055d4590SKeyi Gui sub(/^[a-z][a-z]* */, "", line); # Remove the command from line. 267*055d4590SKeyi Gui 268*055d4590SKeyi Gui if (cmd == "op") { 269*055d4590SKeyi Gui status = defineOpcode(line); 270*055d4590SKeyi Gui } else if (cmd == "format") { 271*055d4590SKeyi Gui status = defineFormat(line); 272*055d4590SKeyi Gui } else { 273*055d4590SKeyi Gui status = -1; 274*055d4590SKeyi Gui } 275*055d4590SKeyi Gui 276*055d4590SKeyi Gui if (status != 0) { 277*055d4590SKeyi Gui printf("syntax error on line: %s\n", line) >"/dev/stderr"; 278*055d4590SKeyi Gui return 1; 279*055d4590SKeyi Gui } 280*055d4590SKeyi Gui } 281*055d4590SKeyi Gui 282*055d4590SKeyi Gui return 0; 283*055d4590SKeyi Gui} 284*055d4590SKeyi Gui 285*055d4590SKeyi Gui# Define an opcode. 286*055d4590SKeyi Guifunction defineOpcode(line, count, parts, idx) { 287*055d4590SKeyi Gui # locals: count, parts, idx 288*055d4590SKeyi Gui count = split(line, parts); 289*055d4590SKeyi Gui if (count != 6) return -1; 290*055d4590SKeyi Gui idx = parseHex(parts[1]); 291*055d4590SKeyi Gui if (idx < 0) return -1; 292*055d4590SKeyi Gui 293*055d4590SKeyi Gui # Extract directly specified values from the line. 294*055d4590SKeyi Gui hex[idx] = parts[1]; 295*055d4590SKeyi Gui name[idx] = parts[2]; 296*055d4590SKeyi Gui format[idx] = parts[3]; 297*055d4590SKeyi Gui hasResult[idx] = (parts[4] == "n") ? "false" : "true"; 298*055d4590SKeyi Gui indexType[idx] = parts[5]; 299*055d4590SKeyi Gui flags[idx] = parts[6]; 300*055d4590SKeyi Gui 301*055d4590SKeyi Gui # Calculate derived values. 302*055d4590SKeyi Gui 303*055d4590SKeyi Gui constName[idx] = toupper(name[idx]); 304*055d4590SKeyi Gui gsub("[/-]", "_", constName[idx]); # Dash and slash become underscore. 305*055d4590SKeyi Gui gsub("[+^]", "", constName[idx]); # Plus and caret are removed. 306*055d4590SKeyi Gui split(name[idx], parts, "/"); 307*055d4590SKeyi Gui 308*055d4590SKeyi Gui family[idx] = toupper(parts[1]); 309*055d4590SKeyi Gui gsub("-", "_", family[idx]); # Dash becomes underscore. 310*055d4590SKeyi Gui gsub("[+^]", "", family[idx]); # Plus and caret are removed. 311*055d4590SKeyi Gui 312*055d4590SKeyi Gui split(format[idx], parts, ""); # Width is the first format char. 313*055d4590SKeyi Gui width[idx] = parts[1]; 314*055d4590SKeyi Gui 315*055d4590SKeyi Gui # This association is used when computing "next" opcodes. 316*055d4590SKeyi Gui familyFormat[family[idx],format[idx]] = idx; 317*055d4590SKeyi Gui 318*055d4590SKeyi Gui # Verify values. 319*055d4590SKeyi Gui 320*055d4590SKeyi Gui if (nextFormat[format[idx]] == "") { 321*055d4590SKeyi Gui printf("unknown format: %s\n", format[idx]) >"/dev/stderr"; 322*055d4590SKeyi Gui return 1; 323*055d4590SKeyi Gui } 324*055d4590SKeyi Gui 325*055d4590SKeyi Gui if (indexTypeValues[indexType[idx]] == "") { 326*055d4590SKeyi Gui printf("unknown index type: %s\n", indexType[idx]) >"/dev/stderr"; 327*055d4590SKeyi Gui return 1; 328*055d4590SKeyi Gui } 329*055d4590SKeyi Gui 330*055d4590SKeyi Gui if (flagsToC(flags[idx]) == "") { 331*055d4590SKeyi Gui printf("bogus flags: %s\n", flags[idx]) >"/dev/stderr"; 332*055d4590SKeyi Gui return 1; 333*055d4590SKeyi Gui } 334*055d4590SKeyi Gui 335*055d4590SKeyi Gui return 0; 336*055d4590SKeyi Gui} 337*055d4590SKeyi Gui 338*055d4590SKeyi Gui# Define a format family. 339*055d4590SKeyi Guifunction defineFormat(line, count, parts, i) { 340*055d4590SKeyi Gui # locals: count, parts, i 341*055d4590SKeyi Gui count = split(line, parts); 342*055d4590SKeyi Gui if (count < 1) return -1; 343*055d4590SKeyi Gui formats[parts[1]] = line; 344*055d4590SKeyi Gui 345*055d4590SKeyi Gui parts[count + 1] = "none"; 346*055d4590SKeyi Gui for (i = 1; i <= count; i++) { 347*055d4590SKeyi Gui nextFormat[parts[i]] = parts[i + 1]; 348*055d4590SKeyi Gui } 349*055d4590SKeyi Gui 350*055d4590SKeyi Gui return 0; 351*055d4590SKeyi Gui} 352*055d4590SKeyi Gui 353*055d4590SKeyi Gui# Produce the nextOpcode and isFirst arrays. The former indicates, for 354*055d4590SKeyi Gui# each opcode, which one should be tried next when doing instruction 355*055d4590SKeyi Gui# fitting. The latter indicates which opcodes are at the head of an 356*055d4590SKeyi Gui# instruction fitting chain. 357*055d4590SKeyi Guifunction deriveOpcodeChains(i, op) { 358*055d4590SKeyi Gui # locals: i, op 359*055d4590SKeyi Gui 360*055d4590SKeyi Gui for (i = 0; i <= MAX_OPCODE; i++) { 361*055d4590SKeyi Gui if (isUnused(i)) continue; 362*055d4590SKeyi Gui isFirst[i] = "true"; 363*055d4590SKeyi Gui } 364*055d4590SKeyi Gui 365*055d4590SKeyi Gui for (i = 0; i <= MAX_OPCODE; i++) { 366*055d4590SKeyi Gui if (isUnused(i)) continue; 367*055d4590SKeyi Gui op = findNextOpcode(i); 368*055d4590SKeyi Gui nextOpcode[i] = op; 369*055d4590SKeyi Gui if (op != -1) { 370*055d4590SKeyi Gui isFirst[op] = "false"; 371*055d4590SKeyi Gui } 372*055d4590SKeyi Gui } 373*055d4590SKeyi Gui} 374*055d4590SKeyi Gui 375*055d4590SKeyi Gui# Given an opcode by index, find the next opcode in the same family 376*055d4590SKeyi Gui# (that is, with the same base name) to try when matching instructions 377*055d4590SKeyi Gui# to opcodes. This simply walks the nextFormat chain looking for a 378*055d4590SKeyi Gui# match. This returns the index of the matching opcode or -1 if there 379*055d4590SKeyi Gui# is none. 380*055d4590SKeyi Guifunction findNextOpcode(idx, fam, fmt, result) { 381*055d4590SKeyi Gui # locals: fam, fmt, result 382*055d4590SKeyi Gui fam = family[idx]; 383*055d4590SKeyi Gui fmt = format[idx]; 384*055d4590SKeyi Gui 385*055d4590SKeyi Gui # Not every opcode has a version with every possible format, so 386*055d4590SKeyi Gui # we have to iterate down the chain until we find one or run out of 387*055d4590SKeyi Gui # formats to try. 388*055d4590SKeyi Gui for (fmt = nextFormat[format[idx]]; fmt != "none"; fmt = nextFormat[fmt]) { 389*055d4590SKeyi Gui result = familyFormat[fam,fmt]; 390*055d4590SKeyi Gui if (result != "") { 391*055d4590SKeyi Gui return result; 392*055d4590SKeyi Gui } 393*055d4590SKeyi Gui } 394*055d4590SKeyi Gui 395*055d4590SKeyi Gui return -1; 396*055d4590SKeyi Gui} 397*055d4590SKeyi Gui 398*055d4590SKeyi Gui# Construct the tables of info indexed by packed opcode. The packed opcode 399*055d4590SKeyi Gui# values are in the range 0-0x1ff, whereas the unpacked opcodes sparsely 400*055d4590SKeyi Gui# span the range 0-0xffff. 401*055d4590SKeyi Guifunction createPackedTables(i, op) { 402*055d4590SKeyi Gui # locals: i, op 403*055d4590SKeyi Gui for (i = 0; i <= MAX_PACKED_OPCODE; i++) { 404*055d4590SKeyi Gui op = unpackOpcode(i); 405*055d4590SKeyi Gui if (isUnused(op)) { 406*055d4590SKeyi Gui packedName[i] = unusedName(op); 407*055d4590SKeyi Gui packedConstName[i] = unusedConstName(op); 408*055d4590SKeyi Gui packedFormat[i] = "00x"; 409*055d4590SKeyi Gui packedFlags[i] = 0; 410*055d4590SKeyi Gui packedWidth[i] = 0; 411*055d4590SKeyi Gui packedIndexType[i] = "unknown"; 412*055d4590SKeyi Gui } else { 413*055d4590SKeyi Gui packedName[i] = name[op]; 414*055d4590SKeyi Gui packedConstName[i] = constName[op]; 415*055d4590SKeyi Gui packedFormat[i] = format[op]; 416*055d4590SKeyi Gui packedFlags[i] = flags[op]; 417*055d4590SKeyi Gui packedWidth[i] = width[op]; 418*055d4590SKeyi Gui packedIndexType[i] = indexType[op]; 419*055d4590SKeyi Gui } 420*055d4590SKeyi Gui } 421*055d4590SKeyi Gui} 422*055d4590SKeyi Gui 423*055d4590SKeyi Gui# Given a packed opcode, returns the raw (unpacked) opcode value. 424*055d4590SKeyi Guifunction unpackOpcode(idx) { 425*055d4590SKeyi Gui # Note: This must be the inverse of the corresponding code in 426*055d4590SKeyi Gui # libdex/DexOpcodes.h. 427*055d4590SKeyi Gui if (idx <= 255) { 428*055d4590SKeyi Gui return idx; 429*055d4590SKeyi Gui } else { 430*055d4590SKeyi Gui idx -= 256; 431*055d4590SKeyi Gui return (idx * 256) + 255; 432*055d4590SKeyi Gui } 433*055d4590SKeyi Gui} 434*055d4590SKeyi Gui 435*055d4590SKeyi Gui# Returns the "unused" name of the given opcode (by index). 436*055d4590SKeyi Gui# That is, this is the human-oriented name to use for an opcode 437*055d4590SKeyi Gui# definition in cases 438*055d4590SKeyi Gui# where the opcode isn't used. 439*055d4590SKeyi Guifunction unusedName(idx) { 440*055d4590SKeyi Gui if (idx <= 255) { 441*055d4590SKeyi Gui return sprintf("unused-%02x", idx); 442*055d4590SKeyi Gui } else { 443*055d4590SKeyi Gui return sprintf("unused-%04x", idx); 444*055d4590SKeyi Gui } 445*055d4590SKeyi Gui} 446*055d4590SKeyi Gui 447*055d4590SKeyi Gui# Returns the "unused" constant name of the given opcode (by index). 448*055d4590SKeyi Gui# That is, this is the name to use for a constant definition in cases 449*055d4590SKeyi Gui# where the opcode isn't used. 450*055d4590SKeyi Guifunction unusedConstName(idx) { 451*055d4590SKeyi Gui if (idx <= 255) { 452*055d4590SKeyi Gui return toupper(sprintf("UNUSED_%02x", idx)); 453*055d4590SKeyi Gui } else { 454*055d4590SKeyi Gui return toupper(sprintf("UNUSED_%04x", idx)); 455*055d4590SKeyi Gui } 456*055d4590SKeyi Gui} 457*055d4590SKeyi Gui 458*055d4590SKeyi Gui# Convert a hex value to an int. 459*055d4590SKeyi Guifunction parseHex(hex, result, chars, count, c, i) { 460*055d4590SKeyi Gui # locals: result, chars, count, c, i 461*055d4590SKeyi Gui hex = tolower(hex); 462*055d4590SKeyi Gui count = split(hex, chars, ""); 463*055d4590SKeyi Gui result = 0; 464*055d4590SKeyi Gui for (i = 1; i <= count; i++) { 465*055d4590SKeyi Gui c = index("0123456789abcdef", chars[i]); 466*055d4590SKeyi Gui if (c == 0) { 467*055d4590SKeyi Gui printf("bogus hex value: %s\n", hex) >"/dev/stderr"; 468*055d4590SKeyi Gui return -1; 469*055d4590SKeyi Gui } 470*055d4590SKeyi Gui result = (result * 16) + c - 1; 471*055d4590SKeyi Gui } 472*055d4590SKeyi Gui return result; 473*055d4590SKeyi Gui} 474*055d4590SKeyi Gui 475*055d4590SKeyi Gui# Initialize the indexTypes data. 476*055d4590SKeyi Guifunction initIndexTypes() { 477*055d4590SKeyi Gui indexTypeValues["unknown"] = "kIndexUnknown"; 478*055d4590SKeyi Gui indexTypeValues["none"] = "kIndexNone"; 479*055d4590SKeyi Gui indexTypeValues["varies"] = "kIndexVaries"; 480*055d4590SKeyi Gui indexTypeValues["type-ref"] = "kIndexTypeRef"; 481*055d4590SKeyi Gui indexTypeValues["string-ref"] = "kIndexStringRef"; 482*055d4590SKeyi Gui indexTypeValues["method-ref"] = "kIndexMethodRef"; 483*055d4590SKeyi Gui indexTypeValues["field-ref"] = "kIndexFieldRef"; 484*055d4590SKeyi Gui indexTypeValues["inline-method"] = "kIndexInlineMethod"; 485*055d4590SKeyi Gui indexTypeValues["vtable-offset"] = "kIndexVtableOffset"; 486*055d4590SKeyi Gui indexTypeValues["field-offset"] = "kIndexFieldOffset"; 487*055d4590SKeyi Gui indexTypeValues["method-and-proto-ref"] = "kIndexMethodAndProtoRef"; 488*055d4590SKeyi Gui indexTypeValues["call-site-ref"] = "kIndexCallSiteRef"; 489*055d4590SKeyi Gui indexTypeValues["method-handle-ref"] = "kIndexMethodHandleRef"; 490*055d4590SKeyi Gui indexTypeValues["proto-ref"] = "kIndexProtoRef"; 491*055d4590SKeyi Gui} 492*055d4590SKeyi Gui 493*055d4590SKeyi Gui# Initialize the flags data. 494*055d4590SKeyi Guifunction initFlags() { 495*055d4590SKeyi Gui flagValues["branch"] = "kInstrCanBranch"; 496*055d4590SKeyi Gui flagValues["continue"] = "kInstrCanContinue"; 497*055d4590SKeyi Gui flagValues["switch"] = "kInstrCanSwitch"; 498*055d4590SKeyi Gui flagValues["throw"] = "kInstrCanThrow"; 499*055d4590SKeyi Gui flagValues["return"] = "kInstrCanReturn"; 500*055d4590SKeyi Gui flagValues["invoke"] = "kInstrInvoke"; 501*055d4590SKeyi Gui flagValues["optimized"] = "0"; # Not represented in C output 502*055d4590SKeyi Gui flagValues["0"] = "0"; 503*055d4590SKeyi Gui} 504*055d4590SKeyi Gui 505*055d4590SKeyi Gui# Translate the given flags into the equivalent C expression. Returns 506*055d4590SKeyi Gui# "" on error. 507*055d4590SKeyi Guifunction flagsToC(f, parts, result, i) { 508*055d4590SKeyi Gui # locals: parts, result, i 509*055d4590SKeyi Gui count = split(f, parts, /\|/); # Split input at pipe characters. 510*055d4590SKeyi Gui result = "0"; 511*055d4590SKeyi Gui 512*055d4590SKeyi Gui for (i = 1; i <= count; i++) { 513*055d4590SKeyi Gui f = flagValues[parts[i]]; 514*055d4590SKeyi Gui if (f == "") { 515*055d4590SKeyi Gui printf("bogus flag: %s\n", f) >"/dev/stderr"; 516*055d4590SKeyi Gui return ""; # Bogus flag name. 517*055d4590SKeyi Gui } else if (f == "0") { 518*055d4590SKeyi Gui # Nothing to append for this case. 519*055d4590SKeyi Gui } else if (result == "0") { 520*055d4590SKeyi Gui result = f; 521*055d4590SKeyi Gui } else { 522*055d4590SKeyi Gui result = result "|" f; 523*055d4590SKeyi Gui } 524*055d4590SKeyi Gui } 525*055d4590SKeyi Gui 526*055d4590SKeyi Gui return result; 527*055d4590SKeyi Gui} 528*055d4590SKeyi Gui 529*055d4590SKeyi Gui# Returns true if the given opcode (by index) is an "optimized" opcode. 530*055d4590SKeyi Guifunction isOptimized(idx, parts, f) { 531*055d4590SKeyi Gui # locals: parts, f 532*055d4590SKeyi Gui split(flags[idx], parts, /\|/); # Split flags[idx] at pipes. 533*055d4590SKeyi Gui for (f in parts) { 534*055d4590SKeyi Gui if (parts[f] == "optimized") return 1; 535*055d4590SKeyi Gui } 536*055d4590SKeyi Gui return 0; 537*055d4590SKeyi Gui} 538*055d4590SKeyi Gui 539*055d4590SKeyi Gui# Returns true if there is no definition for the given opcode (by index). 540*055d4590SKeyi Guifunction isUnused(idx) { 541*055d4590SKeyi Gui return (name[idx] == ""); 542*055d4590SKeyi Gui} 543