/*
* @(#)GenOpcodes.java 1.36 06/10/10
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*
*/
/*
* GenOpcodes is a program for reading the file
* src/share/javavm/include/opcodes.list and deriving from it "source"
* files for building a Java Virtual Machine and associated tools.
*
* The format of opcodes.list is explained in that
* file, which I quote here:
*
* #
* # Any line that doesn't have a-z in the 1st column is a comment.
* #
* # The first column is the name of the opcode.
* #
* # The second column is the opcode's number, or "-" to assign the
* # next available sequential number.
* #
* # The third column is the total length of the instruction. We use 0
* # for opcodes of variable length, as well as unrecognized/unused
* # opcodes.
* #
* # The fourth and fifth column give what the opcode pops off the stack, and
* # what it then pushes back onto the stack
* # - <no effect on stack>
* # I integer
* # L long integer
* # F float
* # D double float
* # A address [array or object]
* # O object only
* # R return address (for jsr)
* # a integer, array, or object
* # ? unknown
* # [I], [L], [F], [D], [A], [B], [C], [?]
* # array of integer, long, float, double, address, bytes,
* # chars, or anything
* # 1,2,3,4,+ used by stack duplicating/popping routines.
* #
* # 1,2,3,4 represent >>any<< stack type except long or double. Two numbers
* # separated by a + (in the third column) indicate that the two, together, can
* # be used for a double or long. (Or they can represent two non-long items).
* #
* # The sixth column has a comma-separated list of attributes of the
* # opcode. These are necessary in the stackmap computation dataflow
* # analysis.
* #
* # GC -- a GC point
* # CGC -- a conditional GC point; only if the thread is at a quickening point
* # BR -- a branch
* # EXC -- May throw exception
* # INV -- A method invocation
* # NFLW -- An instruction that doesn't let control flow through
* # (returns, athrow, switches, goto, ret)
* # QUICK -- A quick instruction, re-written by the interpreter.
* # RET -- A return opcode.
* # FP -- A floating point opcode
* # - -- No special attributes to speak of
* #
* # The seventh column is a "simplification" of the opcode, for opcode
* # sequence measurements (see CVM_INSTRUCTION_COUNTING in executejava.c).
* #
* # The eigth column has the attribute of CVMJITIROpcodeTag.
* # The ninth column has the attribute of type tag listed in typeid.h.
* # The tenth column has the attribute of value representing constant value,
* # local variable number, etc.
*
* The general flow of this program is:
* - parse command-line arguments and instantiate output file writers
* - read input file. For each non-commentary line of input
* - parse the line into words
* - create an Opcode with the line's information and save it
* in an ordered list of Opcodes.
* - call each writer to write the Opcodes to its file.
*
* The output file writers are all implementations of interface FileGenerator.
* Most of them subclass FileGenOpcodeWriter, which contains some useful
* methods and fields. Their names are all of the form XXXGenOpcodeWriter,
* and they are instantiated when the command-line argument -XXX is
* seen. Adding another one is easy by following the pattern. Just don't forget
* to update the usage message as well!
*
* One special note on output file writing: all the output file writers I provide
* use util.FileCompare.ConditionalCopy to avoid touching derived files that
* are unchanged. This is intended to avoid re-compiling due to extraneous
* file date changes when you are using make/gnumake/something-like-make.
* You may or may not desire this behavior.
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.StringTokenizer;
import util.BufferedPrintStream;
class GenOpcodes
{
private static final String[] _usage = {
"usage: java GenOpcodes input_file_name [ opt target_file_name ]+",
" where opt is a flavor of output file. Choices are:",
" -h - C header file, generally opcodes.h",
" -c - C file containing CVMopnames",
" -bcAttr - C file containing CVMbcAttributes",
" -opcodeMap - C file containing CVMJITOpcodeMap",
" -opcodeLengths - C file containing CVMopcodeLengths",
" -simplification - C file containing CVMopcodeSimplification",
" -label - #defines for use in executejava label array",
" -javaConst - Java class OpcodeConst"
};
private static String _inFileName;
private static FileGenerator[] _fileGenerators;
/*
* Main entry point. If there are too few arguments, print a
* usage message. Otherwise, parse the arguments. If successful,
* process the input file. Return status appropriately.
*/
public static void main(String[] args) {
processArgs(args);
try {
// Read in the opcodes.
Opcode[] opcodes = readOpcodes(_inFileName);
// Run each generator.
for (int i = 0; i < _fileGenerators.length; i++) {
_fileGenerators[i].processOpcodes(opcodes);
}
System.exit(0);
} catch (GenOpcodesException ex) {
System.err.println("GenOpcodes: " + ex.getMessage());
ex.printStackTrace(System.err);
System.exit(1);
}
}
private static void printUsage() {
for (int i = 0; i < _usage.length; i++) {
System.err.println(_usage[i]);
}
}
/*
* Parse command-line arguments.
* Instantiate output writers and init them.
*/
private static void processArgs(String[] args) {
/* The first argument is the incoming opcodes definition file
(required). Subsequent arguments are {-<output file type>
<output file name>} pairs where at least one pair is
specified. So we expect at least three arguments, and the
number of arguments must not be even. */
if (args.length < 3 || (args.length % 2) == 0) {
printUsage();
System.exit(1);
}
_inFileName = args[0];
if (_inFileName.length() == 0 || _inFileName.charAt(0) == '-') {
System.err.println("Warning: treating \"" + _inFileName +
"\" as a file name");
}
_fileGenerators = new FileGenerator[args.length / 2];
for (int i = 1; i < args.length; i += 2) {
String arg = args[i];
if (arg.charAt(0) != '-') {
System.err.println("Command line argument \"" + arg +
"\" unexpected");
printUsage();
System.exit(1);
}
// The name of the output writer class we are going to
// instantiate is the option name (without leading -)
// capitalized and concatenated with "GenOpcodeWriter".
// It is also an inner class of GenOpcodes.
// Thus the option "-c" causes us to instantiate a
// "GenOpcodes$CGenOpcodeWriter".
String fileGeneratorName = "GenOpcodes$" +
Character.toUpperCase(arg.charAt(1)) + arg.substring(2) +
"GenOpcodeWriter";
Class fileGeneratorClass;
try {
fileGeneratorClass = Class.forName(fileGeneratorName);
} catch (ClassNotFoundException ex) {
System.err.println("\"" + arg + "\" not supported:\n" + ex);
printUsage();
System.exit(1);
return;
}
FileGenerator fileGenerator;
try {
fileGenerator =
(FileGenerator) fileGeneratorClass.newInstance();
} catch (InstantiationException ex) {
System.err.println("Error instantiating " + fileGeneratorName +
":\n" + ex);
printUsage();
System.exit(1);
return;
} catch (IllegalAccessException ex) {
System.err.println("Error instantiating " + fileGeneratorName +
":\n" + ex);
printUsage();
System.exit(1);
return;
}
fileGenerator.init(args[i + 1]);
_fileGenerators[i / 2] = fileGenerator;
}
}
/*
* Reads in all the opcodes and returns an array of 256 Opcodes.
* Array elements with no assigned Opcode will be null.
*/
private static Opcode[] readOpcodes(String filename)
throws GenOpcodesException {
Opcode[] opcodes = new Opcode[256];
int nextOpcodeNo = 0;
BufferedReader in;
try {
in = new BufferedReader(new FileReader(filename));
} catch (FileNotFoundException ex) {
throw new GenOpcodesException(
"Error opening " + filename + ".", ex);
}
while (true) {
String line;
try {
line = in.readLine();
} catch (IOException ex) {
throw new GenOpcodesException(
"Error reading " + filename + ".", ex);
}
if (line == null) {
// EOF.
break;
}
// Skip comments and blank lines.
if (line.length() == 0 || !Character.isLetter(line.charAt(0))) {
continue;
}
// Extract the fields.
StringTokenizer st = new StringTokenizer(line);
String name = st.nextToken();
String number = st.nextToken();
String length = st.nextToken();
st.nextToken(); // pops
st.nextToken(); // pushes
String[] attributes = parseAttributes(st.nextToken());
String simplification = st.nextToken();
String tag = st.nextToken();
String typeid = st.nextToken();
String value = st.nextToken();
// Advance to the next unused opcode number.
while (opcodes[nextOpcodeNo] != null) {
nextOpcodeNo++;
}
// If an opcode number is given then use it, else use
// the next available opcode number.
int opcodeNo;
boolean assigned;
if (number.equals("-")) {
if (nextOpcodeNo > 253) {
throw new GenOpcodesException(
"Too many opcodes (> 253).");
}
opcodeNo = nextOpcodeNo;
assigned = false;
} else {
try {
opcodeNo = Integer.parseInt(number);
} catch (NumberFormatException ex) {
throw new GenOpcodesException(
"Bad opcode number " + number +
" for opcode " + name, ex);
}
if (opcodeNo < 0 || opcodeNo > 253) {
throw new GenOpcodesException(
"Opcode number " + number +
" for opcode " + name +
" must be in the range 0 - 253");
}
assigned = true;
// If opcodeNo is in use by another Opcode then move
// it out of the way, unless it was explicitly
// assigned.
Opcode opcode = opcodes[opcodeNo];
if (opcode != null) {
if (opcode.isAssigned()) {
throw new GenOpcodesException(
"Opcode number " + opcodeNo +
" has already been assigned.");
}
if (nextOpcodeNo > 253) {
throw new GenOpcodesException(
"Too many opcodes (> 253).");
}
opcodes[nextOpcodeNo] = opcode;
}
}
opcodes[opcodeNo] = new Opcode(
assigned,
name,
length,
attributes,
simplification,
tag,
typeid,
value);
}
return opcodes;
}
/*
* Converts a comma-separated list of attributes to a String[] of
* attributes.
*/
private static String[] parseAttributes(String attributes) {
StringTokenizer st = new StringTokenizer(attributes, ",");
String[] result = new String[st.countTokens()];
for (int i = 0; i < result.length; i++) {
result[i] = st.nextToken();
}
return result;
}
/*
* FileGenerator is the interface between the GenOpcode driver and
* the individual output writers.
*/
private interface FileGenerator
{
/*
* init is called immediately after instantiation, with the
* file name command-line argument. Do not open the file yet!
* If any other error occurs during command-line processing,
* the program will exit without further ado.
*/
public void init(String fileName);
/*
* Processes and writes all the opcodes.
*/
public void processOpcodes(Opcode[] opcodes)
throws GenOpcodesException;
}
/*
* FileGenOpcodeWriter is used to implement common functions
* in most (or all) of the output writers. It does file opening
* and closing, temporary file management and conditional copying.
*/
private static abstract class FileGenOpcodeWriter implements FileGenerator
{
private final String[] _prolog;
private final String[] _epilog;
private String _destFileName;
private File _destFile; // Actual file to create.
private File _outFile; // Temporary file to write to.
private PrintStream _out;
protected FileGenOpcodeWriter(String[] prolog, String[] epilog) {
_prolog = prolog;
_epilog = epilog;
}
/*
* This init method just saves the file name.
*/
public void init(String destFileName) {
_destFileName = destFileName;
}
public void processOpcodes(Opcode[] opcodes)
throws GenOpcodesException {
start();
processAllOpcodes(opcodes);
done();
}
/**
* Processes all opcodes. Subclasses may override this.
*/
protected void processAllOpcodes(Opcode[] opcodes) {
for (int i = 0; i < opcodes.length; i++) {
processOneOpcode(i, opcodes[i]);
}
}
/**
* Processes one opcode. This is what subclasses will usually
* need to override.
*/
protected void processOneOpcode(int ordinal, Opcode opcode) {}
private void start() throws GenOpcodesException {
openFile();
printBlock(_prolog);
}
private void openFile() throws GenOpcodesException {
_destFile = new File(_destFileName);
if (_destFile.exists()) {
_outFile = new File(_destFileName + ".TMP");
} else {
_outFile = _destFile;
}
try {
_out = new BufferedPrintStream(new FileOutputStream(_outFile));
} catch (IOException ex) {
throw new GenOpcodesException(
"Could not open output file " + _outFile, ex);
}
}
private void done() {
printBlock(_epilog);
closeFile();
}
/*
* Close output stream, do conditional copy to final
* destination if the output file isn't the destination file.
*/
private void closeFile() {
_out.close();
if (_destFile != _outFile) {
util.FileCompare.conditionalCopy(_outFile, _destFile);
_outFile.delete();
}
}
/*
* Prints a String[], a common operation when writing
* file prolog/epilog.
*/
private void printBlock(String[] block) {
for (int i = 0; i < block.length; i++) {
_out.println(block[i]);
}
}
protected void print(String s) {
_out.print(s);
}
protected void println(String s) {
_out.println(s);
}
}
/*
* The C-header file contains enum CVMOpcode of all the opc_XXX names
* along with an extern declaration of the CVMopnames array, which is
* created in CGenOpcodeWriter.
*/
private static class HGenOpcodeWriter extends FileGenOpcodeWriter
{
private static final String[] _prolog = {
"/*",
" * This file contains the constants for all the opcodes.",
" * It is generated from opcodes.list.",
" */",
"",
"#ifndef _INCLUDED_GEN_OPCODES_H",
"#define _INCLUDED_GEN_OPCODES_H",
"",
"#include \"javavm/include/defs.h\"",
"",
"enum CVMOpcode {",
};
private static final String[] _epilog = {
"\n};",
"",
"#endif /* _INCLUDED_GEN_OPCODES_H */",
};
public HGenOpcodeWriter() {
super(_prolog, _epilog);
}
public void processOneOpcode(int ordinal, Opcode opcode) {
if (opcode == null) {
return;
}
if (ordinal > 0) {
print(",\n");
}
print(" opc_");
print(opcode.getName());
print(" = ");
print(Integer.toString(ordinal));
}
}
/*
* The C-file contains const char * CVMopnames[256].
* This is initialized with quoted-string forms of all the opcode names.
* Otherwise undefined elements are filled with "??"opcodeNumber
*/
private static class CGenOpcodeWriter extends FileGenOpcodeWriter
{
private static final String[] _prolog = {
"/*",
" * This file contains an array of opcode names.",
" * It is generated from opcodes.list.",
" */",
"",
"#include \"javavm/include/opcodes.h\"",
"",
"#if defined(CVM_TRACE) || defined(CVM_DEBUG) || defined(CVM_INSTRUCTION_COUNTING)",
"const char* const CVMopnames[256] = {",
};
private static final String[] _epilog = {
" \"software\",",
" \"hardware\"",
"};",
"",
"#endif",
};
public CGenOpcodeWriter() {
super(_prolog, _epilog);
}
public void processOneOpcode(int ordinal, Opcode opcode) {
if (ordinal < 254) {
print(" \"");
print(opcode != null ? opcode.getName() : ("??" + ordinal));
println("\",");
}
}
}
/*
* The C-file contains const char CVMbcAttributes[256].
* This is initialized with bitmaps indicating opcode attributes.
*/
private static class BcAttrGenOpcodeWriter extends FileGenOpcodeWriter
{
private static final String gcpointAttr = "CVM_BC_ATT_GCPOINT";
private static final String condGcpointAttr= "CVM_BC_ATT_COND_GCPOINT";
private static final String branchAttr = "CVM_BC_ATT_BRANCH";
private static final String excAttr = "CVM_BC_ATT_THROWSEXCEPTION";
private static final String noflowAttr = "CVM_BC_ATT_NOCONTROLFLOW";
private static final String invocationAttr = "CVM_BC_ATT_INVOCATION";
private static final String quickAttr = "CVM_BC_ATT_QUICK";
private static final String returnAttr = "CVM_BC_ATT_RETURN";
private static final String fpAttr = "CVM_BC_ATT_FP";
private static final String[] _prolog = {
"/*",
" * This file contains an array of byte-code attributes.",
" * It is generated from opcodes.list.",
" */",
"",
"#include \"javavm/include/defs.h\"",
"#include \"javavm/include/bcattr.h\"",
"",
"const CVMUint16 CVMbcAttributes[256] = {",
};
private static final String[] _epilog = {
"};",
};
public BcAttrGenOpcodeWriter() {
super(_prolog, _epilog);
}
public void processOneOpcode(int ordinal, Opcode opcode) {
if (opcode != null) {
println(" /* opc_" + opcode.getName() + " */");
print(" ");
String[] attributes = opcode.getAttributes();
for (int i = 0; i < attributes.length; i++) {
if (i > 0) {
print(" | ");
}
doOneAttribute(attributes[i]);
}
println(",");
} else {
println(" 0,");
}
}
private void doOneAttribute(String attrName) {
if (attrName.equals("BR")) {
print(branchAttr);
} else if (attrName.equals("GC")) {
print(gcpointAttr);
} else if (attrName.equals("CGC")) {
print(condGcpointAttr);
} else if (attrName.equals("EXC")) {
print(excAttr);
} else if (attrName.equals("NFLW")) {
print(noflowAttr);
} else if (attrName.equals("INV")) {
print(invocationAttr);
} else if (attrName.equals("QUICK")) {
print(quickAttr);
} else if (attrName.equals("RET")) {
print(returnAttr);
} else if (attrName.equals("FP")) {
print(fpAttr);
} else {
/*
* Covers the case of '-' as well as unknown attributes
*/
print("0");
}
}
}
/*
* The C file contains CVMJITOpcodeMap[].
*/
private static class OpcodeMapGenOpcodeWriter extends FileGenOpcodeWriter
{
private static final String[] _prolog = {
"/*",
" * This file contains an array of opcode maps.",
" * It is generated from opcodes.list.",
" */",
"",
"#include \"javavm/include/jit/jitirnode.h\"",
"#include \"javavm/include/typeid.h\"",
"#include \"javavm/include/opcodes.h\"",
"",
"const signed char CVMJITOpcodeMap[256][3] = {",
};
private static final String[] _epilog = {
"};",
};
public OpcodeMapGenOpcodeWriter() {
super(_prolog, _epilog);
}
public void processOneOpcode(int ordinal, Opcode opcode) {
if (opcode != null) {
print("{ " + opcode.getTag());
print(", " + opcode.getTypeid());
print(", " + opcode.getValue());
println("}, /* opc_" + opcode.getName() + " */");
} else {
println("{0, 0, 0},");
}
}
}
/*
* The C-file contains const char CVMopcodeLengths[256] (lengths for all fixed
* size opcodes).
*/
private static class OpcodeLengthsGenOpcodeWriter
extends FileGenOpcodeWriter
{
private static final String[] _prolog = {
"/*",
" * This file contains an array of opcode lengths.",
" * It is generated from opcodes.list.",
" * 0-length means the opcode is variable length or unrecognized.",
" */",
"",
"#include \"javavm/include/opcodes.h\"",
"",
"const char CVMopcodeLengths[256] = {",
};
private static final String[] _epilog = {
"};",
};
public OpcodeLengthsGenOpcodeWriter() {
super(_prolog, _epilog);
}
public void processOneOpcode(int ordinal, Opcode opcode) {
if (opcode != null) {
print(" " + opcode.getLength());
println(", /* opc_" + opcode.getName() + " */");
} else {
println(" 0,");
}
}
}
private static class SimplificationGenOpcodeWriter
extends FileGenOpcodeWriter
{
private static final String[] _prolog = {
"/*",
" * This file contains an array of opcode \"simplifications\".",
" * It is generated from opcodes.list.",
" */",
"",
"#include \"javavm/include/opcodes.h\"",
"",
"static const CVMOpcode CVMopcodeSimplification[256] = {",
};
private static final String[] _epilog = {
"};",
};
public SimplificationGenOpcodeWriter() {
super(_prolog, _epilog);
}
public void processOneOpcode(int ordinal, Opcode opcode) {
if (opcode != null) {
print(" opc_" + opcode.getSimplification());
println(", /* opc_" + opcode.getName() + " */");
} else {
println(" 0,");
}
}
}
/*
* The label file is interesting only if you're using gcc or equivalent
* to compiler executejava.c, and are using gcc's labels. This generates
* a set of cpp defines such as this one, to map specific opcode numbers
* to specific semantics:
* #define opc_0 opc_nop
* which indicates that the 0th entry in the label table needs to point to
* the code to implement the Java nop. All undefined opcode numbers are
* defined as opc_DEFAULT
*/
private static class LabelGenOpcodeWriter extends FileGenOpcodeWriter
{
private static final String[] _prolog = {
"/*",
" * This file contains label equates",
" * It is generated from opcodes.list.",
" * It is for use by executejava.c using gcc label arrays.",
" */",
"",
"#ifndef _INCLUDED_OPCODE_LABELS",
"#define _INCLUDED_OPCODE_LABELS",
"",
};
private static final String[] _epilog = {
"",
"#endif",
};
public LabelGenOpcodeWriter() {
super(_prolog, _epilog);
}
public void processOneOpcode(int ordinal, Opcode opcode) {
print( "#define opc_");
print(Integer.toString(ordinal));
print( "\topc_");
println(opcode != null ? opcode.getName() : "DEFAULT");
}
}
/*
* This generates the Java interface OpcodeConst, which contains:
* - constants such as
* public static final int opc_nop = 0;
* for all the defined opcode values.
* - the array of opcode name strings:
* public static final String opcNames[] =
* - the array of instruction lengths:
* public static final int opcLengths[] =
*
* Formerly, the constants, names, and lengths of the real, red-book
* opcodes were imported from somewhere in the compiler and the quick
* information was separately, privately maintained in JavaCodeCompact.
* Now they are all unified in this one, VM-dependent, derived file.
*/
private static class JavaConstGenOpcodeWriter extends FileGenOpcodeWriter {
private static final String[] _prolog = {
"/*",
" * This interface contains opc_ constant values,",
" * a table of opcode names, and a table of instruction lengths.",
" * It is generated from opcodes.list.",
" * It is vm dependent, because it includes the quick opcodes.",
" */",
"package opcodeconsts;",
"public interface OpcodeConst",
"{",
};
private static final String _epilog[] = {
"}",
};
public JavaConstGenOpcodeWriter() {
super(_prolog, _epilog);
}
public void processAllOpcodes(Opcode[] opcodes) {
printConstants(opcodes);
print("\n");
printNames(opcodes);
print("\n");
printSizes(opcodes);
}
private void printConstants(Opcode[] opcodes) {
for (int i = 0; i < opcodes.length; i++) {
Opcode opcode = opcodes[i];
if (opcode != null) {
print(" public static final int opc_");
print(opcode.getName());
print("\t= ");
print(Integer.toString(i));
println(";");
}
}
}
private void printNames(Opcode[] opcodes) {
print(" public static final String[] opcNames = {");
for (int i = 0; i < opcodes.length; i++) {
Opcode opcode = opcodes[i];
String name;
if (opcode != null) {
name = opcode.getName();
} else if (i == 254) {
name = "hardware";
} else if (i == 255) {
name = "software";
} else {
name = "??" + i;
}
if ((i % 4) == 0) {
print("\n\t\"");
} else {
print(" \"");
}
print(name);
print("\",");
}
println("\n };");
}
private void printSizes(Opcode[] opcodes) {
print(" public static final int[] opcLengths = {");
for (int i = 0; i < opcodes.length; i++) {
Opcode opcode = opcodes[i];
if ((i % 10) == 0) {
print("\n\t");
} else {
print(" ");
}
print(opcode != null ? opcode.getLength() : "0");
print(",");
}
println("\n };");
}
}
private static class Opcode
{
private final boolean _assigned;
private final String _name;
private final String _length;
private final String[] _attributes;
private final String _simplification;
private final String _tag;
private final String _typeid;
private final String _value;
public Opcode(
boolean assigned, String name, String length,
String[] attributes, String simplification,
String tag, String typeid, String value) {
_assigned = assigned;
_name = name;
_length = length;
_attributes = attributes;
_simplification = simplification;
_tag = tag;
_typeid = typeid;
_value = value;
}
public boolean isAssigned() {
return _assigned;
}
public String getName() {
return _name;
}
public String getLength() {
return _length;
}
public String[] getAttributes() {
return _attributes;
}
public String getSimplification() {
return _simplification;
}
public String getTag() {
return _tag;
}
public String getTypeid() {
return _typeid;
}
public String getValue() {
return _value;
}
}
private static class GenOpcodesException extends Exception
{
public GenOpcodesException(String message, Throwable cause) {
super(message, cause);
}
public GenOpcodesException(String message) {
super(message);
}
}
}