summaryrefslogtreecommitdiff
path: root/template/insns_info.inc.tmpl
blob: 546368d984d6eeda7d7516c6387a97b680eb6ee8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/** -*-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
 */

% TYPE_CHARS.each do |t, c|
#define <%=t%> '<%=c%>'
% end

extern const struct rb_vm_insn_name_info rb_vm_insn_name_info_base;
extern const unsigned short rb_vm_insn_name_info_offset[];
extern const char rb_vm_insn_operand_info[][8];
extern const unsigned short rb_vm_insn_stack_push_num_info[];
#define insn_name_info (const char *)&rb_vm_insn_name_info_base+rb_vm_insn_name_info_offset
#define insn_operand_info rb_vm_insn_operand_info
#define rb_vm_insn_stack_push_num_info insn_stack_push_num_info

#ifdef RUBY_VM_INSNS_INFO
const unsigned short rb_vm_insn_name_info_offset[] = {
% insn_name_length = @insns.inject(0) do |ofs, insn|
    <%= ofs %>,
%   ofs + insn.name.size + 1
% end
};

ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_name_info_offset);

% n = 100
const struct rb_vm_insn_name_info {
% @insns.each_with_index do |insn, i|
%   if (i % n) == 0
    struct {
%   end
	char L<%=i%n%>[<%= insn.name.size+1 %>];
%   if (i % n) == n - 1 or i == @insns.size - 1
    } S<%=i / n%>;
%   end
% end
} rb_vm_insn_name_info_base = {
% @insns.each_with_index do |insn, i|
%   if (i % n) == 0
    {
%   end
	"<%= insn.name %>",
%   if (i % n) == n - 1 or i == @insns.size - 1
    },
%   end
% end
};

const char rb_vm_insn_operand_info[][8] = {
% @insns.each do |insn|
    "\<%= (insn.opes.size+1).to_s(8) %>""<%
    insn.opes.each {|type, _|
      %><%=TYPE_CHARS.fetch(op2typesig(type))%><%
    }%>",
% end
};

ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_operand_info);

#ifdef USE_INSN_RET_NUM
const unsigned short rb_vm_insn_stack_push_num_info[] = {
% @insns.each do |insn|
    <%= insn.rets.size %>,
% end
};

ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_stack_push_num_info);
#endif
#endif

#ifdef USE_INSN_STACK_INCREASE
static int
insn_stack_increase(int depth, int insn, VALUE *opes)
{
    switch (insn) {
% @insns.each do |insn|
      case BIN(<%= insn.name %>): {
	<%= insn.sp_increase_c_expr %>
      }
% end
      default:
	rb_bug("insn_sp_increase: unreachable");
    }
    return 0;
}
#endif

/* some utilities */

static int
insn_len(VALUE insn)
{
    return (unsigned char)insn_operand_info[(int)insn][0];
}

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]+1;
}

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+1];
    }
    else{
	return 0;
    }
}

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