/** -*-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 insns2vm.rb
 */

#define TS_OFFSET 'O'
#define TS_NUM 'N'
#define TS_LINDEX 'L'
#define TS_DINDEX 'D'
#define TS_VALUE 'V'
#define TS_ID 'I'
#define TS_GENTRY 'G'
#define TS_IC 'C'
#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",
  "getdynamic",
  "setdynamic",
  "getinstancevariable",
  "setinstancevariable",
  "getclassvariable",
  "setclassvariable",
  "getconstant",
  "setconstant",
  "getglobal",
  "setglobal",
  "putnil",
  "putself",
  "putobject",
  "putspecialobject",
  "putiseq",
  "putstring",
  "concatstrings",
  "tostring",
  "toregexp",
  "newarray",
  "duparray",
  "expandarray",
  "concatarray",
  "splatarray",
  "checkincludearray",
  "newhash",
  "newrange",
  "pop",
  "dup",
  "dupn",
  "swap",
  "reput",
  "topn",
  "setn",
  "adjuststack",
  "defined",
  "trace",
  "defineclass",
  "send",
  "invokesuper",
  "invokeblock",
  "leave",
  "finish",
  "throw",
  "jump",
  "branchif",
  "branchunless",
  "getinlinecache",
  "onceinlinecache",
  "setinlinecache",
  "opt_case_dispatch",
  "opt_checkenv",
  "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_length",
  "opt_size",
  "opt_succ",
  "opt_not",
  "opt_regexpmatch1",
  "opt_regexpmatch2",
  "opt_call_c_function",
  "bitblt",
  "answer",

};

static const char *const insn_operand_info[] = {
  "", 
  "L", 
  "L", 
  "NN", 
  "N", 
  "DN", 
  "DN", 
  "IC", 
  "IC", 
  "I", 
  "I", 
  "I", 
  "I", 
  "G", 
  "G", 
  "", 
  "", 
  "V", 
  "N", 
  "S", 
  "V", 
  "N", 
  "", 
  "NN", 
  "N", 
  "V", 
  "NN", 
  "", 
  "V", 
  "V", 
  "N", 
  "N", 
  "", 
  "", 
  "N", 
  "", 
  "", 
  "N", 
  "N", 
  "N", 
  "NVV", 
  "N", 
  "ISN", 
  "INSNC", 
  "NSN", 
  "NN", 
  "", 
  "", 
  "N", 
  "O", 
  "O", 
  "O", 
  "OC", 
  "OC", 
  "C", 
  "HO", 
  "", 
  "C", 
  "C", 
  "C", 
  "C", 
  "C", 
  "C", 
  "CC", 
  "C", 
  "C", 
  "C", 
  "C", 
  "C", 
  "C", 
  "C", 
  "C", 
  "C", 
  "C", 
  "C", 
  "V", 
  "", 
  "F", 
  "", 
  "", 

};

static const int insn_len_info[] = {
  1,
  2,
  2,
  3,
  2,
  3,
  3,
  3,
  3,
  2,
  2,
  2,
  2,
  2,
  2,
  1,
  1,
  2,
  2,
  2,
  2,
  2,
  1,
  3,
  2,
  2,
  3,
  1,
  2,
  2,
  2,
  2,
  1,
  1,
  2,
  1,
  1,
  2,
  2,
  2,
  4,
  2,
  4,
  6,
  4,
  3,
  1,
  1,
  2,
  2,
  2,
  2,
  3,
  3,
  2,
  3,
  1,
  2,
  2,
  2,
  2,
  2,
  2,
  3,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  1,
  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,
  0,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  2,
  1,
  1,
  0,
  2,
  1,
  2,
  1,
  1,
  1,
  1,
  1,
  0,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  0,
  0,
  0,
  1,
  1,
  1,
  0,
  0,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  1,
  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(getdynamic):{
          return depth + 1;
        }
        case BIN(setdynamic):{
          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(checkincludearray):{
          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(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(trace):{
          return depth + 0;
        }
        case BIN(defineclass):{
          return depth + -1;
        }
        case BIN(send):{
          int inc = 0;
        int op_argc = FIX2INT(opes[1]);
        int op_flag = FIX2INT(opes[3]);
        inc += - (int)(op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));;
        return depth + inc;
        }
        case BIN(invokesuper):{
          int inc = 0;
        int op_argc = FIX2INT(opes[0]);
        int op_flag = FIX2INT(opes[2]);
        inc += - (int)(op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));;
        return depth + inc;
        }
        case BIN(invokeblock):{
          int inc = 0;
        int num = FIX2INT(opes[0]);
        inc += 1 - num;;
        return depth + inc;
        }
        case BIN(leave):{
          return depth + 0;
        }
        case BIN(finish):{
          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(getinlinecache):{
          return depth + 1;
        }
        case BIN(onceinlinecache):{
          return depth + 1;
        }
        case BIN(setinlinecache):{
          return depth + 0;
        }
        case BIN(opt_case_dispatch):{
          int inc = 0;
        inc += -1;;
        return depth + inc;
        }
        case BIN(opt_checkenv):{
          return depth + 0;
        }
        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_length):{
          return depth + 0;
        }
        case BIN(opt_size):{
          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;
        }

  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
