kompiler 0.0.0
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.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/bin/kompile +51 -0
- data/lib/kompiler/arch/armv8a/instructions.rb +490 -0
- data/lib/kompiler/arch/armv8a/load.rb +8 -0
- data/lib/kompiler/arch/armv8a/registers.rb +67 -0
- data/lib/kompiler/architecture.rb +30 -0
- data/lib/kompiler/compiler_functions.rb +262 -0
- data/lib/kompiler/directives.rb +167 -0
- data/lib/kompiler/mc_builder.rb +88 -0
- data/lib/kompiler/parsers.rb +508 -0
- data/lib/kompiler.rb +19 -0
- metadata +60 -0
@@ -0,0 +1,490 @@
|
|
1
|
+
# Copyright 2024 Kyrylo Shyshko
|
2
|
+
# Licensed under the Apache License, Version 2.0. See LICENSE file for details.
|
3
|
+
|
4
|
+
module Kompiler
|
5
|
+
|
6
|
+
class ARMv8A
|
7
|
+
|
8
|
+
def self.instructions
|
9
|
+
@@instructions
|
10
|
+
end
|
11
|
+
|
12
|
+
@@instructions = [
|
13
|
+
{ keyword: "mov",
|
14
|
+
operands: [{type: "register", restrictions: {reg_size: 64}}, {type: "immediate", restrictions: {}}],
|
15
|
+
mc_constructor: [
|
16
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
17
|
+
["get_bits", ["get_operand", 1], 0, 16],
|
18
|
+
["bits", 0,0, 1,0,1,0,0,1, 0,1, 1]
|
19
|
+
],
|
20
|
+
bitsize: 32
|
21
|
+
},
|
22
|
+
{ keyword: "mov",
|
23
|
+
operands: [{type: "register", restrictions: {reg_size: 64}}, {type: "register", restrictions: {reg_size: 64}}],
|
24
|
+
mc_constructor: [
|
25
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
|
26
|
+
["bits", 1,1,1,1,1], # rn
|
27
|
+
["bits", 0,0,0,0,0,0], # imm6
|
28
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rm
|
29
|
+
["bits", 0, 0,0, 0,1,0,1,0,1,0, 1]
|
30
|
+
],
|
31
|
+
bitsize: 32
|
32
|
+
},
|
33
|
+
{ keyword: "mov_sp",
|
34
|
+
operands: [{type: "register", restrictions: {reg_size: 64}}, {type: "register", restrictions: {reg_size: 64}}],
|
35
|
+
mc_constructor: [
|
36
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
|
37
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rn
|
38
|
+
["get_bits", 0, 0, 12], # imm12 as ones
|
39
|
+
["bits", 0, 0,1,0,0,0,1, 0, 0, 1]
|
40
|
+
],
|
41
|
+
bitsize: 32
|
42
|
+
},
|
43
|
+
{ keyword: "mvn", # MVN writes the bitwise opposite of the source register to a destination register
|
44
|
+
description: "MVN writes the bitwise opposite of the source register to the destination register",
|
45
|
+
operands: [{type: "register", restrictions: {reg_size: 64}, name: "Destination"}, {type: "register", restrictions: {reg_size: 64}, name: "Source"}],
|
46
|
+
mc_constructor: [
|
47
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
|
48
|
+
["bits", 1,1,1,1,1], # Rn
|
49
|
+
["bits", 0,0,0,0,0,0], # imm6 (shift amount) set to zero
|
50
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rm
|
51
|
+
["bits", 1, 0,0, 0,1,0,1,0,1,0, 1] # N - shift type (zero / LSL) - bits
|
52
|
+
],
|
53
|
+
bitsize: 32
|
54
|
+
},
|
55
|
+
{ keyword: "mvn", # MVN writes the bitwise opposite of the source register to a destination register
|
56
|
+
description: "MVN writes the bitwise opposite of the source register to the destination register",
|
57
|
+
operands: [{type: "register", restrictions: {reg_size: 32}, name: "Destination"}, {type: "register", restrictions: {reg_size: 32}, name: "Source"}],
|
58
|
+
mc_constructor: [
|
59
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
|
60
|
+
["bits", 1,1,1,1,1], # Rn
|
61
|
+
["bits", 0,0,0,0,0,0], # imm6 (shift amount) set to zero
|
62
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rm
|
63
|
+
["bits", 1, 0,0, 0,1,0,1,0,1,0, 0] # N - shift type (zero / LSL) - bits
|
64
|
+
],
|
65
|
+
bitsize: 32
|
66
|
+
},
|
67
|
+
{ keyword: "mov",
|
68
|
+
operands: [{type: "register", restrictions: {reg_size: 32}}, {type: "immediate", restrictions: {}}],
|
69
|
+
mc_constructor: [
|
70
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
71
|
+
["get_bits", ["get_operand", 1], 0, 16],
|
72
|
+
["bits", 0,0, 1,0,1,0,0,1, 0,1, 0]
|
73
|
+
],
|
74
|
+
bitsize: 32
|
75
|
+
},
|
76
|
+
{
|
77
|
+
keyword: "add",
|
78
|
+
operands: [{type: "register", restrictions: {reg_size: 64}}, {type: "register", restrictions: {reg_size: 64}}, {type: "immediate", restrictions: {}}],
|
79
|
+
mc_constructor: [
|
80
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
81
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
82
|
+
["get_bits", ["get_operand", 2], 0, 12],
|
83
|
+
["bits", 0, 0,1,0,0,0,1,0,0,1]
|
84
|
+
],
|
85
|
+
bitsize: 32
|
86
|
+
},
|
87
|
+
|
88
|
+
{
|
89
|
+
keyword: "add",
|
90
|
+
name: "ADD (registers)",
|
91
|
+
description: "Adds two source registers and writes the result to the destination register",
|
92
|
+
operands: [{type: "register", restrictions: {reg_size: 64}}, {type: "register", restrictions: {reg_size: 64}}, {type: "register", restrictions: {reg_size: 64}}],
|
93
|
+
mc_constructor: [
|
94
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
|
95
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rn
|
96
|
+
["get_bits", 0, 0, 6], # imm6
|
97
|
+
["get_bits", ["encode_gp_register", ["get_operand", 2]], 0, 5], # Rm
|
98
|
+
["bits", 0],
|
99
|
+
["bits", 0,0], # shift
|
100
|
+
["bits", 1,1,0,1,0, 0, 0, 1], # sf at the end
|
101
|
+
],
|
102
|
+
bitsize: 32
|
103
|
+
},
|
104
|
+
|
105
|
+
{
|
106
|
+
keyword: "and", # And between registers, with shift set to zero
|
107
|
+
name: "And",
|
108
|
+
description: "Computes a logical bit-wise AND operation between two registers and writes the result to the destination register.",
|
109
|
+
operands: [{type: "register", restrictions: {reg_size: 64}, name: "Destination"}, {type: "register", restrictions: {reg_size: 64}, name: "Register 1"}, {type: "register", restrictions: {reg_size: 64}, name: "Register 2"}],
|
110
|
+
mc_constructor: [
|
111
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
112
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
113
|
+
["get_bits", 0, 0, 6], # imm6 (shift amount) set to zero
|
114
|
+
["get_bits", ["encode_gp_register", ["get_operand", 2]], 0, 5],
|
115
|
+
["bits", 0], # N
|
116
|
+
["bits", 0,0], # shift type
|
117
|
+
["bits", 0,1,0,1,0, 0,0, 1],
|
118
|
+
],
|
119
|
+
bitsize: 32
|
120
|
+
},
|
121
|
+
|
122
|
+
{
|
123
|
+
keyword: "orr", # And between registers, with shift set to zero
|
124
|
+
name: "Or",
|
125
|
+
description: "Computes a logical bit-wise OR operation between two registers and writes the result to the destination register.",
|
126
|
+
operands: [{type: "register", restrictions: {reg_size: 64}, name: "Destination"}, {type: "register", restrictions: {reg_size: 64}, name: "Register 1"}, {type: "register", restrictions: {reg_size: 64}, name: "Register 2"}],
|
127
|
+
mc_constructor: [
|
128
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
129
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
130
|
+
["get_bits", 0, 0, 6], # imm6 (shift amount) set to zero
|
131
|
+
["get_bits", ["encode_gp_register", ["get_operand", 2]], 0, 5],
|
132
|
+
["bits", 0], # N
|
133
|
+
["bits", 0,0], # shift type
|
134
|
+
["bits", 0,1,0,1,0, 1,0, 1],
|
135
|
+
],
|
136
|
+
bitsize: 32
|
137
|
+
},
|
138
|
+
|
139
|
+
{
|
140
|
+
keyword: "adr",
|
141
|
+
operands: [{type: "register", restrictions: {reg_size: 64}}, {type: "label"}],
|
142
|
+
mc_constructor: [
|
143
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
144
|
+
["get_bits", ["subtract", ["get_label_address", ["get_operand", 1]], ["get_current_address"]], 2, 19],
|
145
|
+
["bits", 0,0,0,0,1],
|
146
|
+
["get_bits", ["subtract", ["get_label_address", ["get_operand", 1]], ["get_current_address"]], 0, 2],
|
147
|
+
["bits", 0],
|
148
|
+
],
|
149
|
+
bitsize: 32
|
150
|
+
},
|
151
|
+
{
|
152
|
+
keyword: "b",
|
153
|
+
operands: [{type: "immediate"}],
|
154
|
+
mc_constructor: [["get_bits", ["get_operand", 0], 0, 26], ["bits", 1,0,1,0,0,0]],
|
155
|
+
bitsize: 32
|
156
|
+
},
|
157
|
+
{
|
158
|
+
keyword: "b",
|
159
|
+
operands: [{type: "label"}],
|
160
|
+
mc_constructor: [
|
161
|
+
["if_eq_else", ["modulo", ["subtract", ["get_label_address", ["get_operand", 0]], ["get_current_address"]], 4], 0, [], ["raise_error", "Can't branch to the address - offset not divisible by 4 bytes."]], # Check if address is accessible
|
162
|
+
["get_bits", ["divide", ["subtract", ["get_label_address", ["get_operand", 0]], ["get_current_address"]], 4], 0, 26],
|
163
|
+
["bits", 1,0,1,0,0,0]
|
164
|
+
],
|
165
|
+
bitsize: 32
|
166
|
+
},
|
167
|
+
{
|
168
|
+
keyword: "br",
|
169
|
+
operands: [{type: "register", restrictions: {reg_size: 64}}],
|
170
|
+
mc_constructor: [
|
171
|
+
["bits", 0,0,0,0,0],
|
172
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
173
|
+
["bits", 0, 0, 0,0,0,0, 1,1,1,1,1, 0,0, 0, 0, 1,1,0,1,0,1,1]
|
174
|
+
],
|
175
|
+
bitsize: 32
|
176
|
+
},
|
177
|
+
{
|
178
|
+
keyword: "bl",
|
179
|
+
operands: [{type: "label"}],
|
180
|
+
mc_constructor: [
|
181
|
+
["if_eq_else", ["modulo", ["subtract", ["get_label_address", ["get_operand", 0]], ["get_current_address"]], 4], 0, [], ["raise_error", "Can't branch to the address - offset not divisible by 4 bytes."]], # Check if address is accessible
|
182
|
+
["get_bits", ["divide", ["subtract", ["get_label_address", ["get_operand", 0]], ["get_current_address"]], 4], 0, 26],
|
183
|
+
["bits", 1,0,1,0,0,1]
|
184
|
+
],
|
185
|
+
bitsize: 32
|
186
|
+
},
|
187
|
+
{
|
188
|
+
# LSL (Logical shift left) with an immediate
|
189
|
+
# immr (rotation) is just set to zeros
|
190
|
+
keyword: "lsl",
|
191
|
+
name: "LSL (immediate)",
|
192
|
+
description: "Logically shifts left the value in the source register by the amount specified by the immediate, and stores the output in the destination register",
|
193
|
+
operands: [{type: "register", restrictions: {reg_size: 64}, name: "Destination"}, {type: "register", restrictions: {reg_size: 64}, name: "Source"}, {type: "immediate", name: "Amount"}],
|
194
|
+
mc_constructor: [
|
195
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
196
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
197
|
+
|
198
|
+
["get_bits", ["subtract", 63, ["get_operand", 2]], 0, 6],
|
199
|
+
["get_bits", ["modulo", ["multiply", ["get_operand", 2], -1], 64], 0, 6],
|
200
|
+
|
201
|
+
["bits", 1, 0,1,1,0,0,1, 0,1, 1],
|
202
|
+
],
|
203
|
+
bitsize: 32
|
204
|
+
},
|
205
|
+
{
|
206
|
+
# LSL (Logical shift left) with an immediate for 32-bit registers
|
207
|
+
# immr (rotation) is just set to zeros
|
208
|
+
keyword: "lsl",
|
209
|
+
name: "LSL (immediate)",
|
210
|
+
description: "Logically shifts left the value in the source register by the amount specified by the immediate, and stores the output in the destination register",
|
211
|
+
operands: [{type: "register", restrictions: {reg_size: 32}, name: "Destination"}, {type: "register", restrictions: {reg_size: 32}, name: "Source"}, {type: "immediate", name: "Amount"}],
|
212
|
+
mc_constructor: [
|
213
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
214
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
215
|
+
["get_bits", ["subtract", 31, ["get_operand", 2]], 0, 6],
|
216
|
+
["get_bits", ["modulo", ["multiply", ["get_operand", 2], -1], 32], 0, 6],
|
217
|
+
["bits", 0, 0,1,1,0,0,1, 0,1, 0],
|
218
|
+
],
|
219
|
+
bitsize: 32
|
220
|
+
},
|
221
|
+
|
222
|
+
|
223
|
+
|
224
|
+
{
|
225
|
+
# LSL (Logical shift left) with an immediate
|
226
|
+
# immr (rotation) is just set to zeros
|
227
|
+
keyword: "lsr",
|
228
|
+
name: "LSR (immediate)",
|
229
|
+
description: "Logically shifts right the value in the source register by the amount specified by the immediate, and stores the output in the destination register",
|
230
|
+
operands: [{type: "register", restrictions: {reg_size: 64}, name: "Destination"}, {type: "register", restrictions: {reg_size: 64}, name: "Source"}, {type: "immediate", name: "Amount"}],
|
231
|
+
mc_constructor: [
|
232
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
233
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
234
|
+
|
235
|
+
["bits", 1,1,1,1,1], # imms
|
236
|
+
["bits", 1], # imms end (specifies size)
|
237
|
+
["get_bits", ["get_operand", 2], 0, 6], # immr
|
238
|
+
|
239
|
+
["bits", 1, 0,1,1,0,0,1, 0,1, 1],
|
240
|
+
],
|
241
|
+
bitsize: 32
|
242
|
+
},
|
243
|
+
{
|
244
|
+
keyword: "lsr",
|
245
|
+
name: "LSR (immediate)",
|
246
|
+
description: "Logically shifts right the value in the source register by the amount specified by the immediate, and stores the output in the destination register",
|
247
|
+
operands: [{type: "register", restrictions: {reg_size: 32}, name: "Destination"}, {type: "register", restrictions: {reg_size: 32}, name: "Source"}, {type: "immediate", name: "Amount"}],
|
248
|
+
mc_constructor: [
|
249
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
250
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
251
|
+
|
252
|
+
["bits", 1,1,1,1,1], # imms
|
253
|
+
["bits", 0], # imms end (specifies size)
|
254
|
+
["get_bits", ["get_operand", 2], 0, 6], # immr
|
255
|
+
|
256
|
+
["bits", 0, 0,1,1,0,0,1, 0,1, 0],
|
257
|
+
],
|
258
|
+
bitsize: 32
|
259
|
+
},
|
260
|
+
|
261
|
+
|
262
|
+
|
263
|
+
|
264
|
+
{
|
265
|
+
# LDR immediate
|
266
|
+
keyword: "ldr",
|
267
|
+
operands: [{type: "register", restrictions: {reg_size: 64}}, {type: "label"}],
|
268
|
+
mc_constructor: [
|
269
|
+
["if_eq_else", ["modulo", ["subtract", ["get_label_address", ["get_operand", 1]], ["get_current_address"]], 4], 0, [], ["raise_error", "Can't represent address for LDR - offset not divisible by 4 bytes."]], # Check if address is accessible
|
270
|
+
|
271
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
272
|
+
["get_bits", ["divide", ["subtract", ["get_label_address", ["get_operand", 1]], ["get_current_address"]], 4], 0, 19],
|
273
|
+
|
274
|
+
["bits", 0,0,0,1,1,0,1,0],
|
275
|
+
],
|
276
|
+
bitsize: 32
|
277
|
+
},
|
278
|
+
{
|
279
|
+
keyword: "ldr",
|
280
|
+
operands: [{type: "register", restrictions: {reg_size: 64}}, {type: "register", restrictions: {reg_size: 64}}],
|
281
|
+
mc_constructor: [
|
282
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
283
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
284
|
+
["get_bits", 0, 0, 12], # Immediate offset zero
|
285
|
+
["bits", 1,0, 1,0, 0, 1,1,1, 1,1],
|
286
|
+
],
|
287
|
+
bitsize: 32
|
288
|
+
},
|
289
|
+
{
|
290
|
+
keyword: "ldr",
|
291
|
+
operands: [{type: "register", restrictions: {reg_size: 32}}, {type: "register", restrictions: {reg_size: 64}}],
|
292
|
+
mc_constructor: [
|
293
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
294
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
295
|
+
["get_bits", 0, 0, 12], # Immediate offset zero
|
296
|
+
["bits", 1,0, 1,0, 0, 1,1,1, 0,1],
|
297
|
+
],
|
298
|
+
bitsize: 32
|
299
|
+
},
|
300
|
+
{
|
301
|
+
keyword: "strh",
|
302
|
+
operands: [{type: "register", restrictions: {reg_size: 32}}, {type: "register", restrictions: {reg_size: 64}}],
|
303
|
+
mc_constructor: [
|
304
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
305
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
306
|
+
["get_bits", 0, 0, 12], # Immediate offset zero
|
307
|
+
["bits", 0,0, 1,0, 0, 1,1,1, 1,0],
|
308
|
+
],
|
309
|
+
bitsize: 32
|
310
|
+
},
|
311
|
+
{
|
312
|
+
keyword: "str",
|
313
|
+
description: "Stores the contents of a 32 bit register at the address specified by the second register",
|
314
|
+
operands: [{type: "register", restrictions: {reg_size: 32}, name: "Content"}, {type: "register", restrictions: {reg_size: 64}, name: "Address"}],
|
315
|
+
mc_constructor: [
|
316
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
317
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
318
|
+
["get_bits", 0, 0, 12], # Immediate offset zero
|
319
|
+
["bits", 0,0, 1,0, 0, 1,1,1, 0,1],
|
320
|
+
],
|
321
|
+
bitsize: 32
|
322
|
+
},
|
323
|
+
{
|
324
|
+
keyword: "str",
|
325
|
+
description: "Stores the contents of a 64 bit register at the address specified by the second register",
|
326
|
+
operands: [{type: "register", restrictions: {reg_size: 64}, name: "Content"}, {type: "register", restrictions: {reg_size: 64}, name: "Address"}],
|
327
|
+
mc_constructor: [
|
328
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
329
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
330
|
+
["get_bits", 0, 0, 12], # Immediate offset zero
|
331
|
+
["bits", 0,0, 1,0, 0, 1,1,1, 1,1],
|
332
|
+
],
|
333
|
+
bitsize: 32
|
334
|
+
},
|
335
|
+
|
336
|
+
{
|
337
|
+
keyword: "str_unsigned",
|
338
|
+
name: "STR (immediate), unsigned offset",
|
339
|
+
description: "Stores the contents of a 32 bit register at the address specified by the second register with an unsigned immediate offset.",
|
340
|
+
operands: [{type: "register", restrictions: {reg_size: 32}, name: "Content"}, {type: "register", restrictions: {reg_size: 64}, name: "Address"}, {type: "immediate", name: "Address Offset"}],
|
341
|
+
mc_constructor: [
|
342
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
343
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
344
|
+
["get_bits", ["get_operand", 2], 0, 12], # Immediate offset zero
|
345
|
+
["bits", 0,0, 1,0, 0, 1,1,1, 0,1],
|
346
|
+
],
|
347
|
+
bitsize: 32
|
348
|
+
},
|
349
|
+
|
350
|
+
{
|
351
|
+
keyword: "str_unsigned",
|
352
|
+
name: "STR (immediate), unsigned offset",
|
353
|
+
description: "Stores the contents of a 64 bit register at the address specified by the second register with an unsigned immediate offset.",
|
354
|
+
operands: [{type: "register", restrictions: {reg_size: 64}, name: "Content"}, {type: "register", restrictions: {reg_size: 64}, name: "Address"}, {type: "immediate", name: "Address Offset"}],
|
355
|
+
mc_constructor: [
|
356
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
357
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
358
|
+
["get_bits", ["get_operand", 2], 0, 12], # Immediate offset zero
|
359
|
+
["bits", 0,0, 1,0, 0, 1,1,1, 1,1],
|
360
|
+
],
|
361
|
+
bitsize: 32
|
362
|
+
},
|
363
|
+
|
364
|
+
{
|
365
|
+
keyword: "str_pre_index",
|
366
|
+
name: "STR (immediate), signed offset, pre-index",
|
367
|
+
description: "Stores the contents of a 64-bit register at the address specified by the second register with a signed immediate offset that is added before storing.",
|
368
|
+
operands: [{type: "register", restrictions: {reg_size: 64}, name: "Content"}, {type: "register", restrictions: {reg_size: 64}, name: "Address"}, {type: "immediate", name: "Address Offset"}],
|
369
|
+
mc_constructor: [
|
370
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
371
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
372
|
+
["bits", 1, 1],
|
373
|
+
["get_bits", ["get_operand", 2], 0, 9],
|
374
|
+
["bits", 0, 0,0, 0,0, 0, 1,1,1, 1,1],
|
375
|
+
],
|
376
|
+
bitsize: 32
|
377
|
+
},
|
378
|
+
|
379
|
+
{
|
380
|
+
keyword: "str_pre_index",
|
381
|
+
name: "STR (immediate), signed offset, pre-index",
|
382
|
+
description: "Stores the contents of a 32-bit register at the address specified by the second register with a signed immediate offset that is added before storing.",
|
383
|
+
operands: [{type: "register", restrictions: {reg_size: 32}, name: "Content"}, {type: "register", restrictions: {reg_size: 64}, name: "Address"}, {type: "immediate", name: "Address Offset"}],
|
384
|
+
mc_constructor: [
|
385
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
386
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
387
|
+
["bits", 1, 1],
|
388
|
+
["get_bits", ["get_operand", 2], 0, 9],
|
389
|
+
["bits", 0, 0,0, 0,0, 0, 1,1,1, 0,1],
|
390
|
+
],
|
391
|
+
bitsize: 32
|
392
|
+
},
|
393
|
+
|
394
|
+
|
395
|
+
{
|
396
|
+
keyword: "cmp",
|
397
|
+
operands: [{type: "register", restrictions: {reg_size: 64}}, {type: "immediate"}],
|
398
|
+
mc_constructor: [
|
399
|
+
["bits", 1,1,1,1,1],
|
400
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
401
|
+
["get_bits", ["get_operand", 1], 0, 12], # Immediate offset zero
|
402
|
+
["bits", 0, 0,1,0,0,0,1, 1, 1, 1],
|
403
|
+
],
|
404
|
+
bitsize: 32
|
405
|
+
},
|
406
|
+
|
407
|
+
{
|
408
|
+
keyword: "cmp",
|
409
|
+
name: "CMP (two registers)",
|
410
|
+
description: "Compares two 64-bit registers and updates condition flags based on the result.",
|
411
|
+
operands: [{type: "register", restrictions: {reg_size: 64}, name: "Register 1"}, {type: "register", restrictions: {reg_size: 64}, name: "Register 2"}],
|
412
|
+
mc_constructor: [
|
413
|
+
["bits", 1,1,1,1,1], # Rd
|
414
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
415
|
+
["get_bits", 0, 0, 6], # Immediate offset zero (shift amount)
|
416
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rm
|
417
|
+
["bits", 0],
|
418
|
+
["bits", 0, 0], # Shift type
|
419
|
+
["bits", 1,1,0,1,0,1,1,1],
|
420
|
+
],
|
421
|
+
bitsize: 32
|
422
|
+
},
|
423
|
+
|
424
|
+
{
|
425
|
+
keyword: "cmp",
|
426
|
+
name: "CMP (two registers)",
|
427
|
+
description: "Compares two 32-bit registers and updates condition flags based on the result.",
|
428
|
+
operands: [{type: "register", restrictions: {reg_size: 32}, name: "Register 1"}, {type: "register", restrictions: {reg_size: 32}, name: "Register 2"}],
|
429
|
+
mc_constructor: [
|
430
|
+
["bits", 1,1,1,1,1], # Rd
|
431
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
432
|
+
["get_bits", 0, 0, 6], # Immediate offset zero (shift amount)
|
433
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rm
|
434
|
+
["bits", 0],
|
435
|
+
["bits", 0, 0], # Shift type
|
436
|
+
["bits", 1,1,0,1,0,1,1,0],
|
437
|
+
],
|
438
|
+
bitsize: 32
|
439
|
+
},
|
440
|
+
|
441
|
+
{
|
442
|
+
keyword: "sub",
|
443
|
+
operands: [{type: "register", restrictions: {reg_size: 64}}, {type: "register", restrictions: {reg_size: 64}}, {type: "immediate"}],
|
444
|
+
mc_constructor: [
|
445
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
446
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
447
|
+
["get_bits", ["get_operand", 2], 0, 12], # Immediate offset zero
|
448
|
+
["bits", 0], # Shift
|
449
|
+
["bits", 0,1,0,0,0,1,0,1,1],
|
450
|
+
],
|
451
|
+
bitsize: 32
|
452
|
+
},
|
453
|
+
|
454
|
+
|
455
|
+
|
456
|
+
#
|
457
|
+
# B.cond instructions
|
458
|
+
#
|
459
|
+
|
460
|
+
{
|
461
|
+
keyword: "b.eq",
|
462
|
+
name: "Branch with condition",
|
463
|
+
description: "Branches to a label if the condition (equality) is met",
|
464
|
+
operands: [{type: "label"}],
|
465
|
+
mc_constructor: [
|
466
|
+
["if_eq_else", ["modulo", ["subtract", ["get_label_address", ["get_operand", 0]], ["get_current_address"]], 4], 0, [], ["raise_error", "Can't branch to the address - offset not divisible by 4 bytes."]], # Check if address is accessible
|
467
|
+
["bits", 0,0,0,0], # eq condition
|
468
|
+
["bits", 0],
|
469
|
+
["get_bits", ["divide", ["subtract", ["get_label_address", ["get_operand", 0]], ["get_current_address"]], 4], 0, 19],
|
470
|
+
["bits", 0, 0,1,0,1,0,1,0],
|
471
|
+
],
|
472
|
+
bitsize: 32
|
473
|
+
},
|
474
|
+
{
|
475
|
+
keyword: "b.eq",
|
476
|
+
operands: [{type: "immediate"}],
|
477
|
+
description: "Changes the PC relatively by the immediate value if the condition is met (equality)",
|
478
|
+
mc_constructor: [
|
479
|
+
["bits", 0,0,0,0], # eq condition
|
480
|
+
["bits", 0],
|
481
|
+
["get_bits", ["get_operand", 0], 0, 19],
|
482
|
+
["bits", 0, 0,1,0,1,0,1,0],
|
483
|
+
],
|
484
|
+
bitsize: 32
|
485
|
+
},
|
486
|
+
]
|
487
|
+
|
488
|
+
end # Kompiler::ARMv8A
|
489
|
+
|
490
|
+
end # Kompiler
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Copyright 2024 Kyrylo Shyshko
|
2
|
+
# Licensed under the Apache License, Version 2.0. See LICENSE file for details.
|
3
|
+
|
4
|
+
require 'kompiler/arch/armv8a/instructions.rb'
|
5
|
+
require 'kompiler/arch/armv8a/registers.rb'
|
6
|
+
|
7
|
+
|
8
|
+
Kompiler::Architecture.set_arch(Kompiler::ARMv8A.instructions, Kompiler::ARMv8A.registers)
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# Copyright 2024 Kyrylo Shyshko
|
2
|
+
# Licensed under the Apache License, Version 2.0. See LICENSE file for details.
|
3
|
+
|
4
|
+
module Kompiler
|
5
|
+
|
6
|
+
class ARMv8A
|
7
|
+
|
8
|
+
def self.registers
|
9
|
+
@@registers
|
10
|
+
end
|
11
|
+
|
12
|
+
@@registers = [
|
13
|
+
{:reg_name=>"w0", :reg_value=>0, :reg_size=>32, :reg_type=>"gpr"},
|
14
|
+
{:reg_name=>"w1", :reg_value=>1, :reg_size=>32, :reg_type=>"gpr"},
|
15
|
+
{:reg_name=>"w2", :reg_value=>2, :reg_size=>32, :reg_type=>"gpr"},
|
16
|
+
{:reg_name=>"w3", :reg_value=>3, :reg_size=>32, :reg_type=>"gpr"},
|
17
|
+
{:reg_name=>"w4", :reg_value=>4, :reg_size=>32, :reg_type=>"gpr"},
|
18
|
+
{:reg_name=>"w5", :reg_value=>5, :reg_size=>32, :reg_type=>"gpr"},
|
19
|
+
{:reg_name=>"w6", :reg_value=>6, :reg_size=>32, :reg_type=>"gpr"},
|
20
|
+
{:reg_name=>"w7", :reg_value=>7, :reg_size=>32, :reg_type=>"gpr"},
|
21
|
+
{:reg_name=>"w8", :reg_value=>8, :reg_size=>32, :reg_type=>"gpr"},
|
22
|
+
{:reg_name=>"w9", :reg_value=>9, :reg_size=>32, :reg_type=>"gpr"},
|
23
|
+
{:reg_name=>"w10", :reg_value=>10, :reg_size=>32, :reg_type=>"gpr"},
|
24
|
+
{:reg_name=>"w11", :reg_value=>11, :reg_size=>32, :reg_type=>"gpr"},
|
25
|
+
{:reg_name=>"w12", :reg_value=>12, :reg_size=>32, :reg_type=>"gpr"},
|
26
|
+
{:reg_name=>"w13", :reg_value=>13, :reg_size=>32, :reg_type=>"gpr"},
|
27
|
+
{:reg_name=>"w14", :reg_value=>14, :reg_size=>32, :reg_type=>"gpr"},
|
28
|
+
{:reg_name=>"w15", :reg_value=>15, :reg_size=>32, :reg_type=>"gpr"},
|
29
|
+
{:reg_name=>"x0", :reg_value=>0, :reg_size=>64, :reg_type=>"gpr"},
|
30
|
+
{:reg_name=>"x1", :reg_value=>1, :reg_size=>64, :reg_type=>"gpr"},
|
31
|
+
{:reg_name=>"x2", :reg_value=>2, :reg_size=>64, :reg_type=>"gpr"},
|
32
|
+
{:reg_name=>"x3", :reg_value=>3, :reg_size=>64, :reg_type=>"gpr"},
|
33
|
+
{:reg_name=>"x4", :reg_value=>4, :reg_size=>64, :reg_type=>"gpr"},
|
34
|
+
{:reg_name=>"x5", :reg_value=>5, :reg_size=>64, :reg_type=>"gpr"},
|
35
|
+
{:reg_name=>"x6", :reg_value=>6, :reg_size=>64, :reg_type=>"gpr"},
|
36
|
+
{:reg_name=>"x7", :reg_value=>7, :reg_size=>64, :reg_type=>"gpr"},
|
37
|
+
{:reg_name=>"x8", :reg_value=>8, :reg_size=>64, :reg_type=>"gpr"},
|
38
|
+
{:reg_name=>"x9", :reg_value=>9, :reg_size=>64, :reg_type=>"gpr"},
|
39
|
+
{:reg_name=>"x10", :reg_value=>10, :reg_size=>64, :reg_type=>"gpr"},
|
40
|
+
{:reg_name=>"x11", :reg_value=>11, :reg_size=>64, :reg_type=>"gpr"},
|
41
|
+
{:reg_name=>"x12", :reg_value=>12, :reg_size=>64, :reg_type=>"gpr"},
|
42
|
+
{:reg_name=>"x13", :reg_value=>13, :reg_size=>64, :reg_type=>"gpr"},
|
43
|
+
{:reg_name=>"x14", :reg_value=>14, :reg_size=>64, :reg_type=>"gpr"},
|
44
|
+
{:reg_name=>"x15", :reg_value=>15, :reg_size=>64, :reg_type=>"gpr"},
|
45
|
+
{:reg_name=>"x16", :reg_value=>16, :reg_size=>64, :reg_type=>"gpr"},
|
46
|
+
{:reg_name=>"x17", :reg_value=>17, :reg_size=>64, :reg_type=>"gpr"},
|
47
|
+
{:reg_name=>"x18", :reg_value=>18, :reg_size=>64, :reg_type=>"gpr"},
|
48
|
+
{:reg_name=>"x19", :reg_value=>19, :reg_size=>64, :reg_type=>"gpr"},
|
49
|
+
{:reg_name=>"x20", :reg_value=>20, :reg_size=>64, :reg_type=>"gpr"},
|
50
|
+
{:reg_name=>"x21", :reg_value=>21, :reg_size=>64, :reg_type=>"gpr"},
|
51
|
+
{:reg_name=>"x22", :reg_value=>22, :reg_size=>64, :reg_type=>"gpr"},
|
52
|
+
{:reg_name=>"x23", :reg_value=>23, :reg_size=>64, :reg_type=>"gpr"},
|
53
|
+
{:reg_name=>"x24", :reg_value=>24, :reg_size=>64, :reg_type=>"gpr"},
|
54
|
+
{:reg_name=>"x25", :reg_value=>25, :reg_size=>64, :reg_type=>"gpr"},
|
55
|
+
{:reg_name=>"x26", :reg_value=>26, :reg_size=>64, :reg_type=>"gpr"},
|
56
|
+
{:reg_name=>"x27", :reg_value=>27, :reg_size=>64, :reg_type=>"gpr"},
|
57
|
+
{:reg_name=>"x28", :reg_value=>28, :reg_size=>64, :reg_type=>"gpr"},
|
58
|
+
{:reg_name=>"x29", :reg_value=>29, :reg_size=>64, :reg_type=>"gpr"},
|
59
|
+
{:reg_name=>"x30", :reg_value=>30, :reg_size=>64, :reg_type=>"gpr"},
|
60
|
+
{:reg_name=>"x31", :reg_value=>31, :reg_size=>64, :reg_type=>"gpr"},
|
61
|
+
{:reg_name=>"lr", :reg_value=>30, :reg_size=>64, :reg_type=>"gpr"},
|
62
|
+
{:reg_name=>"sp", :reg_value=>31, :reg_size=>64, :reg_type=>"gpr"},
|
63
|
+
]
|
64
|
+
|
65
|
+
end # Kompiler::ARMv8A
|
66
|
+
|
67
|
+
end # Kompiler
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Copyright 2024 Kyrylo Shyshko
|
2
|
+
# Licensed under the Apache License, Version 2.0. See LICENSE file for details.
|
3
|
+
|
4
|
+
module Kompiler
|
5
|
+
|
6
|
+
class Architecture
|
7
|
+
|
8
|
+
@@instructions = []
|
9
|
+
@@registers = []
|
10
|
+
|
11
|
+
def self.set_arch instructions, registers
|
12
|
+
@@instructions = instructions
|
13
|
+
@@registers = registers
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.load_arch(arch_name)
|
17
|
+
require "kompiler/arch/#{arch_name.downcase}/load"
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.instructions
|
21
|
+
@@instructions
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.registers
|
25
|
+
@@registers
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|