#Copyright Massachusetts Institute of technology, 2002.
#Written by Eric Prud'hommeaux for the World Wide Web Consortium

use strict;
require Exporter;
#require AutoLoader;

$W3C::JVM::JVM::REVISION = '$Id: Instruction.pm,v 1.17 2003/03/24 14:13:56 eric Exp $ ';

package W3C::JVM::Instruction;
use vars qw(@ISA @TODO @EXPORT_OK $VERSION $DSLI);
@ISA = qw(Exporter); # AutoLoader);
@TODO = qw();
@EXPORT_OK = qw($InstructionTable);
$VERSION = 0.0;
$DSLI = 'adpO';

use W3C::Util::Exception;
use W3C::JVM::UninitializedObject;

# Contrary to my standard approach, W3C::JVM::Instruction objects are
# implemented as ARRAY refs for ease and brevity of initialization.
# These are the element offsets for the array members:
use vars qw($InstructionTable $OPCODE $INSTRUCTION $PARMS $ARGS $RESULTS $DESC $TIME $INTERP $COMPILE $EXTRA2 $THINGY1 $THINGY2);
($OPCODE, $INSTRUCTION, $PARMS, $ARGS, $RESULTS, $DESC, $TIME, $INTERP, $COMPILE, $EXTRA2) = (0..9);

