ytljit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/README +29 -0
  2. data/Rakefile +22 -0
  3. data/ext/code_alloc.c +266 -0
  4. data/ext/extconf.rb +3 -0
  5. data/ext/ytljit.c +527 -0
  6. data/ext/ytljit.h +285 -0
  7. data/lib/ytljit/asm.rb +205 -0
  8. data/lib/ytljit/asmext.rb +199 -0
  9. data/lib/ytljit/asmext_x64.rb +212 -0
  10. data/lib/ytljit/asmext_x86.rb +128 -0
  11. data/lib/ytljit/asmutil.rb +182 -0
  12. data/lib/ytljit/codespace.rb +92 -0
  13. data/lib/ytljit/error.rb +7 -0
  14. data/lib/ytljit/instruction.rb +138 -0
  15. data/lib/ytljit/instruction_ia.rb +1298 -0
  16. data/lib/ytljit/instruction_x64.rb +41 -0
  17. data/lib/ytljit/instruction_x86.rb +11 -0
  18. data/lib/ytljit/marshal.rb +133 -0
  19. data/lib/ytljit/matcher.rb +235 -0
  20. data/lib/ytljit/rubyvm.rb +63 -0
  21. data/lib/ytljit/struct.rb +125 -0
  22. data/lib/ytljit/type.rb +112 -0
  23. data/lib/ytljit/util.rb +63 -0
  24. data/lib/ytljit/vm.rb +1649 -0
  25. data/lib/ytljit/vm_codegen.rb +491 -0
  26. data/lib/ytljit/vm_inline_method.rb +85 -0
  27. data/lib/ytljit/vm_inspect.rb +74 -0
  28. data/lib/ytljit/vm_sendnode.rb +561 -0
  29. data/lib/ytljit/vm_trans.rb +508 -0
  30. data/lib/ytljit/vm_type.rb +299 -0
  31. data/lib/ytljit/vm_type_gen.rb +158 -0
  32. data/lib/ytljit/vm_typeinf.rb +98 -0
  33. data/lib/ytljit.rb +46 -0
  34. data/test/asmsample.rb +117 -0
  35. data/test/cstest.rb +61 -0
  36. data/test/marshaltest.rb +27 -0
  37. data/test/test_assemble.rb +148 -0
  38. data/test/test_assemble2.rb +286 -0
  39. data/test/test_codespace.rb +102 -0
  40. data/test/test_typeinf.rb +21 -0
  41. data/test/tivmtest.rb +54 -0
  42. data/test/vmtest.rb +59 -0
  43. data/test/vmtest2.rb +41 -0
  44. data/test/vmtest3.rb +22 -0
  45. data/test/vmtest_compile_only.rb +41 -0
  46. data/test/vmtest_execute_only.rb +22 -0
  47. metadata +121 -0
