evoasm 0.0.2.pre7 → 0.1.0.pre2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/.gdbinit +41 -0
  3. data/.gitignore +1 -2
  4. data/.gitmodules +3 -0
  5. data/.rubocop.yml +8 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.md +660 -0
  8. data/Makefile +1 -1
  9. data/README.md +17 -9
  10. data/Rakefile +39 -107
  11. data/bin/gdb +1 -1
  12. data/bin/gdb_loop +4 -0
  13. data/docs/FindingInstructions.md +17 -0
  14. data/docs/JIT.md +14 -0
  15. data/docs/SymbolicRegression.md +102 -0
  16. data/docs/Visualization.md +29 -0
  17. data/docs/examples/bit_insts.rb +44 -0
  18. data/docs/examples/jit.rb +26 -0
  19. data/docs/examples/loss.gif +0 -0
  20. data/docs/examples/program.png +0 -0
  21. data/docs/examples/sym_reg.rb +64 -0
  22. data/docs/examples/vis.rb +38 -0
  23. data/evoasm.gemspec +21 -15
  24. data/ext/evoasm_ext/Rakefile +3 -0
  25. data/ext/evoasm_ext/compile.rake +35 -0
  26. data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.c +226 -0
  27. data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.h +84 -0
  28. data/ext/evoasm_ext/libevoasm/src/evoasm-arch.c +52 -0
  29. data/ext/evoasm_ext/libevoasm/src/evoasm-arch.h +101 -0
  30. data/ext/evoasm_ext/libevoasm/src/evoasm-bitmap.h +158 -0
  31. data/ext/evoasm_ext/libevoasm/src/evoasm-buf.c +204 -0
  32. data/ext/evoasm_ext/libevoasm/src/evoasm-buf.h +109 -0
  33. data/ext/evoasm_ext/libevoasm/src/evoasm-domain.c +124 -0
  34. data/ext/evoasm_ext/libevoasm/src/evoasm-domain.h +279 -0
  35. data/ext/evoasm_ext/libevoasm/src/evoasm-error.c +65 -0
  36. data/ext/evoasm_ext/libevoasm/src/evoasm-error.h +108 -0
  37. data/ext/evoasm_ext/{evoasm-log.c → libevoasm/src/evoasm-log.c} +36 -18
  38. data/ext/evoasm_ext/libevoasm/src/evoasm-log.h +93 -0
  39. data/ext/evoasm_ext/libevoasm/src/evoasm-param.c +22 -0
  40. data/ext/evoasm_ext/libevoasm/src/evoasm-param.h +33 -0
  41. data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.c +192 -0
  42. data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.h +60 -0
  43. data/ext/evoasm_ext/libevoasm/src/evoasm-pop.c +1323 -0
  44. data/ext/evoasm_ext/libevoasm/src/evoasm-pop.h +107 -0
  45. data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.c +116 -0
  46. data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.h +60 -0
  47. data/ext/evoasm_ext/libevoasm/src/evoasm-program.c +1827 -0
  48. data/ext/evoasm_ext/libevoasm/src/evoasm-program.h +167 -0
  49. data/ext/evoasm_ext/libevoasm/src/evoasm-rand.c +65 -0
  50. data/ext/evoasm_ext/libevoasm/src/evoasm-rand.h +76 -0
  51. data/ext/evoasm_ext/libevoasm/src/evoasm-signal.c +106 -0
  52. data/ext/evoasm_ext/libevoasm/src/evoasm-signal.h +58 -0
  53. data/ext/evoasm_ext/libevoasm/src/evoasm-util.h +112 -0
  54. data/ext/evoasm_ext/libevoasm/src/evoasm-x64.c +925 -0
  55. data/ext/evoasm_ext/libevoasm/src/evoasm-x64.h +277 -0
  56. data/ext/evoasm_ext/libevoasm/src/evoasm.c +28 -0
  57. data/ext/evoasm_ext/libevoasm/src/evoasm.h +35 -0
  58. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-enums.h +2077 -0
  59. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.c +191203 -0
  60. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.h +1713 -0
  61. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.c +348 -0
  62. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.h +93 -0
  63. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.c +51 -0
  64. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.h +509 -0
  65. data/lib/evoasm.rb +28 -11
  66. data/lib/evoasm/buffer.rb +105 -0
  67. data/lib/evoasm/capstone.rb +100 -0
  68. data/lib/evoasm/domain.rb +116 -0
  69. data/lib/evoasm/error.rb +37 -16
  70. data/lib/evoasm/exception_error.rb +19 -0
  71. data/lib/evoasm/ffi_ext.rb +53 -0
  72. data/lib/evoasm/libevoasm.rb +286 -0
  73. data/lib/evoasm/libevoasm/x64_enums.rb +1967 -0
  74. data/lib/evoasm/parameter.rb +20 -0
  75. data/lib/evoasm/population.rb +145 -0
  76. data/lib/evoasm/population/parameters.rb +227 -0
  77. data/lib/evoasm/population/plotter.rb +89 -0
  78. data/lib/evoasm/prng.rb +64 -0
  79. data/lib/evoasm/program.rb +195 -12
  80. data/lib/evoasm/program/io.rb +144 -0
  81. data/lib/evoasm/test.rb +8 -0
  82. data/lib/evoasm/version.rb +1 -1
  83. data/lib/evoasm/x64.rb +115 -0
  84. data/lib/evoasm/x64/cpu_state.rb +95 -0
  85. data/lib/evoasm/x64/instruction.rb +109 -0
  86. data/lib/evoasm/x64/operand.rb +156 -0
  87. data/lib/evoasm/x64/parameters.rb +211 -0
  88. data/test/helpers/population_helper.rb +128 -0
  89. data/test/helpers/test_helper.rb +1 -0
  90. data/test/helpers/x64_helper.rb +24 -0
  91. data/test/integration/bitwise_reverse_test.rb +41 -0
  92. data/test/integration/gcd_test.rb +52 -0
  93. data/test/integration/popcnt_test.rb +46 -0
  94. data/test/integration/sym_reg_test.rb +68 -0
  95. data/test/unit/evoasm/buffer_test.rb +48 -0
  96. data/test/unit/evoasm/capstone_test.rb +18 -0
  97. data/test/unit/evoasm/domain_test.rb +55 -0
  98. data/test/unit/evoasm/population/parameters_test.rb +106 -0
  99. data/test/unit/evoasm/population_test.rb +96 -0
  100. data/test/unit/evoasm/prng_test.rb +47 -0
  101. data/test/unit/evoasm/x64/cpu_state_test.rb +73 -0
  102. data/test/unit/evoasm/x64/encoding_test.rb +320 -0
  103. data/test/unit/evoasm/x64/instruction_access_test.rb +177 -0
  104. data/test/unit/evoasm/x64/instruction_encoding_test.rb +780 -0
  105. data/test/unit/evoasm/x64/instruction_test.rb +62 -0
  106. data/test/unit/evoasm/x64/parameters_test.rb +65 -0
  107. data/test/unit/evoasm/x64_test.rb +52 -0
  108. metadata +195 -89
  109. data/Gemfile.rake +0 -8
  110. data/Gemfile.rake.lock +0 -51
  111. data/LICENSE.txt +0 -373
  112. data/data/tables/README.md +0 -19
  113. data/data/tables/x64.csv +0 -1684
  114. data/data/templates/evoasm-x64.c.erb +0 -319
  115. data/data/templates/evoasm-x64.h.erb +0 -126
  116. data/examples/abs.yml +0 -20
  117. data/examples/popcnt.yml +0 -17
  118. data/examples/sym_reg.yml +0 -26
  119. data/exe/evoasm-search +0 -13
  120. data/ext/evoasm_ext/evoasm-alloc.c +0 -145
  121. data/ext/evoasm_ext/evoasm-alloc.h +0 -59
  122. data/ext/evoasm_ext/evoasm-arch.c +0 -44
  123. data/ext/evoasm_ext/evoasm-arch.h +0 -161
  124. data/ext/evoasm_ext/evoasm-bitmap.h +0 -114
  125. data/ext/evoasm_ext/evoasm-buf.c +0 -130
  126. data/ext/evoasm_ext/evoasm-buf.h +0 -47
  127. data/ext/evoasm_ext/evoasm-error.c +0 -31
  128. data/ext/evoasm_ext/evoasm-error.h +0 -75
  129. data/ext/evoasm_ext/evoasm-free-list.c.tmpl +0 -121
  130. data/ext/evoasm_ext/evoasm-free-list.h.tmpl +0 -86
  131. data/ext/evoasm_ext/evoasm-log.h +0 -69
  132. data/ext/evoasm_ext/evoasm-misc.c +0 -23
  133. data/ext/evoasm_ext/evoasm-misc.h +0 -282
  134. data/ext/evoasm_ext/evoasm-param.h +0 -37
  135. data/ext/evoasm_ext/evoasm-search.c +0 -2145
  136. data/ext/evoasm_ext/evoasm-search.h +0 -214
  137. data/ext/evoasm_ext/evoasm-util.h +0 -40
  138. data/ext/evoasm_ext/evoasm-x64.c +0 -275624
  139. data/ext/evoasm_ext/evoasm-x64.h +0 -5436
  140. data/ext/evoasm_ext/evoasm.c +0 -7
  141. data/ext/evoasm_ext/evoasm.h +0 -23
  142. data/ext/evoasm_ext/evoasm_ext.c +0 -1757
  143. data/ext/evoasm_ext/extconf.rb +0 -31
  144. data/lib/evoasm/cli.rb +0 -6
  145. data/lib/evoasm/cli/search.rb +0 -127
  146. data/lib/evoasm/core_ext.rb +0 -1
  147. data/lib/evoasm/core_ext/array.rb +0 -9
  148. data/lib/evoasm/core_ext/integer.rb +0 -10
  149. data/lib/evoasm/core_ext/kwstruct.rb +0 -13
  150. data/lib/evoasm/core_ext/range.rb +0 -5
  151. data/lib/evoasm/examples.rb +0 -27
  152. data/lib/evoasm/gen.rb +0 -8
  153. data/lib/evoasm/gen/enum.rb +0 -169
  154. data/lib/evoasm/gen/name_util.rb +0 -80
  155. data/lib/evoasm/gen/state.rb +0 -176
  156. data/lib/evoasm/gen/state_dsl.rb +0 -152
  157. data/lib/evoasm/gen/strio.rb +0 -27
  158. data/lib/evoasm/gen/translator.rb +0 -1102
  159. data/lib/evoasm/gen/version.rb +0 -5
  160. data/lib/evoasm/gen/x64.rb +0 -237
  161. data/lib/evoasm/gen/x64/funcs.rb +0 -495
  162. data/lib/evoasm/gen/x64/inst.rb +0 -781
  163. data/lib/evoasm/search.rb +0 -40
  164. data/lib/evoasm/tasks/gen_task.rb +0 -86
  165. data/lib/evoasm/tasks/template_task.rb +0 -52
  166. data/test/test_helper.rb +0 -1
  167. data/test/x64/test_helper.rb +0 -19
  168. data/test/x64/x64_test.rb +0 -87
