/** -*-c-*-
  This file contains instruction information for yarv instruction sequence.

  ----
  This file is auto generated by insns2vm.rb
  DO NOT TOUCH!

  If you want to fix something, you must edit 'template/insns_info.inc.tmpl'
  or tool/insns2vm.rb
 */

#define TS_OFFSET 'O'
#define TS_NUM 'N'
#define TS_LINDEX 'L'
#define TS_VALUE 'V'
#define TS_ID 'I'
#define TS_GENTRY 'G'
#define TS_IC 'K'
#define TS_CALLINFO 'C'
#define TS_CALLCACHE 'E'
#define TS_CDHASH 'H'
#define TS_ISEQ 'S'
#define TS_VARIABLE '.'
#define TS_FUNCPTR 'F'

static const char *const insn_name_info[] = {
  "nop",
  "getlocal",
  "setlocal",
  "getspecial",
  "setspecial",
  "getinstancevariable",
  "setinstancevariable",
  "getclassvariable",
  "setclassvariable",
  "getconstant",
  "setconstant",
  "getglobal",
  "setglobal",
  "putnil",
  "putself",
  "putobject",
  "putspecialobject",
  "putiseq",
  "putstring",
  "concatstrings",
  "tostring",
  "toregexp",
  "newarray",
  "duparray",
  "expandarray",
  "concatarray",
  "splatarray",
  "newhash",
  "newrange",
  "pop",
  "dup",
  "dupn",
  "swap",
  "reverse",
  "reput",
  "topn",
  "setn",
  "adjuststack",
  "defined",
  "checkmatch",
  "checkkeyword",
  "trace",
  "defineclass",
  "send",
  "opt_str_freeze",
  "opt_send_without_block",
  "invokesuper",
  "invokeblock",
  "leave",
  "throw",
  "jump",
  "branchif",
  "branchunless",
  "branchnil",
  "getinlinecache",
  "setinlinecache",
  "once",
  "opt_case_dispatch",
  "opt_plus",
  "opt_minus",
  "opt_mult",
  "opt_div",
  "opt_mod",
  "opt_eq",
  "opt_neq",
  "opt_lt",
  "opt_le",
  "opt_gt",
  "opt_ge",
  "opt_ltlt",
  "opt_aref",
  "opt_aset",
  "opt_aset_with",
  "opt_aref_with",
  "opt_length",
  "opt_size",
  "opt_empty_p",
  "opt_succ",
  "opt_not",
  "opt_regexpmatch1",
  "opt_regexpmatch2",
  "opt_call_c_function",
  "bitblt",
  "answer",
  "getlocal_OP__WC__0",
  "getlocal_OP__WC__1",
  "setlocal_OP__WC__0",
  "setlocal_OP__WC__1",
  "putobject_OP_INT2FIX_O_0_C_",
  "putobject_OP_INT2FIX_O_1_C_",

};

static const char *const insn_operand_info[] = {
  "",
  "LN",
  "LN",
  "NN",
  "N",
  "IK",
  "IK",
  "I",
  "I",
  "I",
  "I",
  "G",
  "G",
  "",
  "",
  "V",
  "N",
  "S",
  "V",
  "N",
  "",
  "NN",
  "N",
  "V",
  "NN",
  "",
  "V",
  "N",
  "N",
  "",
  "",
  "N",
  "",
  "N",
  "",
  "N",
  "N",
  "N",
  "NVV",
  "N",
  "LN",
  "N",
  "ISN",
  "CES",
  "V",
  "CE",
  "CES",
  "C",
  "",
  "N",
  "O",
  "O",
  "O",
  "O",
  "OK",
  "K",
  "SK",
  "HO",
  "CE",
  "CE",
  "CE",
  "CE",
  "CE",
  "CE",
  "CECE",
  "CE",
  "CE",
  "CE",
  "CE",
  "CE",
  "CE",
  "CE",
  "CEV",
  "CEV",
  "CE",
  "CE",
  "CE",
  "CE",
  "CE",
  "V",
  "CE",
  "F",
  "",
  "",
  "L",
  "L",
  "L",
  "L",
  "",
  "",

};

static const int insn_len_info[] = {
  1,
  3,
  3,
  3,
  2,
  3,
  3,
  2,
  2,
  2,
  2,
  2,
  2,
  1,
  1,
  2,
  2,
  2,
  2,
  2,
  1,
  3,
  2,
  2,
  3,
  1,
  2,
  2,
  2,
  1,
  1,
  2,
  1,
  2,
  1,
  2,
  2,
  2,
  4,
  2,
  3,
  2,
  4,
  4,
  2,
  3,
  4,
  2,
  1,
  2,
  2,
  2,
  2,
  2,
  3,
  2,
  3,
  3,
  3,
  3,
  3,
  3,
  3,
  3,
  5,
  3,
  3,
  3,
  3,
  3,
  3,
  3,
  4,
  4,
  3,
  3,
  3,
  3,
  3,
  2,
  3,
  2,
  1,
  1,
  2,
  2,
  2,
  2,
  1,
  1,

};

