blob: c6a0aa7982ceaf055e3e0d380030a82c5e51335b [file] [log] [blame]
/*
* Copyright (C) 2008 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 dasm;
import com.android.dx.dex.code.Dop;
import com.android.dx.dex.code.Dops;
import com.android.dx.dex.code.InsnFormat;
import com.android.dx.dex.code.form.Form10t;
import com.android.dx.dex.code.form.Form10x;
import com.android.dx.dex.code.form.Form11n;
import com.android.dx.dex.code.form.Form11x;
import com.android.dx.dex.code.form.Form12x;
import com.android.dx.dex.code.form.Form20t;
import com.android.dx.dex.code.form.Form21c;
import com.android.dx.dex.code.form.Form21h;
import com.android.dx.dex.code.form.Form21s;
import com.android.dx.dex.code.form.Form21t;
import com.android.dx.dex.code.form.Form22b;
import com.android.dx.dex.code.form.Form22c;
import com.android.dx.dex.code.form.Form22s;
import com.android.dx.dex.code.form.Form22t;
import com.android.dx.dex.code.form.Form22x;
import com.android.dx.dex.code.form.Form23x;
import com.android.dx.dex.code.form.Form30t;
import com.android.dx.dex.code.form.Form31c;
import com.android.dx.dex.code.form.Form31i;
import com.android.dx.dex.code.form.Form31t;
import com.android.dx.dex.code.form.Form32x;
import com.android.dx.dex.code.form.Form35c;
import com.android.dx.dex.code.form.Form3rc;
import com.android.dx.dex.code.form.Form51l;
import com.android.dx.io.Opcodes;
import java.util.Hashtable;
/**
* Holds information about Dalvik opcodes and its parameters.
*/
class DopInfo {
// maps instruction name -> DopInfo object
static Hashtable<String, DopInfo> dopsTable;
// information maintained about each instruction:
public String name; // opcode name
public Dop opcode; // its opcode
public String args; // the argument code
public final static String ARG_REGISTER = "R";
public final static String ARG_TYPE = "T";
public final static String ARG_LITERAL = "I";
public final static String ARG_ADDRESS = "A";
public final static String ARG_FIELD = "F";
public final static String ARG_METHOD = "M";
public final static String ARG_INTFMETHOD = "Y";
public final static String ARG_STRING = "S";
public final static String ARG_REGLIST = "Z";
public final static String ARG_REGRANGE = "G";
/**
* define type of parameters each instruction has
*/
public final static String ARG_REG_REG = ARG_REGISTER + ARG_REGISTER;
public final static String ARG_REG_REG_REG = ARG_REGISTER + ARG_REGISTER
+ ARG_REGISTER;
public final static String ARG_REG_LITERAL = ARG_REGISTER + ARG_LITERAL;
public final static String ARG_REG_REG_LITERAL = ARG_REGISTER
+ ARG_REGISTER + ARG_LITERAL;
public final static String ARG_REG_ADDRESS = ARG_REGISTER + ARG_ADDRESS;
public final static String ARG_REG_REG_ADDRESS = ARG_REGISTER
+ ARG_REGISTER + ARG_ADDRESS;
public final static String ARG_REG_TYPE = ARG_REGISTER + ARG_TYPE;
public final static String ARG_REG_REG_TYPE = ARG_REGISTER + ARG_REGISTER
+ ARG_TYPE;
public final static String ARG_REG_FIELD = ARG_REGISTER + ARG_FIELD;
public final static String ARG_REG_REG_FIELD = ARG_REGISTER + ARG_REGISTER
+ ARG_FIELD;
public final static String ARG_REG_STRING = ARG_REGISTER + ARG_STRING;
public final static String ARG_REG_REG_STRING = ARG_REGISTER + ARG_REGISTER
+ ARG_STRING;
public final static String ARG_REGLIST_TYPE = ARG_REGLIST + ARG_TYPE;
public final static String ARG_REGLIST_METHOD = ARG_REGLIST + ARG_METHOD;
public final static String ARG_REGLIST_INTFMETHOD = ARG_REGLIST
+ ARG_INTFMETHOD;
public final static String ARG_REGRANGE_TYPE = ARG_REGRANGE + ARG_TYPE;
public final static String ARG_REGRANGE_METHOD = ARG_REGRANGE + ARG_METHOD;
public final static String ARG_REGRANGE_INTFMETHOD = ARG_REGRANGE
+ ARG_INTFMETHOD;
public static DopInfo get(String name) {
return (DopInfo) dopsTable.get(name);
}
public static boolean contains(String name) {
return dopsTable.get(name) != null;
}
/**
* Adds new opcode to table
*/
static private void add(String name, Dop opcode, String args) {
DopInfo info = new DopInfo();
info.name = name;
info.opcode = opcode;
info.args = args;
dopsTable.put(name, info);
}
static private String getArgsFormat(Dop dop) {
InsnFormat format = dop.getFormat();
if (format instanceof Form10x) return "";
if (format instanceof Form12x) return ARG_REG_REG;
if (format instanceof Form11n) return ARG_REG_LITERAL;
if (format instanceof Form11x) return ARG_REGISTER;
if (format instanceof Form10t || format instanceof Form20t)
return ARG_ADDRESS;
if (format instanceof Form22x) return ARG_REG_REG;
if (format instanceof Form21t) return ARG_REG_ADDRESS;
if (format instanceof Form21s) return ARG_REG_LITERAL;
if (format instanceof Form21h) return ARG_REG_LITERAL;
if (format instanceof Form21c) {
switch (dop.getOpcode()) {
case Opcodes.CONST_CLASS:
case Opcodes.CHECK_CAST:
case Opcodes.NEW_INSTANCE:
return ARG_REG_TYPE;
case Opcodes.SGET:
case Opcodes.SGET_WIDE:
case Opcodes.SGET_OBJECT:
case Opcodes.SGET_BOOLEAN:
case Opcodes.SGET_BYTE:
case Opcodes.SGET_CHAR:
case Opcodes.SGET_SHORT:
case Opcodes.SPUT:
case Opcodes.SPUT_WIDE:
case Opcodes.SPUT_OBJECT:
case Opcodes.SPUT_BOOLEAN:
case Opcodes.SPUT_BYTE:
case Opcodes.SPUT_CHAR:
case Opcodes.SPUT_SHORT:
return ARG_REG_FIELD;
default:
return ARG_REG_STRING;
}
}
if (format instanceof Form23x) return ARG_REG_REG_REG;
if (format instanceof Form22b) return ARG_REG_REG_LITERAL;
if (format instanceof Form22t) return ARG_REG_REG_ADDRESS;
if (format instanceof Form22s) return ARG_REG_REG_LITERAL;
if (format instanceof Form22c) {
switch (dop.getOpcode()) {
case Opcodes.INSTANCE_OF:
case Opcodes.NEW_ARRAY:
return ARG_REG_REG_TYPE;
case Opcodes.IGET:
case Opcodes.IGET_WIDE:
case Opcodes.IGET_OBJECT:
case Opcodes.IGET_BOOLEAN:
case Opcodes.IGET_BYTE:
case Opcodes.IGET_CHAR:
case Opcodes.IGET_SHORT:
case Opcodes.IPUT:
case Opcodes.IPUT_WIDE:
case Opcodes.IPUT_OBJECT:
case Opcodes.IPUT_BOOLEAN:
case Opcodes.IPUT_BYTE:
case Opcodes.IPUT_CHAR:
case Opcodes.IPUT_SHORT:
return ARG_REG_REG_FIELD;
default:
return ARG_REG_REG_STRING;
}
}
if (format instanceof Form30t) return ARG_ADDRESS;
if (format instanceof Form32x) return ARG_REG_REG;
if (format instanceof Form31i) return ARG_REG_LITERAL;
if (format instanceof Form31t) return ARG_REG_ADDRESS;
if (format instanceof Form31c) return ARG_REG_STRING;
if (format instanceof Form35c) {
switch (dop.getOpcode()) {
case Opcodes.INVOKE_VIRTUAL:
case Opcodes.INVOKE_SUPER:
case Opcodes.INVOKE_DIRECT:
case Opcodes.INVOKE_STATIC:
return ARG_REGLIST_METHOD;
case Opcodes.INVOKE_INTERFACE:
return ARG_REGLIST_INTFMETHOD;
default:
return ARG_REGLIST_TYPE;
}
}
if (format instanceof Form3rc) {
switch (dop.getOpcode()) {
case Opcodes.FILLED_NEW_ARRAY_RANGE:
return ARG_REGRANGE_TYPE;
case Opcodes.INVOKE_INTERFACE_RANGE:
return ARG_REGRANGE_INTFMETHOD;
default:
return ARG_REGRANGE_METHOD;
}
}
if (format instanceof Form51l) return ARG_REG_LITERAL; // not "RL" since
// it is
// processed as
// Number
return "";
}
/**
* dopsTable initialization
*/
static {
dopsTable = new Hashtable<String, DopInfo>();
for (int i = 0; i < Opcodes.MAX_VALUE - Opcodes.MIN_VALUE + 1; i++) {
try {
Dop dop = Dops.get(i);
add(dop.getName(), dop, getArgsFormat(dop));
} catch (Exception e) {
}
}
}
};