@@ -0,0 +1,212 @@
1
+ module YTLJit
2
+ module FuncArgX64CommonMixin
3
+ include AbsArch
4
+ include X64
5
+ ARGPOS2REG = [RDI, RSI, RDX, RCX, R8, R9]
6
+ ARGPOS2FREG = [XMM0, XMM1, XMM2, XMM3]
7
+ end
8
+
9
+ module FunctionArgumentX64MixinInt
10
+ include FuncArgX64CommonMixin
11
+
12
+ def argpos2reg
13
+ case @abi_kind
14
+ when :c
15
+ ARGPOS2REG
16
+
17
+ when :ytl
18
+ []
19
+
20
+ else
21
+ raise "#{@abi_kind}"
22
+ end
23
+ end
24
+ end
25
+
26
+ module FunctionArgumentX64MixinFloat
27
+ include FuncArgX64CommonMixin
28
+
29
+ def argpos2reg
30
+ case @abi_kind
31
+ when :c
32
+ ARGPOS2FREG
33
+
34
+ when :ytl
35
+ []
36
+
37
+ else
38
+ raise "#{@abi_kind}"
39
+ end
40
+ end
41
+ end
42
+
43
+ module FunctionArgumentX64MixinCommon
44
+ include FuncArgX64CommonMixin
45
+
46
+ def dst_opecode
47
+ if @no < argpos2reg.size then
48
+ argpos2reg[@no]
49
+ else
50
+ spos = @no - argpos2reg.size
51
+ OpIndirect.new(SPR, OpImmidiate8.new(spos * 8))
52
+ end
53
+ end
54
+
55
+ def src_opecode
56
+ if @no < argpos2reg.size then
57
+ argpos2reg[@no]
58
+ else
59
+ # +1 means return address slot
60
+ spos = @no - argpos2reg.size + 1
61
+ OpIndirect.new(SPR, OpImmidiate8.new(spos * 8))
62
+ end
63
+ end
64
+
65
+ def gen_access_dst(gen, inst, dst, src, src2)
66
+ code = ""
67
+ asm = gen.asm
68
+ fainfo = gen.funcarg_info
69
+
70
+ if @no == 0 then
71
+ fainfo.area_allocate_pos.push nil
72
+ fainfo.used_arg_tab.push Hash.new
73
+ end
74
+
75
+ # It can be argpos2reg.size == 0, so this "if" isn't "elsif"
76
+ if @no == argpos2reg.size then
77
+ offset = asm.offset
78
+ code += asm.update_state(gen.sub(SPR, 0))
79
+ fainfo.area_allocate_pos[-1] = offset
80
+ end
81
+
82
+ if @no < argpos2reg.size then
83
+ argreg = argpos2reg[@no]
84
+
85
+ # for nested function call. need save previous reg.
86
+ if asm.retry_mode != :change_op and
87
+ fainfo.used_arg_tab.last[@no] then
88
+ asm.update_state(gen.push(argreg))
89
+ fainfo.push argreg
90
+ end
91
+ code += asm.update_state(gen.mov(argreg, src))
92
+ else
93
+ # spilled reg
94
+ spos = @no - argpos2reg.size
95
+ argdst = OpIndirect.new(SPR, OpImmidiate8.new(spos * 8))
96
+
97
+ if src.is_a?(OpRegXMM) then
98
+ code += asm.update_state(gen.movsd(argdst, src))
99
+ else
100
+ if inst == :mov and !src.is_a?(OpRegistor) then
101
+ code += asm.update_state(gen.send(inst, TMPR, src))
102
+ code += asm.update_state(gen.mov(argdst, TMPR))
103
+ else
104
+ code += asm.update_state(gen.mov(argdst, src))
105
+ end
106
+ end
107
+ end
108
+
109
+ if asm.retry_mode != :change_op then
110
+ # if retry mode fainfo.used_arg_tab is deleted
111
+ fainfo.used_arg_tab.last[@no] = @size
112
+ end
113
+ code
114
+ end
115
+
116
+ # Access the passing argument from caller
117
+ #
118
+ def gen_access_src(gen, inst, dst, src, src2)
119
+ asm = gen.asm
120
+ fainfo = gen.funcarg_info
121
+ code = ""
122
+ if @no < argpos2reg.size then
123
+ code += asm.update_state(gen.mov(TMPR, argpos2reg[@no]))
124
+ else
125
+ spos = @no - argpos2reg.size
126
+ offset = 8 + spos * 8
127
+ code += asm.update_state(gen.mov(TMPR, OpIndirect.new(SPR, offset)))
128
+ end
129
+ code += asm.update_state(gen.send(inst, src, TMPR))
130
+ code
131
+ end
132
+ end
133
+
134
+ module GeneratorExtendX64Mixin
135
+ include FuncArgX64CommonMixin
136
+
137
+ def mov64(dst, src)
138
+ case dst
139
+ when OpIndirect
140
+ case src
141
+ when Integer
142
+ disp = dst.disp
143
+ dst2 = dst.class.new(dst.reg, disp + 4)
144
+ bit32val = 1 << 32
145
+ code = mov(dst2, src / bit32val)
146
+ code += mov(dst, src % bit32val)
147
+ code
148
+ else
149
+ nosupported_addressing_mode(:mov64, dst, src)
150
+ end
151
+ else
152
+ nosupported_addressing_mode(:mov64, dst, src)
153
+ end
154
+ end
155
+
156
+ def call_with_arg_get_argsize(addr, argnum)
157
+ argnum * 8
158
+ end
159
+
160
+ def call_with_arg(addr, argnum, argsize)
161
+ fainfo = funcarg_info
162
+
163
+ orgaddress = @asm.current_address
164
+ code = ""
165
+ code += @asm.update_state(mov(RAX, OpImmidiate32.new(argnum)))
166
+ code += @asm.update_state(call(addr))
167
+ callpos = @asm.current_address - @asm.output_stream.base_address
168
+ if @asm.retry_mode != :change_op then
169
+ return [code, callpos]
170
+ end
171
+
172
+ offset = @funcarg_info.area_allocate_pos.pop
173
+ if offset then
174
+ imm = OpImmidiate8.new(argsize)
175
+ code += @asm.update_state(add(SPR, imm))
176
+ alloc_argument_area = lambda {
177
+ @asm.with_current_address(@asm.output_stream.base_address + offset) {
178
+ @asm.output_stream[offset] = sub(SPR, argsize)
179
+ }
180
+ }
181
+ @asm.after_patch_tab.push alloc_argument_area
182
+ end
183
+
184
+ @funcarg_info.update_maxargs(argnum)
185
+ @funcarg_info.used_arg_tab.pop
186
+
187
+ =begin
188
+ # Save already stored restorer
189
+ uat = @funcarg_info.used_arg_tab.last
190
+ while !fainfo.empty? do
191
+ nreg = fainfo.pop
192
+ if argpos = ARGPOS2REG.index(nreg) then
193
+ if uat[argpos] then
194
+ fainfo.push nreg
195
+ break
196
+ else
197
+ code += @asm.update_state(pop(nreg))
198
+ uat[argpos] = true
199
+ end
200
+ else
201
+ fainfo.push nreg
202
+ break
203
+ end
204
+ end
205
+ =end
206
+
207
+ @asm.current_address = orgaddress
208
+
209
+ [code, callpos]
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,128 @@
1
+ module YTLJit
2
+ module FunctionArgumentX86Mixin
3
+ include AbsArch
4
+
5
+ def size
6
+ case @abi_kind
7
+ when :c
8
+ AsmType::MACHINE_WORD.size
9
+
10
+ when :ytl
11
+ 8
12
+ end
13
+ end
14
+
15
+ def dst_opecode
16
+ OpIndirect.new(SPR, OpImmidiate8.new(@no * size))
17
+ end
18
+
19
+
20
+ def src_opecode
21
+ # AsmType::MACHINE_WORD.size is return address slot
22
+ offset = AsmType::MACHINE_WORD.size + @no * size
23
+ OpIndirect.new(SPR, offset)
24
+ end
25
+
26
+ def gen_access_dst(gen, inst, dst, src, src2)
27
+ argdst = dst_opecode
28
+ code = ""
29
+ asm = gen.asm
30
+ fainfo = gen.funcarg_info
31
+ if @no == 0 then
32
+ offset = asm.offset
33
+ code += asm.update_state(gen.sub(SPR, fainfo.maxargs * size))
34
+ fainfo.area_allocate_pos.push offset
35
+ fainfo.used_arg_tab.push Hash.new
36
+ end
37
+
38
+ if asm.retry_mode != :change_op then
39
+ # if retry mode fainfo.used_arg_tab is deleted
40
+ fainfo.used_arg_tab.last[@no] = size
41
+ end
42
+ if src.is_a?(OpRegXMM) then
43
+ code += asm.update_state(gen.movsd(argdst, src))
44
+ else
45
+ if inst == :mov and !src.is_a?(OpRegistor) then
46
+ code += asm.update_state(gen.send(inst, TMPR, src))
47
+ code += asm.update_state(gen.mov(argdst, TMPR))
48
+ else
49
+ code += asm.update_state(gen.mov(argdst, src))
50
+ end
51
+ end
52
+ code
53
+ end
54
+
55
+ # Access the passing argument from caller
56
+ # You can use only between entering the function and change value of
57
+ # stack pointer.
58
+ #
59
+ def gen_access_src(gen, inst, dst, src, src2)
60
+ asm = gen.asm
61
+ fainfo = gen.funcarg_info
62
+ code = ""
63
+ code += asm.update_state(gen.mov(TMPR, src_opecode))
64
+ code += asm.update_state(gen.send(inst, src, TMPR))
65
+ code
66
+ end
67
+ end
68
+
69
+ module GeneratorExtendX86Mixin
70
+ include AbsArch
71
+
72
+ def mov64(dst, src)
73
+ case dst
74
+ when OpIndirect
75
+ case src
76
+ when Integer
77
+ disp = dst.disp
78
+ dst2 = dst.class.new(dst.reg, disp + 4)
79
+ bit32val = 1 << 32
80
+ code = mov(dst2, src / bit32val)
81
+ code += mov(dst, src % bit32val)
82
+ code
83
+ else
84
+ nosupported_addressing_mode(:mov64, dst, src)
85
+ end
86
+ else
87
+ nosupported_addressing_mode(:mov64, dst, src)
88
+ end
89
+ end
90
+
91
+ def call_with_arg_get_argsize(addr, argnum)
92
+ argsize = 0
93
+ argnum.times do |i|
94
+ if @funcarg_info.used_arg_tab.last[i] then
95
+ argsize += @funcarg_info.used_arg_tab.last[i]
96
+ else
97
+ STDERR.print "Wanrnning arg not initialized -- #{i}\n"
98
+ argsize += 4
99
+ end
100
+ end
101
+ argsize
102
+ end
103
+
104
+ def call_with_arg(addr, argnum, argsize)
105
+ orgaddress = @asm.current_address
106
+ code = @asm.update_state(call(addr))
107
+ callpos = @asm.current_address - @asm.output_stream.base_address
108
+ if @asm.retry_mode == :change_op then
109
+ return [code, callpos]
110
+ end
111
+
112
+ code += @asm.update_state(add(SPR, OpImmidiate8.new(argsize)))
113
+ offset = @funcarg_info.area_allocate_pos.pop
114
+ alloc_argument_area = lambda {
115
+ asm.with_current_address(asm.output_stream.base_address + offset) {
116
+ asm.output_stream[offset] = sub(SPR, argsize)
117
+ }
118
+ }
119
+ asm.after_patch_tab.push alloc_argument_area
120
+
121
+ @funcarg_info.update_maxargs(argnum)
122
+ @funcarg_info.used_arg_tab.pop
123
+ @asm.current_address = orgaddress
124
+
125
+ [code, callpos]
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,182 @@
1
+ module YTLJit
2
+ module SSE
3
+ XMM0 = OpRXMM0.instance
4
+ XMM1 = OpRXMM1.instance
5
+ XMM2 = OpRXMM2.instance
6
+ XMM3 = OpRXMM3.instance
7
+ XMM4 = OpRXMM4.instance
8
+ XMM5 = OpRXMM5.instance
9
+ XMM6 = OpRXMM6.instance
10
+ XMM7 = OpRXMM7.instance
11
+ end
12
+
13
+ module SSE64
14
+ XMM8 = OpRXMM8.instance
15
+ XMM9 = OpRXMM9.instance
16
+ XMM10 = OpRXMM10.instance
17
+ XMM11 = OpRXMM11.instance
18
+ XMM12 = OpRXMM12.instance
19
+ XMM13 = OpRXMM13.instance
20
+ XMM14 = OpRXMM14.instance
21
+ XMM15 = OpRXMM15.instance
22
+ end
23
+
24
+ module X86
25
+ EAX = OpEAX.instance
26
+ EDX = OpEDX.instance
27
+ ECX = OpECX.instance
28
+ EBX = OpEBX.instance
29
+ ESP = OpESP.instance
30
+ EBP = OpEBP.instance
31
+ ESI = OpESI.instance
32
+ EDI = OpEDI.instance
33
+
34
+ AL = OpAL.instance
35
+ CL = OpCL.instance
36
+ DL = OpDL.instance
37
+ BL = OpBL.instance
38
+
39
+ INDIRECT_EAX = OpIndirect.new(EAX)
40
+ INDIRECT_EDX = OpIndirect.new(EDX)
41
+ INDIRECT_ECX = OpIndirect.new(ECX)
42
+ INDIRECT_EBX = OpIndirect.new(EBX)
43
+ INDIRECT_ESP = OpIndirect.new(ESP)
44
+ INDIRECT_EBP = OpIndirect.new(EBX)
45
+ INDIRECT_ESI = OpIndirect.new(ESI)
46
+ INDIRECT_EDI = OpIndirect.new(EDI)
47
+
48
+ include SSE
49
+ end
50
+
51
+ module X64
52
+ RAX = OpRAX.instance
53
+ RDX = OpRDX.instance
54
+ RCX = OpRCX.instance
55
+ RBX = OpRBX.instance
56
+ RSP = OpRSP.instance
57
+ RBP = OpRBP.instance
58
+ RSI = OpRSI.instance
59
+ RDI = OpRDI.instance
60
+
61
+ R8 = OpR8.instance
62
+ R9 = OpR9.instance
63
+ R10 = OpR10.instance
64
+ R11 = OpR11.instance
65
+ R12 = OpR12.instance
66
+ R13 = OpR13.instance
67
+ R14 = OpR14.instance
68
+ R15 = OpR15.instance
69
+
70
+ INDIRECT_RAX = OpIndirect.new(RAX)
71
+ INDIRECT_RDX = OpIndirect.new(RDX)
72
+ INDIRECT_RCX = OpIndirect.new(RCX)
73
+ INDIRECT_RBX = OpIndirect.new(RBX)
74
+ INDIRECT_RSP = OpIndirect.new(RSP)
75
+ INDIRECT_RBP = OpIndirect.new(RBX)
76
+ INDIRECT_RSI = OpIndirect.new(RSI)
77
+ INDIRECT_RDI = OpIndirect.new(RDI)
78
+
79
+ include SSE
80
+ include SSE64
81
+ end
82
+
83
+ module AbsArch
84
+ AL = OpAL.instance
85
+ CL = OpCL.instance
86
+ DL = OpDL.instance
87
+ BL = OpBL.instance
88
+
89
+ include SSE
90
+ case $ruby_platform
91
+ when /i.86/
92
+ TMPR = OpEAX.instance
93
+ TMPR2 = OpEDX.instance
94
+ TMPR3 = OpECX.instance
95
+ RETR = OpEAX.instance
96
+ SPR = OpESP.instance
97
+ BPR = OpEBP.instance
98
+ when /x86_64/
99
+ TMPR = OpRAX.instance
100
+ # TMPR2 = OpRDX.instance
101
+ # TMPR3 = OpRCX.instance
102
+ TMPR2 = OpR10.instance
103
+ TMPR3 = OpR11.instance
104
+ RETR = OpRAX.instance
105
+ SPR = OpRSP.instance
106
+ BPR = OpRBP.instance
107
+ end
108
+ INDIRECT_TMPR = OpIndirect.new(TMPR)
109
+ INDIRECT_TMPR2 = OpIndirect.new(TMPR2)
110
+ INDIRECT_RETR = OpIndirect.new(RETR)
111
+ INDIRECT_SPR = OpIndirect.new(SPR)
112
+ INDIRECT_BPR = OpIndirect.new(BPR)
113
+ FUNC_ARG = Hash.new {|hash, key|
114
+ hash[key] = FunctionArgumentInt.new(key, :c)
115
+ }
116
+ FUNC_FLOAT_ARG = Hash.new {|hash, key|
117
+ hash[key] = FunctionArgumentFloat.new(key, :c)
118
+ }
119
+ FUNC_ARG_YTL = Hash.new {|hash, key|
120
+ hash[key] = FunctionArgumentInt.new(key, :ytl)
121
+ }
122
+ FUNC_FLOAT_ARG_YTL = Hash.new {|hash, key|
123
+ hash[key] = FunctionArgumentFloat.new(key, :ytl)
124
+ }
125
+ end
126
+
127
+ module InternalRubyType
128
+ include AbsArch
129
+ VALUE = AsmType::MACHINE_WORD
130
+ P_CHAR = AsmType::Pointer.new(AsmType::INT8)
131
+
132
+ RBasic = AsmType::Struct.new(
133
+ VALUE, :flags,
134
+ VALUE, :klass
135
+ )
136
+ RString = AsmType::Struct.new(
137
+ RBasic, :basic,
138
+ AsmType::Union.new(
139
+ AsmType::Struct.new(
140
+ AsmType::INT32, :len,
141
+ P_CHAR, :ptr,
142
+ AsmType::Union.new(
143
+ AsmType::INT32, :capa,
144
+ VALUE, :shared,
145
+ ), :aux
146
+ ), :heap,
147
+ AsmType::Array.new(
148
+ AsmType::INT8,
149
+ 24
150
+ ), :ary
151
+ ), :as
152
+ )
153
+
154
+ RFloat = AsmType::Struct.new(
155
+ RBasic, :basic,
156
+ AsmType::DOUBLE, :float_value
157
+ )
158
+
159
+ EMBEDER_FLAG = (1 << 13)
160
+ def self.rstring_ptr(str, csstart, cscont)
161
+ cs_embed = CodeSpace.new
162
+
163
+ asm = Assembler.new(csstart)
164
+ rsstr = TypedData.new(InternalRubyType::RString, str)
165
+ # asm.step_mode = true
166
+ asm.with_retry do
167
+ asm.mov(TMPR, rsstr[:basic][:flags])
168
+ asm.and(TMPR, EMBEDER_FLAG)
169
+ asm.jz(cs_embed.var_base_address)
170
+ asm.mov(TMPR, rsstr[:as][:heap][:ptr])
171
+ asm.jmp(cscont.var_base_address)
172
+ end
173
+
174
+ asm = Assembler.new(cs_embed)
175
+ # asm.step_mode = true
176
+ asm.with_retry do
177
+ asm.mov(TMPR, rsstr[:as][:ary])
178
+ asm.jmp(cscont.var_base_address)
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,92 @@
1
+ module YTLJit
2
+ class CodeSpace
3
+ @@disasm_cache = {}
4
+ @@disasmed_codespace = {}
5
+ def self.disasm_cache
6
+ @@disasm_cache
7
+ end
8
+
9
+ def initialize
10
+ @refer_operands = []
11
+ reset
12
+ end
13
+
14
+ attr :disasm_cache
15
+ attr :refer_operands
16
+
17
+ def reset
18
+ @org_base_address = base_address
19
+ self.current_pos = 0
20
+ end
21
+
22
+ def emit(code)
23
+ self[self.current_pos] = code
24
+ end
25
+
26
+ def var_base_address(offset = 0)
27
+ func = lambda {
28
+ base_address + offset
29
+ }
30
+ ovi32 = OpVarMemAddress.new(func)
31
+ @refer_operands.push ovi32
32
+ ovi32
33
+ end
34
+
35
+ def var_base_immidiate_address(offset = 0)
36
+ func = lambda {
37
+ base_address + offset
38
+ }
39
+ ovi32 = OpVarImmidiateAddress.new(func)
40
+ @refer_operands.push ovi32
41
+ ovi32
42
+ end
43
+
44
+ def update_refer
45
+ @refer_operands.each do |refop|
46
+ refop.refer.each do |stfn|
47
+ stfn.call
48
+ end
49
+ end
50
+ end
51
+
52
+ def fill_disasm_cache
53
+ if @@disasmed_codespace[self] then
54
+ return
55
+ end
56
+ @@disasmed_codespace[self] = true
57
+ tmpfp = Tempfile.open("ytljitcode")
58
+ tmpfp.write code
59
+ tmpfp.close(false)
60
+ # quick dirty hack to work on Cygwin & Mac OS X/Core2Duo
61
+ # TODO: bdf and instruction set architecture should be automatically selected
62
+ case $ruby_platform
63
+ when /x86_64-darwin/
64
+ objcopy_cmd = "gobjcopy -I binary -O mach-o-i386 -B i386 --adjust-vma=#{base_address} #{tmpfp.path}"
65
+ objdump_cmd = "gobjdump -M x86-64 -D #{tmpfp.path}"
66
+
67
+ when /x86_64/
68
+ objcopy_cmd = "objcopy -I binary -O elf64-x86-64 -B i386 --adjust-vma=#{base_address} #{tmpfp.path}"
69
+ objdump_cmd = "objdump -M x86-64 -D #{tmpfp.path}"
70
+
71
+ when /i.86/
72
+ objcopy_cmd = "objcopy -I binary -O elf32-i386 -B i386 --adjust-vma=#{base_address} #{tmpfp.path}"
73
+ objdump_cmd = "objdump -M i386 -D #{tmpfp.path}"
74
+ end
75
+ system(objcopy_cmd)
76
+ File.popen(objdump_cmd, "r") {|fp|
77
+ fp.readlines.each do |lin|
78
+ if /([0-9a-f]*):(\t[0-9a-f ]+? *\t.*)/ =~ lin then
79
+ @@disasm_cache[$1] = $2
80
+ end
81
+ end
82
+ }
83
+ end
84
+
85
+ def disassemble
86
+ fill_disasm_cache
87
+ @@disasm_cache.each do |add, asm|
88
+ print "#{add}: #{asm}\n"
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,7 @@
1
+ module YTLJit
2
+ class AsmError<RuntimeError
3
+ end
4
+
5
+ class IlligalOperand<AsmError
6
+ end
7
+ end