# Following is an array of W3C::JVM::Instruction objects, all of which
# will be initialized at the end of the initializer:
$InstructionTable = [

#[Code, 'Instruction', [qw(Stack arguments)], [qw(Stack results)], 'Brief description', Cycle, 
# "code;
#code;", $THINGY1, $THINGY2], 

[0, 'nop', [qw()], [qw(...)], [qw(...)], 'do nothing', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[1, 'aconst', [qw()], [qw(...)], [qw(... null)], 'push null', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[2, 'iconst', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[3, 'iconst_0', [qw()], [qw(...)], [qw(... 0)], 'push int constant 0', 1, 
 'push (@$stack, 0);
1;', 'push (@$stack, "0"); "";', $THINGY2], 
[4, 'iconst_1', [qw()], [qw(...)], [qw(... 1)], 'push int constant 1', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[5, 'iconst_2', [qw()], [qw(...)], [qw(... 2)], 'push int constant 2', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[6, 'iconst_3', [qw()], [qw(...)], [qw(... 3)], 'push int constant 3', 1, 
 'push (@$stack, 3);
1;', 'push (@$stack, 3); "";', $THINGY2], 
[7, 'iconst_4', [qw()], [qw(...)], [qw(... 4)], 'push int constant 4', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[8, 'iconst_5', [qw()], [qw(...)], [qw(... 5)], 'push int constant 5', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[9, 'lconst', [qw()], [qw(...)], [qw(... word1 word2)], 'load long constant 0', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[10, 'lconst', [qw()], [qw(...)], [qw(... word1 word3)], 'load long constant 1', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[11, 'fconst', [qw()], [qw(...)], [qw(... 0.0)], 'push float constant', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[12, 'fconst', [qw()], [qw(...)], [qw(... 1.0)], 'push float constant', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[13, 'fconst', [qw()], [qw(...)], [qw(... 2.0)], 'push float constant', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[14, 'dconst', [qw()], [qw(...)], [qw(... word1 word2)], 'push double', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[15, 'dconst', [qw()], [qw(...)], [qw(... word1 word3)], 'push double', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[16, 'bipush', [qw(1Int)], [qw(...)], [qw(... value)], 'push byte', 1, 
 'push (@$stack, $parms->[0]);
1;', 'push (@$stack, $parms->[0]); "";', $THINGY2], 
#[17, 'sipush', [qw()], [qw(...)], [qw(... value)], 'push short', 1, 
# "code;
#code;", $THINGY1, $THINGY2], 
[17, 'iconst_3', [qw(2Const)], [qw(...)], [qw(... value)], 'push short', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[18, 'ldc', [qw(1ConstW)], [qw(...)], [qw(... item)], 'push item from constant pool', 1, 
 'push(@$stack, $parms->[0]);
1;', 'push(@$stack, $parms->[0]); "";', $THINGY2], 
[19, 'ldc_w', [qw(2ConstDW)], [qw(...)], [qw(... item)], 'push item from constant pool', 1, 
 'push(@$stack, $parms->[0]);
1;', $THINGY1, $THINGY2], 
[20, 'ldc2_w', [qw(2ConstDW)], [qw(...)], [qw(... item.word1 item.word2)], 'push item from constant pool', 1, 
 'push(@$stack, $parms->[0]);
1;', $THINGY1, $THINGY2], 
[21, 'iload', [qw()], [qw(...)], [qw(... value)], 'load int from a local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[22, 'lload', [qw()], [qw(...)], [qw(... word1 word2)], 'load long from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[23, 'fload', [qw()], [qw(...)], [qw(... value)], 'load float from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[24, 'dload', [qw()], [qw(...)], [qw(... word1 word2)], 'load double from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[25, 'aload', [qw()], [qw(...)], [qw(... objectref)], 'load reference from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[26, 'iload', [qw()], [qw(...)], [qw(... value)], 'load int from a local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[27, 'iload_1', [qw()], [qw(...)], [qw(... value)], 'load int from a local variable', 1, 
 'push(@$stack, $vars->[1]);
1;', 'push(@$stack, "\$vars->[1]"); "";', $THINGY2], 
[28, 'iload', [qw()], [qw(...)], [qw(... value)], 'load int from a local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[29, 'iload', [qw()], [qw(...)], [qw(... value)], 'load int from a local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[30, 'lload', [qw()], [qw(...)], [qw(... word1 word3)], 'load long from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[31, 'lload', [qw()], [qw(...)], [qw(... word1 word4)], 'load long from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[32, 'lload', [qw()], [qw(...)], [qw(... word1 word5)], 'load long from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[33, 'lload', [qw()], [qw(...)], [qw(... word1 word6)], 'load long from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[34, 'fload', [qw()], [qw(...)], [qw(... value)], 'load float from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[35, 'fload', [qw()], [qw(...)], [qw(... value)], 'load float from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[36, 'fload', [qw()], [qw(...)], [qw(... value)], 'load float from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[37, 'fload', [qw()], [qw(...)], [qw(... value)], 'load float from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[38, 'dload', [qw()], [qw(...)], [qw(... word1 word2)], 'load double from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[39, 'dload', [qw()], [qw(...)], [qw(... word1 word2)], 'load double from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[40, 'dload', [qw()], [qw(...)], [qw(... word1 word2)], 'load double from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[41, 'dload', [qw()], [qw(...)], [qw(... word1 word2)], 'load double from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[42, 'aload_0', [qw()], [qw(...)], [qw(... objectref)], 'load reference from local variable', 1, 
 'push (@$stack, $vars->[0]);
;', 'push (@$stack, "\$vars->[0]"); ""', $THINGY2], 
[43, 'aload_1', [qw()], [qw(...)], [qw(... objectref)], 'load reference from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[44, 'aload_2', [qw()], [qw(...)], [qw(... objectref)], 'load reference from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[45, 'aload_3', [qw()], [qw(...)], [qw(... objectref)], 'load reference from local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[46, 'iaload', [qw()], [qw(... arrayref index)], [qw(... value)], 'load int from array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[47, 'laload', [qw()], [qw(... arrayref index)], [qw(... word1 word2)], 'load long from array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[48, 'faload', [qw()], [qw(... arrayref index)], [qw(... value)], 'load float from array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[49, 'daload', [qw()], [qw(... arrayref index)], [qw(... word1 word2)], 'load double from array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[50, 'aaload', [qw()], [qw(... arrayref index)], [qw(... value)], 'load a reference from array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[51, 'baload', [qw()], [qw(... arrayref index)], [qw(... value)], 'load byte or boolean from array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[52, 'caload', [qw()], [qw(... arrayref index)], [qw(... value)], 'load char from array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[53, 'saload', [qw()], [qw(... arrayref index)], [qw(... value)], 'load short from array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[54, 'istore', [qw()], [qw(... value)], [qw(...)], 'store int into local variable', 1, 
 '$vars->[1] = pop (@$stack);
1;', $THINGY1, $THINGY2], 
[55, 'lstore', [qw()], [qw(... word1 word2)], [qw(...)], 'store long into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[56, 'fstore', [qw()], [qw(... value)], [qw(...)], 'store float into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[57, 'dstore', [qw()], [qw(... word1 word2)], [qw(...)], 'store double into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[58, 'astore', [qw()], [qw(... objectref)], [qw(...)], 'store reference in local vairable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[59, 'istore', [qw()], [qw(... value)], [qw(...)], 'store int into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[60, 'istore', [qw()], [qw(... value)], [qw(...)], 'store int into local variable', 1, 
 '$vars->[1] = pop (@$stack);
1;', '$tmp = pop (@$stack); "\$vars->[1] = $tmp;";', $THINGY2], 
[61, 'istore', [qw()], [qw(... value)], [qw(...)], 'store int into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[62, 'istore', [qw()], [qw(... value)], [qw(...)], 'store int into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[63, 'lstore', [qw()], [qw(... word1 word2)], [qw(...)], 'store long into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[64, 'lstore', [qw()], [qw(... word1 word2)], [qw(...)], 'store long into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[65, 'lstore', [qw()], [qw(... word1 word2)], [qw(...)], 'store long into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[66, 'lstore', [qw()], [qw(... word1 word2)], [qw(...)], 'store long into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[67, 'fstore', [qw()], [qw(... value)], [qw(...)], 'store float into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[68, 'fstore', [qw()], [qw(... value)], [qw(...)], 'store float into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[69, 'fstore', [qw()], [qw(... value)], [qw(...)], 'store float into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[70, 'fstore', [qw()], [qw(... value)], [qw(...)], 'store float into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[71, 'dstore', [qw()], [qw(... word1 word2)], [qw(...)], 'store double into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[72, 'dstore', [qw()], [qw(... word1 word2)], [qw(...)], 'store double into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[73, 'dstore', [qw()], [qw(... word1 word2)], [qw(...)], 'store double into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[74, 'dstore', [qw()], [qw(... word1 word2)], [qw(...)], 'store double into local variable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[75, 'astore_0', [qw()], [qw(... objectref)], [qw(...)], 'store reference in local vairable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[76, 'astore_1', [qw()], [qw(... objectref)], [qw(...)], 'store reference in local vairable', 1, 
 '$vars->[1] = pop (@$stack);
1;', '$tmp = pop (@$stack); "\$vars->[1] = $tmp";', $THINGY2], 
[77, 'astore_2', [qw()], [qw(... objectref)], [qw(...)], 'store reference in local vairable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[78, 'astore_3', [qw()], [qw(... objectref)], [qw(...)], 'store reference in local vairable', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[79, 'iastore', [qw()], [qw(... arrayref index value)], [qw(...)], 'store into int array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[80, 'lastore', [qw()], [qw(... arrayref index word1 word2)], [qw(...)], 'store into long array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[81, 'fastore', [qw()], [qw(... arrayref index value)], [qw(...)], 'store into float array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[82, 'dastore', [qw()], [qw(... arrayref index word1 word2)], [qw(...)], 'store into double array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[83, 'aastore', [qw()], [qw(... arrayref index value)], [qw(...)], 'store into reference array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[84, 'bastore', [qw()], [qw(... arrayref index value)], [qw(...)], 'store into byte or boolean array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[85, 'castore', [qw()], [qw(... arrayref index value)], [qw(...)], 'store into char array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[86, 'sastore', [qw()], [qw(... arrayref index value)], [qw(...)], 'store short into array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[87, 'pop', [qw()], [qw(... word)], [qw(...)], 'pop the top word of the operand stack', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[88, 'pop2', [qw()], [qw(... word1 word2)], [qw(...)], 'pop the top two words of the operand stack', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[89, 'dup', [qw()], [qw(... word)], [qw(... word word)], 'duplicate top operand stack word', 1, 
 'push (@$stack, $stack->[-1]);
1;', 'push (@$stack, $stack->[-1]); "";', $THINGY2], 
[90, 'dup', [qw()], [qw(... word2 word1)], [qw(... word1 word2 word1)], 'duplicate top operand stack word and put two down', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[91, 'dup', [qw()], [qw(... word3 word2 word1)], [qw(... word1 word3 word2 word1)], 'duplicate top operand stack word and put three down', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[92, 'dup2', [qw()], [qw(... word2 word1)], [qw(... word2 word1 word2 word1)], 'duplicate top two operand stack words', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[93, 'dup2', [qw()], [qw(... w3 w2 w1)], [qw(... w2 w1 w3 w2 w1)], 'duplicate top two operand stack words and put three down', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[94, 'dup2', [qw()], [qw(... w4 w3 w2 w1)], [qw(... w2 w1 w4 w3 w2 w1)], 'duplicate top two operand stack words and put four down', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[95, 'swap', [qw()], [qw(... word2 word1)], [qw(... word1 word2)], 'swap top two words on the operand stack', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[96, 'iadd', [qw()], [qw(... value1 value2)], [qw(... result)], 'add int', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[97, 'ladd', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'add long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[98, 'fadd', [qw()], [qw(... value1 value2)], [qw(... result)], 'add float', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[99, 'dadd', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'add double', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[100, 'isub', [qw()], [qw(... value1 value2)], [qw(... result)], 'subtract int (value1 - value2)', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[101, 'lsub', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'subtract long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[102, 'fsub', [qw()], [qw(... value1 value2)], [qw(... result)], 'subtract float', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[103, 'dsub', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'subtract double', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[104, 'imul', [qw()], [qw(... value1 value2)], [qw(... result)], 'multiply int', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[105, 'lmul', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'multiply long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[106, 'fmul', [qw()], [qw(... value1 value2)], [qw(... result)], 'multiply float', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[107, 'dmul', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'multiply double', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[108, 'idiv', [qw()], [qw(... value1 value2)], [qw(... result)], 'divide int (value1/value2)', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[109, 'ldiv', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'divide long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[110, 'fdiv', [qw()], [qw(... value1 value2)], [qw(... result)], 'divide float', 3, 
 'code;
code;', $THINGY1, $THINGY2], 
[111, 'ddiv', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'divide double', 1, 
'code;
code;', $THINGY1, $THINGY2], 
[112, 'irem', [qw()], [qw(... value1 value2)], [qw(... result)], 'remainder int (value1 % value2)', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[113, 'lrem', [qw()], [qw(... word1 word2 word1 word3)], [qw(... word1 word3)], 'remainder long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[114, 'frem', [qw()], [qw(... value1 value2)], [qw(... result)], 'remainder float', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[115, 'drem', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'remainder double', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[116, 'ineg', [qw()], [qw(... value)], [qw(... result)], 'negate int', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[117, 'lneg', [qw()], [qw(... word1 word2)], [qw(... word1 word2)], 'negate long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[118, 'fneg', [qw()], [qw(... value)], [qw(... result)], 'negate float', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[119, 'dneg', [qw()], [qw(... word1 word2)], [qw(... word1 word2)], 'negate double', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[120, 'ishl', [qw()], [qw(... value1 value2)], [qw(... result)], 'shift left int', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[121, 'lshl', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'shift left long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[122, 'ishr', [qw()], [qw(... value1 value3)], [qw(... result)], 'shift right int', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[123, 'lshr', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'arithmetic shift right long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[124, 'iushr', [qw()], [qw(... value1 value2)], [qw(... result)], 'logical right int shift', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[125, 'lushr', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'logical right long shift', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[126, 'iand', [qw()], [qw(... value1 value2)], [qw(... result)], 'boolean AND int', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[127, 'land', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'boolean AND long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[128, 'ior', [qw()], [qw(... value1 value2)], [qw(... result)], 'boolean OR int', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[129, 'lor', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'boolean OR long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[130, 'ixor', [qw()], [qw(... value1 value2)], [qw(... result)], 'boolean XOR int', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[131, 'lxor', [qw()], [qw(... word1 word2 word1 word2)], [qw(... word1 word2)], 'boolean XOR long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[132, 'iinc', [qw(1Register 1Int)], [qw(...)], [qw(...)], 'increment local variable by a constant', 1, 
 '$vars->[$parms->[0]] += $parms->[1];
1;', '"\$vars->[$parms->[0]] += $parms->[1];";', $THINGY2], 
[133, 'i2l', [qw()], [qw(... value)], [qw(... word1 word2)], 'convert int to long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[134, 'i2f', [qw()], [qw(... value)], [qw(... result)], 'convert int to float', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[135, 'i2d', [qw()], [qw(... value)], [qw(... word1 word2)], 'convert int to double', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[136, 'l2i', [qw()], [qw(... word1 word2)], [qw(... result)], 'convert long to int', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[137, 'l2f', [qw()], [qw(... word1 word2)], [qw(... result)], 'convert long to float', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[138, 'l2d', [qw()], [qw(... word1 word2)], [qw(... word1 word2)], 'convert double to long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[139, 'f2i', [qw()], [qw(... value)], [qw(... result)], 'convert float to int', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[140, 'f2l', [qw()], [qw(... value)], [qw(... w1 w2)], 'convert float to long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[141, 'f2d', [qw()], [qw(... value)], [qw(... w1 w2)], 'convert float to double', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[142, 'd2i', [qw()], [qw(... word1 word2)], [qw(... result)], 'convert double to int', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[143, 'd2l', [qw()], [qw(... word1 word2)], [qw(... result)], 'convert double to long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[144, 'd2f', [qw()], [qw(... word1 word2)], [qw(... result)], 'convert double to float', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[145, 'i2b', [qw()], [qw(... value)], [qw(... result)], 'convert int to byte', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[146, 'i2c', [qw()], [qw(... value)], [qw(... result)], 'convert int to char', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[147, 'i2s', [qw()], [qw(... value)], [qw(... result)], 'convert int to short', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[148, 'lcmp', [qw()], [qw(... word1 word2 word1 word2)], [qw(... result)], 'compare long', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[149, 'fcmpl', [qw()], [qw(... value1 value2)], [qw(... result)], 'compare float', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[150, 'fcmpg', [qw()], [qw(... value1 value2)], [qw(... result)], 'compare float', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[151, 'dcmpl', [qw()], [qw(... word1 word2 word1 word2)], [qw(... result)], 'compare double', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[152, 'dcmpg', [qw()], [qw(... word1 word2 word1 word2)], [qw(... result)], 'compare double', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[153, 'ifeq', [qw()], [qw(... value)], [qw(...)], 'branch if equal zero', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[154, 'ifne', [qw()], [qw(... value)], [qw(...)], 'branch if not equal zero', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[155, 'iflt', [qw()], [qw(... value)], [qw(...)], 'branch if less than zero', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[156, 'ifge', [qw()], [qw(... value)], [qw(...)], 'branch if greater than or equal to zero', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[157, 'ifgt', [qw()], [qw(... value)], [qw(...)], 'branch if greater than zero', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[158, 'ifle', [qw()], [qw(... value)], [qw(...)], 'branch if less than or equal zero', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[159, 'if', [qw()], [qw(... value1 value2)], [qw(...)], 'branch if int equal', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[160, 'if', [qw()], [qw(... value1 value2)], [qw(...)], 'branch if int not equal', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[161, 'if_icmplt', [qw(2Offset)], [qw(... value1 value2)], [qw(...)], 'branch if int less than', 1, 
 'if (pop (@$stack) > pop (@$stack)) {$pc += $parms->[0]-3};
1;', '$tmp =  $pc + $parms->[0]; $t2 = pop (@$stack); $t3 = pop (@$stack); push (@{$gotoTargets->{$tmp}}, $pc); "if ($t2 > $t3) {goto L$tmp;}";', $THINGY2], 
[162, 'if', [qw()], [qw(... value1 value2)], [qw(...)], 'branch if int greater than or equal', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[163, 'if', [qw()], [qw(... value1 value2)], [qw(...)], 'branch if int greater than', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[164, 'if', [qw()], [qw(... value1 value2)], [qw(...)], 'branch if int less than or equal', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[165, 'if', [qw()], [qw(... value1 value2)], [qw(...)], 'branch if reference equal', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[166, 'if', [qw()], [qw(... value1 value2)], [qw(...)], 'branch if reference not equal', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[167, 'goto', [qw(2Offset)], [qw(...)], [qw(...)], 'branch always', 1, 
 '$pc += $parms->[0]-3;
1;', '$tmp = $pc+$parms->[0]; push (@{$gotoTargets->{$tmp}}, $pc); "goto L$tmp;"', $THINGY2], 
[168, 'jsr', [qw()], [qw(...)], [qw(... address)], 'jump subroutine', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[169, 'ret', [qw()], [qw(...)], [qw(...)], 'return from a subroutine', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[170, 'tableswitch', [qw()], [qw(... index)], [qw(...)], 'access jump table by index and jump', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[171, 'lookupswitch', [qw()], [qw(... key)], [qw(...)], 'access jump table by key match and jump', 'k', 
 'code;
code;', $THINGY1, $THINGY2], 
[172, 'ireturn', [qw()], [qw(... value)], [qw( -)], 'return int from method', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[173, 'lreturn', [qw()], [qw(... word1 word2)], [qw( -)], 'return long from method', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[174, 'freturn', [qw()], [qw(... value)], [qw( -)], 'return float from method', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[175, 'dreturn', [qw()], [qw(... word1 word2)], [qw( -)], 'return double from method', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[176, 'areturn', [qw()], [qw(... objectref)], [qw( -)], 'return reference from method', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[177, 'return', [qw()], [qw(...)], [qw( -)], 'return void from a method', 1, 
 '$done=1;
1;', '"return;"', $THINGY2], 
#[178, 'getstatic', [qw()], [qw(...)], [qw(... value)], 'get static field from class', 1, 
# "code;
#code;", $THINGY1, $THINGY2], 
[178, 'getstatic', [qw(2Field)], [qw(...)], [qw(... word1 word2)], 'get static field from class', 1, 
 'push(@$stack, $parms->[0]);
1;', 'push(@$stack, $parms->[0]); "";', $THINGY2], 
#[179, 'putstatic', [qw()], [qw(... value)], [qw(...)], 'set a static field in a class', 1, 
# "code;
#code;", $THINGY1, $THINGY2], 
[179, 'putstatic', [qw()], [qw(... word1 word2)], [qw(...)], 'set a static field in a class', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
#[180, 'getfield', [qw()], [qw(... objectref)], [qw(... value)], 'fetch field from object', 2, 
# "code;
#code;", $THINGY1, $THINGY2], 
[180, 'getfield', [qw()], [qw(... objectref)], [qw(... word1 word2)], 'fetch field from object', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
#[181, 'putfield', [qw()], [qw(... objectref value)], [qw(...)], 'set field in an object', 1, 
# "code;
#code;", $THINGY1, $THINGY2], 
[181, 'putfield', [qw(2FieldRef)], [qw(... objectref word1 word2)], [qw(...)], 'set field in an object', 1, 
 '$self->putField($parms->[0], $stack, 0, 1);
1;', $THINGY1, $THINGY2], 
[182, 'invokevirtual', [qw(2Method)], [qw(... objectref arg1 arg2 ...)], [qw(...)], 'invoke an instance method', 3, 
 '$self->executeMethod($parms->[0], $stack, 0, 0);
1;', '$self->compile_invoke($stack, 0, $parms->[0], 0)', $THINGY2], 
[183, 'invokespecial', [qw(2Method)], [qw(... objectref arg1 arg2 ...)], [qw(...)], 'invoke a special interface method', 2, 
 '$self->executeMethod($parms->[0], $stack, 0, 1);
1;', 'push (@$stack, $self->compile_invoke($stack, 0, $parms->[0], 1)); ""', $THINGY2], 
[184, 'invokestatic', [qw()], [qw(... objectref arg1 arg2 ...)], [qw(...)], 'invoke a class (static) method', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[185, 'invokeinterface', [qw()], [qw(... objectref arg1 arg2 ...)], [qw(...)], 'invoke an interface method', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[186, 'xxxunusedxxx', [qw()], [qw()], [qw()], ' ', 'n', 
 'code;
code;', $THINGY1, $THINGY2], 
[187, 'new', [qw(2Class)], [qw(...)], [qw(... objectref)], 'create a new object', 2, 
 'push (@$stack, new W3C::JVM::UninitializedObject($parms->[0]));
1;', 'push (@$stack, new W3C::JVM::UninitializedObject($parms->[0])); "";', $THINGY2], 
[188, 'newarray', [qw()], [qw(... count)], [qw(... arrayref)], 'crate a new array', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[189, 'anewarray', [qw()], [qw(... count)], [qw(... arrayref)], 'create new array of reference', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[190, 'arraylength', [qw()], [qw(... arrayref)], [qw(... length)], 'get length of array', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[191, 'athrow', [qw()], [qw(... objectref)], [qw(objectref)], 'throw exception or error', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[192, 'checkcast', [qw()], [qw(... objectref)], [qw(... objectref)], 'check whether object is of given type', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[193, 'instanceof', [qw()], [qw(... objectref)], [qw(... result)], 'determine if object is of a given type', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[194, 'monitorenter', [qw()], [qw(... objectref)], [qw(...)], 'enter monitor for an object', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[195, 'monitorexit', [qw()], [qw(... objectref)], [qw(...)], 'exit monitor for an object', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[196, 'wide', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[197, 'multianewarray', [qw()], [qw(... count1 [count2 ...])], [qw(... arrayref)], 'create a new multidimensional array', 'n', 
 'code;
code;', $THINGY1, $THINGY2], 
[198, 'ifnull', [qw()], [qw(... value)], [qw(...)], 'branch if reference is null', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[199, 'ifnonnull', [qw()], [qw(... value)], [qw(...)], 'branch if reference is non null', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[200, 'goto', [qw()], [qw(...)], [qw(...)], 'branch always (wide index)', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[201, 'jsr', [qw()], [qw(...)], [qw(... address)], 'jump subroutine', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[202, 'breakpoint', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[203, 'ldc', [qw()], [qw(...)], [qw(... item)], 'push item from constant pool', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[204, 'ldc', [qw()], [qw(...)], [qw(... item)], 'push item from constant pool', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[205, 'ldc2', [qw(1String)], [qw(...)], [qw(... item.word1 item.word3)], 'push item from constant pool', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[206, 'getfield', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[207, 'putfield', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[208, 'getfield2', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[209, 'putfield2', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[210, 'getstatic', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[211, 'putstatic', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[212, 'getstatic2', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[213, 'putstatic2', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[214, 'invokevirtual', [qw()], [qw()], [qw()], ' ', 3, 
 'code;
code;', $THINGY1, $THINGY2], 
[215, 'invokenonvirtual', [qw()], [qw()], [qw()], ' ', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[216, 'invokesuper', [qw()], [qw()], [qw()], ' ', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[217, 'invokestatic', [qw()], [qw()], [qw()], ' ', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[218, 'invokeinterface', [qw()], [qw()], [qw()], ' ', 2, 
 'code;
code;', $THINGY1, $THINGY2], 
[219, 'invokevirtualobject', [qw()], [qw()], [qw()], ' ', 3, 
 'code;
code;', $THINGY1, $THINGY2], 
[221, 'new', [qw()], [qw(...)], [qw(... objectref)], 'create a new object', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[222, 'anewarray', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[223, 'multianewarray', [qw()], [qw(... count1 [count2 ...])], [qw(... arrayref)], 'create a new multidimensional array', 'n', 
 'code;
code;', $THINGY1, $THINGY2], 
[224, 'checkcast', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[225, 'instanceof', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[226, 'invokevirtual', [qw(2Method)], [qw()], [qw()], ' ', 3, 
 'code;
code;', $THINGY1, $THINGY2], 
[227, 'getfield', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[228, 'putfield', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[254, 'impdep1', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
[255, 'impdep2', [qw()], [qw()], [qw()], ' ', 1, 
 'code;
code;', $THINGY1, $THINGY2], 
    ];
# *table originally from http://www.csee.wvu.edu/~callahan/cs136/opcodes.htm

# Take the above array of methods and turn them elements into
# W3C::JVM::Instruction objects so the following methods may
# be called upon them.
for (my $i = 0; $i < @$InstructionTable; $i++) {
    bless ($InstructionTable->[$i], 'W3C::JVM::Instruction');
}

sub getInterpreterCode {
    my ($self) = @_;
    return $self->[$INTERP];
}

sub getCompilerCode {
    my ($self) = @_;
    return $self->[$COMPILE];
}

sub getParms {
    my ($self, $byteCode, $pc, $pool) = @_;
    my $typeSet = $self->[$PARMS];
    my $parms = [];
    my $types = [];
    my $iParm = 0;
    for (my $i = 0; $i < @$typeSet; $i++) {
	my $type = $typeSet->[$i];
	if ($type !~ m/^(\d+)(.*)$/) {
	    my $n = $byteCode->[$pc];
	    &throw(new W3C::Util::Exception(-message => "what type is $n $self->[$INSTRUCTION] type $type at $pc.$i"));
	}
	my ($parmWidth, $refType) = ($1, $2);
	my $target;
	if ($parmWidth == 1) {
	    $target = $byteCode->[$pc+$iParm+1];
	    $iParm += 1;
	} elsif ($parmWidth == 2) {
	    $target = $byteCode->[$pc+$iParm+1] * 256 + $byteCode->[$pc+$iParm+2];
	    $iParm += 2;
	}

	# Resolving parameters:
	#   pool references are resolved now.
	#   ints and strings are passed as scalars
	#   offsets are resolved against the current program counter

	# note - Int and Register behave the same.
	if ($refType eq 'Int') {
	    push (@$parms, $target);
	} elsif ($refType eq 'Offset') {
	    if ($target > 32767) {
		$target = $target - 65536;
	    }
	    push (@$parms, $target);
	} elsif ($refType eq 'Register') {
	    push (@$parms, $target);
	} else {
	    # presume it's a pool entry
	    push (@$parms, $pool->getEntry($target));
	}
	push (@$types, $refType);
    }
    return ($parms, $types, $iParm);
}

sub disassemble {
    my ($self, $byteCode, $pc, $parms, $types, $flags) = @_;
    $flags ||= {};
    my $n = $byteCode->[$pc];
    my $fmt = $flags->{-ordinal} == 16 ? 'x' : 'd';
    my @ret;
    for (my $i = 0; $i < @$parms; $i++) {
	my $parmStr = ref $parms->[$i] ? $parms->[$i]->toString() : $parms->[$i];
	if ($types->[$i] eq 'Offset') {
	    $parmStr = sprintf("%$fmt", $pc+$parmStr);
	}
#	my $parmStr = $parms->[$i]->can('toString') ? $parms->[$i]->toString() : $parms->[$i];
	push (@ret, "<$types->[$i] $parmStr>");
    }
    my $parmStr = join (' ', @ret);
    my $code = $self->[$INSTRUCTION];
    my $ret = sprintf("%3$fmt: %3$fmt %s", $pc, $n, $code); # "$pc: $n $code";
    if (@ret) {
	$ret .= " ($parmStr)";
    }
    if ($flags->{-showInterpreterCode}) {
	$ret .= " [$self->[$INTERP]]";
    }
    if ($flags->{-showCompilerCode}) {
	$ret .= " [$self->[$COMPILE]]";
    }
    return $ret;
}

sub toString {
    my ($self) = @_;
    my $code = $self->[$INSTRUCTION];
    return sprintf("%d %s %s %s", $self->[$OPCODE], $self->[$INSTRUCTION], 
		   $self->[$INTERP], $self->[$COMPILE]);
}

sub makeException {
    my ($self, $error) = @_;
    if ($error =~ m/Bareword "code" not allowed while "strict subs" in use at /) {
	return new W3C::Util::NotImplementedException(-class => 'W3C::JVM::Instruction', 
						      -method => "$self->[$INSTRUCTION]($self->[$OPCODE])");
    } else {&throw()}
}

1;