#ifdef USE_INSN_RET_NUM
static const int insn_stack_push_num_info[] = {
  0,
  1,
  0,
  1,
  0,
  1,
  0,
  1,
  0,
  1,
  0,
  1,
  0,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  0,
  2,
  1,
  2,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  0,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  0,
  0,
  0,
  0,
  1,
  1,
  1,
  0,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  0,
  1,
  1,
  1,
  1,
  0,
  0,
  1,
  1,

};
#endif

#ifdef USE_INSN_STACK_INCREASE
static int
insn_stack_increase(int depth, int insn, VALUE *opes)
{
  switch(insn){
        case BIN(nop):{
          return depth + 0;
        }
        case BIN(getlocal):{
          return depth + 1;
        }
        case BIN(setlocal):{
          return depth + -1;
        }
        case BIN(getspecial):{
          return depth + 1;
        }
        case BIN(setspecial):{
          return depth + -1;
        }
        case BIN(getinstancevariable):{
          return depth + 1;
        }
        case BIN(setinstancevariable):{
          return depth + -1;
        }
        case BIN(getclassvariable):{
          return depth + 1;
        }
        case BIN(setclassvariable):{
          return depth + -1;
        }
        case BIN(getconstant):{
          return depth + 0;
        }
        case BIN(setconstant):{
          return depth + -2;
        }
        case BIN(getglobal):{
          return depth + 1;
        }
        case BIN(setglobal):{
          return depth + -1;
        }
        case BIN(putnil):{
          return depth + 1;
        }
        case BIN(putself):{
          return depth + 1;
        }
        case BIN(putobject):{
          return depth + 1;
        }
        case BIN(putspecialobject):{
          return depth + 1;
        }
        case BIN(putiseq):{
          return depth + 1;
        }
        case BIN(putstring):{
          return depth + 1;
        }
        case BIN(concatstrings):{
          int inc = 0;
        int num = FIX2INT(opes[0]);
        inc += 1 - num;;
        return depth + inc;
        }
        case BIN(tostring):{
          return depth + 0;
        }
        case BIN(toregexp):{
          int inc = 0;
        int cnt = FIX2INT(opes[1]);
        inc += 1 - cnt;;
        return depth + inc;
        }
        case BIN(newarray):{
          int inc = 0;
        int num = FIX2INT(opes[0]);
        inc += 1 - num;;
        return depth + inc;
        }
        case BIN(duparray):{
          return depth + 1;
        }
        case BIN(expandarray):{
          int inc = 0;
        int num = FIX2INT(opes[0]);
        int flag = FIX2INT(opes[1]);
        inc += num - 1 + (flag & 1 ? 1 : 0);;
        return depth + inc;
        }
        case BIN(concatarray):{
          return depth + -1;
        }
        case BIN(splatarray):{
          return depth + 0;
        }
        case BIN(newhash):{
          int inc = 0;
        int num = FIX2INT(opes[0]);
        inc += 1 - num;;
        return depth + inc;
        }
        case BIN(newrange):{
          return depth + -1;
        }
        case BIN(pop):{
          return depth + -1;
        }
        case BIN(dup):{
          return depth + 1;
        }
        case BIN(dupn):{
          int inc = 0;
        int n = FIX2INT(opes[0]);
        inc += n;;
        return depth + inc;
        }
        case BIN(swap):{
          return depth + 0;
        }
        case BIN(reverse):{
          int inc = 0;
        inc += 0;;
        return depth + inc;
        }
        case BIN(reput):{
          int inc = 0;
        inc += 0;;
        return depth + inc;
        }
        case BIN(topn):{
          int inc = 0;
        inc += 1;;
        return depth + inc;
        }
        case BIN(setn):{
          int inc = 0;
        inc += 0;
        return depth + inc;
        }
        case BIN(adjuststack):{
          int inc = 0;
        int n = FIX2INT(opes[0]);
        inc -= n;
        return depth + inc;
        }
        case BIN(defined):{
          return depth + 0;
        }
        case BIN(checkmatch):{
          return depth + -1;
        }
        case BIN(checkkeyword):{
          return depth + 1;
        }
        case BIN(trace):{
          return depth + 0;
        }
        case BIN(defineclass):{
          return depth + -1;
        }
        case BIN(send):{
          int inc = 0;
        CALL_INFO ci = (CALL_INFO)(opes[0]);
        inc += - (int)(ci->orig_argc + ((ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0));;
        return depth + inc;
        }
        case BIN(opt_str_freeze):{
          return depth + 1;
        }
        case BIN(opt_send_without_block):{
          int inc = 0;
        CALL_INFO ci = (CALL_INFO)(opes[0]);
        inc += -ci->orig_argc;;
        return depth + inc;
        }
        case BIN(invokesuper):{
          int inc = 0;
        CALL_INFO ci = (CALL_INFO)(opes[0]);
        inc += - (int)(ci->orig_argc + ((ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0));;
        return depth + inc;
        }
        case BIN(invokeblock):{
          int inc = 0;
        CALL_INFO ci = (CALL_INFO)(opes[0]);
        inc += 1 - ci->orig_argc;;
        return depth + inc;
        }
        case BIN(leave):{
          return depth + 0;
        }
        case BIN(throw):{
          return depth + 0;
        }
        case BIN(jump):{
          return depth + 0;
        }
        case BIN(branchif):{
          return depth + -1;
        }
        case BIN(branchunless):{
          return depth + -1;
        }
        case BIN(branchnil):{
          return depth + -1;
        }
        case BIN(getinlinecache):{
          return depth + 1;
        }
        case BIN(setinlinecache):{
          return depth + 0;
        }
        case BIN(once):{
          return depth + 1;
        }
        case BIN(opt_case_dispatch):{
          int inc = 0;
        inc += -1;;
        return depth + inc;
        }
        case BIN(opt_plus):{
          return depth + -1;
        }
        case BIN(opt_minus):{
          return depth + -1;
        }
        case BIN(opt_mult):{
          return depth + -1;
        }
        case BIN(opt_div):{
          return depth + -1;
        }
        case BIN(opt_mod):{
          return depth + -1;
        }
        case BIN(opt_eq):{
          return depth + -1;
        }
        case BIN(opt_neq):{
          return depth + -1;
        }
        case BIN(opt_lt):{
          return depth + -1;
        }
        case BIN(opt_le):{
          return depth + -1;
        }
        case BIN(opt_gt):{
          return depth + -1;
        }
        case BIN(opt_ge):{
          return depth + -1;
        }
        case BIN(opt_ltlt):{
          return depth + -1;
        }
        case BIN(opt_aref):{
          return depth + -1;
        }
        case BIN(opt_aset):{
          return depth + -2;
        }
        case BIN(opt_aset_with):{
          return depth + -1;
        }
        case BIN(opt_aref_with):{
          return depth + 0;
        }
        case BIN(opt_length):{
          return depth + 0;
        }
        case BIN(opt_size):{
          return depth + 0;
        }
        case BIN(opt_empty_p):{
          return depth + 0;
        }
        case BIN(opt_succ):{
          return depth + 0;
        }
        case BIN(opt_not):{
          return depth + 0;
        }
        case BIN(opt_regexpmatch1):{
          return depth + 0;
        }
        case BIN(opt_regexpmatch2):{
          return depth + -1;
        }
        case BIN(opt_call_c_function):{
          return depth + 0;
        }
        case BIN(bitblt):{
          return depth + 1;
        }
        case BIN(answer):{
          return depth + 1;
        }
        case BIN(getlocal_OP__WC__0):{
          return depth + 1;
        }
        case BIN(getlocal_OP__WC__1):{
          return depth + 1;
        }
        case BIN(setlocal_OP__WC__0):{
          return depth + -1;
        }
        case BIN(setlocal_OP__WC__1):{
          return depth + -1;
        }
        case BIN(putobject_OP_INT2FIX_O_0_C_):{
          return depth + 1;
        }
        case BIN(putobject_OP_INT2FIX_O_1_C_):{
          return depth + 1;
        }

  default:
    rb_bug("insn_sp_increase: unreachable");
  }
  return 0;
}
#endif

/* some utilities */

static int
insn_len(VALUE insn)
{
  return insn_len_info[(int)insn];
}

static const char *
insn_name(VALUE insn)
{
  return insn_name_info[(int)insn];
}

static const char *
insn_op_types(VALUE insn)
{
  return insn_operand_info[(int)insn];
}

static int
insn_op_type(VALUE insn, long pos)
{
  int len = insn_len(insn) - 1;
  if(pos < len){
    return insn_operand_info[(int)insn][pos];
  }
  else{
    return 0;
  }
}

#ifdef USE_INSN_RET_NUM
static int
insn_ret_num(VALUE insn)
{
  return insn_stack_push_num_info[(int)insn];
}
#endif