@@ -1,5 +0,0 @@
1
- module Evoasm
2
- module Gen
3
- VERSION = '0.0.1'
4
- end
5
- end
@@ -1,237 +0,0 @@
1
- module Evoasm::Gen
2
- module X64
3
- MNEM_BLACKLIST = %w()
4
-
5
- # RFLAGS either not used at all
6
- # or not read by any non-system instruction
7
- IGNORED_RFLAGS = %i(RF VIF AC VM NT TF DF IF AF)
8
-
9
- # Exception flag/mask bits. Mostly meant to be checked
10
- # by the user, which we are not doing at the moment
11
- IGNORED_MXCSR = %i(PE UE OE ME ZE DE IE PM UM OM ZM DM IM MM)
12
- REGISTERS = {
13
- ip: %i(IP),
14
- rflags: %i(OF SF ZF PF CF),
15
- mxcsr: %i(FZ RC DAZ),
16
- gp: %i(A C D B SP BP SI DI 8 9 10 11 12 13 14 15),
17
- mm: %i(MM0 MM1 MM2 MM3 MM4 MM5 MM6 MM7),
18
- xmm: %i(XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 XMM9 XMM10 XMM11 XMM12 XMM13 XMM14 XMM15),
19
- zmm: %i(ZMM16 ZMM17 ZMM18 ZMM19 ZMM20 ZMM21 ZMM22 ZMM23 ZMM24 ZMM25 ZMM26 ZMM27 ZMM28 ZMM29 ZMM30 ZMM31)
20
- }
21
-
22
- REGISTER_NAMES = REGISTERS.values.flatten
23
-
24
- CPUID = {
25
- [0x1, nil] => {
26
- d: %i(
27
- fpu
28
- vme
29
- de
30
- pse
31
- tsc
32
- msr
33
- pae
34
- mce
35
- cx8
36
- apic
37
- reserved
38
- sep
39
- mtrr
40
- pge
41
- mca
42
- cmov
43
- pat
44
- pse36
45
- psn
46
- clfsh
47
- reserved
48
- ds
49
- acpi
50
- mmx
51
- fxsr
52
- sse
53
- sse2
54
- ss
55
- htt
56
- tm
57
- ia64
58
- pbe),
59
- c: %i(
60
- sse3
61
- pclmulqdq
62
- dtes64
63
- monitor
64
- ds_cpl
65
- vmx
66
- smx
67
- est
68
- tm2
69
- ssse3
70
- cnxt_id
71
- sdbg
72
- fma
73
- cx16
74
- xtpr
75
- pdcm
76
- reserved
77
- pcid
78
- dca
79
- sse4_1
80
- sse4_2
81
- x2apic
82
- movbe
83
- popcnt
84
- tsc_deadline
85
- aes
86
- xsave
87
- osxsave
88
- avx
89
- f16c
90
- rdrnd
91
- hypervisor
92
- )
93
- },
94
- [0x7, 0x0] => {
95
- b: %i(
96
- fsgsbase
97
- IA32_TSC_ADJUST
98
- sgx
99
- bmi1
100
- hle
101
- avx2
102
- reserved
103
- smep
104
- bmi2
105
- erms
106
- invpcid
107
- rtm
108
- pqm
109
- FPU_CS_DS_DEPRECATED
110
- mpx
111
- pqe
112
- avx512f
113
- avx512dq
114
- rdseed
115
- adx
116
- smap
117
- avx512ifma
118
- pcommit
119
- clflushopt
120
- clwb
121
- avx512pf
122
- avx512er
123
- avx512cd
124
- sha
125
- avx512bw
126
- avx512vl
127
- ),
128
-
129
- c: %i(
130
- prefetchwt1
131
- avx512vbmi
132
- reserved
133
- reserved
134
- reserved
135
- reserved
136
- reserved
137
- reserved
138
- reserved
139
- reserved
140
- reserved
141
- reserved
142
- reserved
143
- reserved
144
- reserved
145
- reserved
146
- reserved
147
- reserved
148
- reserved
149
- reserved
150
- reserved
151
- reserved
152
- reserved
153
- reserved
154
- reserved
155
- reserved
156
- reserved
157
- reserved
158
- reserved
159
- reserved
160
- reserved
161
- reserved
162
- )
163
- },
164
-
165
- [0x80000001, nil] => {
166
- d: %i(
167
- fpu
168
- vme
169
- de
170
- pse
171
- tsc
172
- msr
173
- pae
174
- mce
175
- cx8
176
- apic
177
- reserved
178
- syscall
179
- mtrr
180
- pge
181
- mca
182
- cmov
183
- pat
184
- pse36
185
- reserved
186
- mp
187
- nx
188
- reserved
189
- mmxext
190
- mmx
191
- fxsr
192
- fxsr_opt
193
- pdpe1gb
194
- rdtscp
195
- reserved
196
- lm
197
- 3dnowext
198
- 3dnow
199
- ),
200
-
201
- c: %i(
202
- lahf_lm
203
- cmp_legacy
204
- svm
205
- extapic
206
- cr8_legacy
207
- abm
208
- sse4a
209
- misalignsse
210
- 3dnowprefetch
211
- osvw
212
- ibs
213
- xop
214
- skinit
215
- wdt
216
- reserved
217
- lwp
218
- fma4
219
- tce
220
- nodeid_msr
221
- reserved
222
- tbm
223
- topoext
224
- perfctr_core
225
- perfctr_nb
226
- reserved
227
- dbx
228
- perftsc
229
- pcx_l2i
230
- reserved
231
- reserved
232
- reserved
233
- )
234
- }
235
- }
236
- end
237
- end
@@ -1,495 +0,0 @@
1
- require 'evoasm/gen/state_dsl'
2
- require 'evoasm/core_ext/kwstruct'
3
-
4
- module Evoasm::Gen
5
- module X64
6
- VEX = KwStruct.new :rex_w, :reg_reg_param, :rm_reg_param, :vex_m, :vex_v, :vex_l, :vex_p do
7
- include StateDSL
8
-
9
- state def two_byte_vex
10
- state do
11
- log :trace, 'writing vex'
12
- write 0b11000101, 8
13
- write [
14
- [:neg, :rex_r],
15
- [:neg, vex_v || :vex_v],
16
- (vex_l || :vex_l),
17
- vex_p
18
- ], [1, 4, 1, 2]
19
- ret
20
- end
21
- end
22
-
23
- state def three_byte_vex
24
- state do
25
- log :trace, 'writing vex'
26
- write 0b11000100, 8
27
- write [[:neg, :rex_r],
28
- [:neg, :rex_x],
29
- [:neg, :rex_b],
30
- vex_m], [1, 1, 1, 5]
31
- write [rex_w || :rex_w,
32
- [:neg, vex_v || :vex_v],
33
- vex_l || :vex_l,
34
- vex_p], [1, 4, 1, 2]
35
- ret
36
- end
37
- end
38
-
39
- def zero_rex?
40
- cond =
41
- [:and,
42
- [:eq, :rex_x, 0b0],
43
- [:eq, :rex_b, 0b0]
44
- ]
45
-
46
- cond << [:eq, :rex_w, 0b0] unless rex_w == 0x0
47
-
48
- cond
49
- end
50
-
51
- state def root_state
52
- state do
53
- comment 'VEX'
54
-
55
- # assume rex_w and vex_l set
56
- # default unset 0 is ok for both
57
- if vex_m == 0x01 && rex_w != 0x1
58
- to_if :and, zero_rex?, [:false?, :force_long_vex?], two_byte_vex
59
- else_to three_byte_vex
60
- else
61
- to three_byte_vex
62
- end
63
- end
64
- end
65
- end
66
-
67
- REX = KwStruct.new :rex_w, :reg_reg_param, :rm_reg_param, :force, :rm_reg_type, :modrm do
68
- include StateDSL
69
-
70
- alias_method :modrm?, :modrm
71
- # reg_reg_param
72
- # and rm_reg_param
73
- # are REGISTERS
74
- # and NOT register ids
75
- # or bitfield values
76
-
77
- def rex_bit(reg)
78
- [:div, [:reg_code, reg], 8]
79
- end
80
-
81
- def base_or_index?
82
- modrm? && rm_reg_type != :reg
83
- end
84
-
85
- def need_rex?
86
- cond = [:or]
87
- cond << [:neq, rex_bit(reg_reg_param), 0] if reg_reg_param
88
- cond << [:and, [:set?, rm_reg_param], [:neq, rex_bit(rm_reg_param), 0]] if rm_reg_param
89
-
90
- cond << [:and, [:set?, :reg_base], [:neq, rex_bit(:reg_base), 0]] if base_or_index?
91
- cond << [:and, [:set?, :reg_index], [:neq, rex_bit(:reg_index), 0]] if base_or_index?
92
-
93
- cond == [:or] ? false : cond
94
- end
95
-
96
- state def rex_b
97
- state do
98
- log :trace, 'setting rex_b... modrm_rm='
99
-
100
- #FIXME: can REX.b ever be ignored ?
101
- #set :_rex_b, :rex_b
102
- #to write_rex
103
-
104
- rex_b_rm_reg = proc do
105
- set :_rex_b, rex_bit(rm_reg_param)
106
- to write_rex
107
- end
108
-
109
- rex_b_reg_reg = proc do
110
- set :_rex_b, rex_bit(reg_reg_param)
111
- to write_rex
112
- end
113
-
114
- rex_b_base_reg = proc do
115
- log :trace, 'setting rex_b from base'
116
- set :_rex_b, rex_bit(:reg_base)
117
- to write_rex
118
- end
119
-
120
- if !modrm?
121
- if reg_reg_param
122
- rex_b_reg_reg[]
123
- else
124
- fail
125
- end
126
- else
127
- case rm_reg_type
128
- when :reg
129
- log :trace, 'setting rex_b from modrm_rm'
130
- rex_b_rm_reg[]
131
- when :rm
132
- to_if :set?, :reg_base, &rex_b_base_reg
133
- else_to(&rex_b_rm_reg)
134
- when :mem
135
- rex_b_base_reg[]
136
- else
137
- fail
138
- end
139
- end
140
- end
141
- end
142
-
143
- state def rex_rx
144
- state do
145
- # MI and other encodings
146
- # do not use the MODRM.reg field
147
- # so the corresponding REX bit
148
- # is ignored
149
-
150
- set_rex_r_free = proc do
151
- set :_rex_r, :rex_r
152
- end
153
-
154
- rex_x_free = proc do
155
- set :_rex_x, :rex_x
156
- to rex_b
157
- end
158
-
159
- rex_x_index = proc do
160
- set :_rex_x, rex_bit(:reg_index)
161
- log :trace, 'rex_b... A'
162
- to rex_b
163
- end
164
-
165
- if modrm?
166
- if reg_reg_param
167
- set :_rex_r, rex_bit(reg_reg_param)
168
- else
169
- set_rex_r_free[]
170
- end
171
-
172
- case rm_reg_type
173
- when :reg
174
- rex_x_free[]
175
- when :rm
176
- to_if :set?, :reg_index, &rex_x_index
177
- else_to(&rex_x_free)
178
- when :mem
179
- rex_x_index[]
180
- else
181
- fail
182
- end
183
- else
184
- set_rex_r_free[]
185
- rex_x_free[]
186
- end
187
- end
188
- end
189
-
190
- state def root_state
191
- if force
192
- rex_rx
193
- else
194
- # rex?: output REX even if not force
195
- # need_rex?: REX is required (use of ext. reg.)
196
- state do
197
- to_if :or, [:true?, :force_rex?], need_rex?, rex_rx
198
- else_to do
199
- ret
200
- end
201
- end
202
- end
203
- end
204
-
205
- state def write_rex
206
- state do
207
- comment 'REX prefix'
208
- rex_w = self.rex_w
209
-
210
- # assume rex_w is set if the
211
- # attr rex_w is nil
212
- # unset default 0 is ok
213
- rex_w ||= :rex_w
214
-
215
- write [0b0100, rex_w, :_rex_r, :_rex_x, :_rex_b], [4, 1, 1, 1, 1]
216
- log :trace, 'writing rex % % % %', :rex_w, :_rex_r, :_rex_x, :_rex_b
217
-
218
- ret
219
- end
220
- end
221
- end
222
-
223
- ModRMSIB = KwStruct.new :reg_reg_param, :rm_reg_param, :rm_type, :modrm_reg, :rm_reg_access,
224
- :reg_reg_access do
225
- include StateDSL
226
-
227
- def reg_bits(reg, reg_code: false)
228
- reg_code = if reg_code
229
- reg
230
- else
231
- [:reg_code, reg]
232
- end
233
- [:mod, reg_code, 8]
234
- end
235
-
236
- def write_modrm(mod, rm)
237
- reg = if modrm_reg
238
- modrm_reg
239
- elsif reg_reg_param
240
- # register, use register parameter specified
241
- # in reg_reg_param
242
- reg_bits(reg_reg_param)
243
- else
244
- # ModRM.reg is free, use a parameter
245
- reg_bits(:modrm_reg, reg_code: true)
246
- end
247
-
248
- write [mod, reg, rm], [2, 3, 3]
249
- end
250
-
251
- def write_sib(scale = nil, index = nil, base = nil)
252
- write [
253
- scale || [:log2, :scale],
254
- index || reg_bits(:_reg_index),
255
- base || reg_bits(:reg_base)
256
- ], [2, 3, 3]
257
- end
258
-
259
- def zero_disp?
260
- # NOTE: unset disp defaults to 0 as well
261
- [:eq, :disp, 0]
262
- end
263
-
264
- def matching_disp_size?
265
- [:or, [:unset?, :disp_size], [:eq, :disp_size, [:disp_size]]]
266
- end
267
-
268
- def disp_fits?(size)
269
- [:ltq, [:disp_size], size]
270
- end
271
-
272
- def disp?(size)
273
- [:and,
274
- disp_fits?(size),
275
- matching_disp_size?
276
- ]
277
- end
278
-
279
- def vsib?
280
- rm_type == :vsib
281
- end
282
-
283
- def direct_only?
284
- rm_type == :reg
285
- end
286
-
287
- def indirect_only?
288
- rm_type == :mem
289
- end
290
-
291
- def modrm_sib_disp(rm:, sib:)
292
- to_if :and, zero_disp?,
293
- matching_disp_size?,
294
- [reg_code_not_in?(:reg_base, 5, 13)] do
295
- write_modrm 0b00, rm
296
- write_sib if sib
297
- ret
298
- end
299
- else_to do
300
- to_if :and, disp_fits?(8), [:false?, :force_disp32?] do
301
- write_modrm 0b01, rm
302
- write_sib if sib
303
- write :disp, 8
304
- ret
305
- end
306
- else_to do
307
- write_modrm 0b10, rm
308
- write_sib if sib
309
- write :disp, 32
310
- ret
311
- end
312
- end
313
- end
314
-
315
- state def _scale_index_base
316
- state do
317
- modrm_sib_disp rm: 0b100, sib: true
318
- end
319
- end
320
-
321
- def index_encodable?
322
- [:neq, [:reg_code, :reg_index], 0b0100]
323
- end
324
-
325
- state def scale_index_base
326
- state do
327
- log :trace, 'scale, index, base'
328
- set :_reg_index, :reg_index
329
-
330
- if vsib?
331
- to _scale_index_base
332
- else
333
- to_if index_encodable?, _scale_index_base
334
- else_to do
335
- # not encodable
336
- error :not_encodable, "index not encodable", param: :reg_index
337
- end
338
- end
339
- end
340
- end
341
-
342
- state def disp_only
343
- state do
344
- log :trace, 'disp only'
345
- set :_reg_index, :reg_index
346
- write_modrm 0b00, 0b100
347
- write_sib nil, nil, 0b101
348
- write :disp, 32
349
- ret
350
- end
351
- end
352
-
353
- state def index_only
354
- state do
355
- log :trace, 'index only'
356
-
357
- if vsib?
358
- cond = true
359
- else
360
- cond = index_encodable?
361
- end
362
-
363
- to_if cond do
364
- set :_reg_index, :reg_index
365
- write_modrm 0b00, 0b100
366
- write_sib nil, nil, 0b101
367
- write :disp, 32
368
- ret
369
- end
370
- if cond != true
371
- else_to do
372
- error :not_encodable, "index not encodable (0b0100)", param: :reg_index
373
- end
374
- end
375
- end
376
- end
377
-
378
- state def base_only_w_sib
379
- state do
380
- # need index to encode as 0b100 (RSP, ESP, SP)
381
- set :_reg_index, :SP
382
- to _scale_index_base
383
- end
384
- end
385
-
386
- def ip_base?
387
- [:eq, :reg_base, :IP]
388
- end
389
-
390
- def reg_code_not_in?(reg, *ids)
391
- [:not_in?, [:reg_code, reg], *ids]
392
- end
393
-
394
- state def base_only_wo_sib
395
- state do
396
- modrm_sib_disp rm: reg_bits(:reg_base), sib: false
397
- end
398
- end
399
-
400
- state def base_only
401
- state do
402
- log :trace, 'base only'
403
- to_if ip_base? do
404
- write_modrm 0b00, 0b101
405
- write :disp, 32
406
- ret
407
- end
408
- else_to do
409
- to_if :and, [:false?, :force_sib?], reg_code_not_in?(:reg_base, 4, 12), base_only_wo_sib
410
- else_to base_only_w_sib
411
- end
412
- end
413
- end
414
-
415
- def no_index?
416
- [:unset?, :reg_index]
417
- end
418
-
419
- def no_base?
420
- [:unset?, :reg_base]
421
- end
422
-
423
- state def indirect
424
- state do
425
- log :trace, 'indirect addressing'
426
- # VSIB does not allow to omit index
427
- if vsib?
428
- to_if no_base? do
429
- to_if :set?, :reg_index, index_only
430
- else_to do
431
- error :missing_param, param: :reg_index
432
- end
433
- end
434
- else_to scale_index_base
435
- else
436
- to_if no_base? do
437
- to_if no_index? do
438
- to_if :set?, :disp, disp_only
439
- else_to do
440
- error :missing_param, param: :disp
441
- end
442
- end
443
- else_to index_only
444
- end
445
- else_to do
446
- to_if no_index?, base_only
447
- else_to scale_index_base
448
- end
449
- end
450
- end
451
- end
452
-
453
- def direct
454
- state do
455
- access rm_reg_param, rm_reg_access if rm_reg_param
456
-
457
- write_modrm 0b11, reg_bits(rm_reg_param)
458
- ret
459
- end
460
- end
461
-
462
- def indirect?
463
- [:or,
464
- [:set?, :reg_base],
465
- [:set?, :reg_index],
466
- [:set?, :disp]
467
- ]
468
- end
469
-
470
- state def root_state
471
- state do
472
- comment 'ModRM'
473
- log :trace, 'ModRM'
474
-
475
- access reg_reg_param, reg_reg_access if reg_reg_param
476
-
477
- if direct_only?
478
- to direct
479
- else
480
- to_if indirect?, indirect
481
-
482
- # VSIB does not allow this
483
- if vsib? || indirect_only?
484
- else_to do
485
- error :not_encodable, (vsib? ? "VSIB does not allow indirect addressing" : "indirect addressing not allowed")
486
- end
487
- else
488
- else_to direct
489
- end
490
- end
491
- end
492
- end
493
- end
494
- end
495
- end