kompiler 0.2.0.pre.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/kompiler/architectures/armv8a/instructions.rb +385 -48
- data/lib/kompiler/mc_builder.rb +1 -0
- data/lib/kompiler/parsers.rb +5 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc460a4bb7ead297f0fe530c19304038f4d3980103cde260df057c52b35cfeeb
|
4
|
+
data.tar.gz: 57ea6ace09f3b1a5c3d0914d9edbbd02a83a5002b5c55ecde398f593cdcbb211
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c78b06f86db101176939c5aad994950e60d63827fe1a1470d5fad991fb9f2f3d26efef86981039fa2c41b22f034ad2c953bead0961ea4ea411ec583d64e5a27
|
7
|
+
data.tar.gz: 4c001f5a2c64e4a26752c98a116ff85138733662fe376e4b470352731cee721688bd194760f89e949552cf59e3824ef7b2ac607f6ab696732d783dff1b779cf6
|
@@ -103,18 +103,21 @@ end
|
|
103
103
|
},
|
104
104
|
|
105
105
|
{
|
106
|
-
keyword: "and",
|
107
|
-
name: "And",
|
108
|
-
description: "
|
109
|
-
operands: [{type: "register", restrictions: {
|
106
|
+
keyword: "and",
|
107
|
+
name: "And (register)",
|
108
|
+
description: "Performs a bitwise AND of two register values and writes the result to the destination register.",
|
109
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Register 2"}],
|
110
110
|
mc_constructor: [
|
111
|
-
["
|
112
|
-
["
|
111
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "and Error: Register sizes are not the same"]],
|
112
|
+
["if_eq_else", ["get_key", ["get_operand", 1], :reg_size], ["get_key", ["get_operand", 2], :reg_size], [], ["raise_error", "and Error: Register sizes are not the same"]],
|
113
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
|
114
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rn
|
113
115
|
["get_bits", 0, 0, 6], # imm6 (shift amount) set to zero
|
114
116
|
["get_bits", ["encode_gp_register", ["get_operand", 2]], 0, 5],
|
115
117
|
["bits", 0], # N
|
116
118
|
["bits", 0,0], # shift type
|
117
|
-
["bits", 0,1,0,1,0, 0,0
|
119
|
+
["bits", 0,1,0,1,0, 0,0],
|
120
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []], # sf
|
118
121
|
],
|
119
122
|
bitsize: 32
|
120
123
|
},
|
@@ -185,82 +188,101 @@ end
|
|
185
188
|
bitsize: 32
|
186
189
|
},
|
187
190
|
{
|
188
|
-
# LSL (Logical shift left) with an immediate
|
189
|
-
# immr (rotation) is just set to zeros
|
190
191
|
keyword: "lsl",
|
191
|
-
name: "
|
192
|
-
description: "Logically shifts left the value in the source register by the amount specified by the immediate, and
|
193
|
-
operands: [{type: "register", restrictions: {
|
192
|
+
name: "Logical shift left (immediate)",
|
193
|
+
description: "Logically shifts left the value in the source register by the amount specified by the immediate, and writes the result to the destination register",
|
194
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source"}, {type: "immediate", name: "Shift amount"}],
|
194
195
|
mc_constructor: [
|
196
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "lsl Error: Register sizes are not the same"]],
|
195
197
|
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
196
198
|
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
197
199
|
|
198
|
-
["
|
199
|
-
|
200
|
+
["case", ["get_key", ["get_operand", 0], :reg_size],
|
201
|
+
64, ["concat", ["get_bits", ["subtract", 63, ["get_operand", 2]], 0, 6],
|
202
|
+
["get_bits", ["modulo", ["multiply", ["get_operand", 2], -1], 64], 0, 6],],
|
203
|
+
32, ["concat", ["get_bits", ["subtract", 31, ["get_operand", 2]], 0, 6],
|
204
|
+
["get_bits", ["modulo", ["multiply", ["get_operand", 2], -1], 32], 0, 6]],
|
205
|
+
[]
|
206
|
+
],
|
200
207
|
|
201
|
-
["
|
208
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []], # N
|
209
|
+
["bits", 0,1,1,0,0,1, 0,1],
|
210
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []], # sf
|
202
211
|
],
|
203
212
|
bitsize: 32
|
204
213
|
},
|
214
|
+
|
205
215
|
{
|
206
|
-
# LSL (Logical shift left) with an immediate for 32-bit registers
|
207
|
-
# immr (rotation) is just set to zeros
|
208
216
|
keyword: "lsl",
|
209
|
-
name: "
|
210
|
-
description: "Logically shifts left the value in the source register by the amount specified by
|
211
|
-
operands: [{type: "register", restrictions: {
|
217
|
+
name: "Logical shift left (register)",
|
218
|
+
description: "Logically shifts left the value in the source register by the amount specified by a variable number of bits, shifting in zeros, and writes the result to the destination register. The shift amount is equal to a modulo operation between the second register value and register size (either 64 or 32).",
|
219
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Shift amount"}],
|
212
220
|
mc_constructor: [
|
221
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "lsl Error: Register sizes are not the same"]],
|
222
|
+
["if_eq_else", ["get_key", ["get_operand", 1], :reg_size], ["get_key", ["get_operand", 2], :reg_size], [], ["raise_error", "lsl Error: Register sizes are not the same"]],
|
223
|
+
|
213
224
|
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
214
225
|
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
215
|
-
|
216
|
-
["
|
217
|
-
|
226
|
+
|
227
|
+
["bits", 0,0, 0,1,0,0],
|
228
|
+
|
229
|
+
["get_bits", ["encode_gp_register", ["get_operand", 2]], 0, 5],
|
230
|
+
|
231
|
+
["bits", 0,1,1,0,1,0,1,1, 0, 0],
|
232
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []], # sf
|
218
233
|
],
|
219
234
|
bitsize: 32
|
220
235
|
},
|
221
236
|
|
222
|
-
|
223
|
-
|
224
237
|
{
|
225
|
-
# LSL (Logical shift left) with an immediate
|
226
|
-
# immr (rotation) is just set to zeros
|
227
238
|
keyword: "lsr",
|
228
|
-
name: "
|
229
|
-
description: "Logically shifts right the value in the source register by the amount specified by the immediate, and
|
230
|
-
operands: [{type: "register", restrictions: {
|
239
|
+
name: "Logical shift right (immediate)",
|
240
|
+
description: "Logically shifts right the value in the source register by the amount specified by the immediate, and writes the result to the destination register",
|
241
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source"}, {type: "immediate", name: "Shift amount"}],
|
231
242
|
mc_constructor: [
|
243
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "lsr Error: Register sizes are not the same"]],
|
232
244
|
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
233
245
|
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
234
|
-
|
246
|
+
|
235
247
|
["bits", 1,1,1,1,1], # imms
|
236
|
-
["bits", 1], # imms end
|
248
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []], # imms end
|
249
|
+
|
237
250
|
["get_bits", ["get_operand", 2], 0, 6], # immr
|
238
251
|
|
239
|
-
["
|
252
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []], # N
|
253
|
+
|
254
|
+
["bits", 0,1,1,0,0,1, 0,1],
|
255
|
+
|
256
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []], # sf
|
240
257
|
],
|
241
258
|
bitsize: 32
|
242
259
|
},
|
260
|
+
|
261
|
+
|
243
262
|
{
|
244
263
|
keyword: "lsr",
|
245
|
-
name: "
|
246
|
-
description: "Logically shifts right the value in the source register by the amount specified by
|
247
|
-
operands: [{type: "register", restrictions: {
|
264
|
+
name: "Logical shift right (register)",
|
265
|
+
description: "Logically shifts right the value in the source register by the amount specified by a variable number of bits, shifting in zeros, and writes the result to the destination register. The shift amount is equal to a modulo operation between the second register value and register size (either 64 or 32).",
|
266
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Shift amount"}],
|
248
267
|
mc_constructor: [
|
268
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "lsl Error: Register sizes are not the same"]],
|
269
|
+
["if_eq_else", ["get_key", ["get_operand", 1], :reg_size], ["get_key", ["get_operand", 2], :reg_size], [], ["raise_error", "lsl Error: Register sizes are not the same"]],
|
270
|
+
|
249
271
|
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
250
272
|
["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
273
|
|
256
|
-
["bits",
|
274
|
+
["bits", 1,0, 0,1,0,0],
|
275
|
+
|
276
|
+
["get_bits", ["encode_gp_register", ["get_operand", 2]], 0, 5],
|
277
|
+
|
278
|
+
["bits", 0,1,1,0,1,0,1,1, 0, 0],
|
279
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []], # sf
|
257
280
|
],
|
258
281
|
bitsize: 32
|
259
282
|
},
|
260
283
|
|
261
284
|
|
262
285
|
|
263
|
-
|
264
286
|
{
|
265
287
|
# LDR immediate
|
266
288
|
keyword: "ldr",
|
@@ -292,6 +314,33 @@ end
|
|
292
314
|
bitsize: 32
|
293
315
|
},
|
294
316
|
|
317
|
+
{
|
318
|
+
keyword: "ldr_unsigned",
|
319
|
+
name: "Load Register (immediate), unsigned offset",
|
320
|
+
description: "Loads 4 or 8 bytes from memory at the address in the second register with an unsigned immediate offset, and writes it to the destination register",
|
321
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Source address"}, {type: "immediate", name: "Offset"}],
|
322
|
+
mc_constructor: [
|
323
|
+
["case", ["get_key", ["get_operand", 0], :reg_size],
|
324
|
+
64, ["if_eq_else", ["modulo", ["get_operand", 2], 8], 0, [], ["raise_error", "ldr_unsigned Error: Unsigned offset must be divisible by 8 for 64-bit registers."]],
|
325
|
+
32, ["if_eq_else", ["modulo", ["get_operand", 2], 4], 0, [], ["raise_error", "ldr_unsigned Error: Unsigned offset must be divisible by 4 for 32-bit registers."]],
|
326
|
+
[]
|
327
|
+
],
|
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",
|
331
|
+
["case", ["get_key", ["get_operand", 0], :reg_size],
|
332
|
+
64, ["divide", ["get_operand", 2], 8],
|
333
|
+
32, ["divide", ["get_operand", 2], 4],
|
334
|
+
["get_operand", 2]
|
335
|
+
],
|
336
|
+
0, 12],
|
337
|
+
["bits", 1,0, 1,0, 0, 1,1,1],
|
338
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []],
|
339
|
+
["bits", 1],
|
340
|
+
],
|
341
|
+
bitsize: 32
|
342
|
+
},
|
343
|
+
|
295
344
|
{
|
296
345
|
keyword: "ldrb",
|
297
346
|
name: "Load Register Byte",
|
@@ -394,8 +443,67 @@ end
|
|
394
443
|
],
|
395
444
|
bitsize: 32
|
396
445
|
},
|
446
|
+
|
447
|
+
|
448
|
+
{
|
449
|
+
keyword: "strb",
|
450
|
+
name: "Store byte",
|
451
|
+
description: "Stores the least significant byte of a 32-bit general purpose register at the address specified by the second register.",
|
452
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr", reg_size: 32}, name: "Content"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Address"}],
|
453
|
+
mc_constructor: [
|
454
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
455
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
456
|
+
["get_bits", 0, 0, 12],
|
457
|
+
["bits", 0,0, 1,0, 0, 1,1,1, 0,0],
|
458
|
+
],
|
459
|
+
bitsize: 32
|
460
|
+
},
|
461
|
+
|
462
|
+
{
|
463
|
+
keyword: "strb_unsigned",
|
464
|
+
name: "Store byte (immediate), unsigned offset",
|
465
|
+
description: "Stores the least significant byte of a 32-bit general purpose register at the address specified by the second register with an unsigned immediate offset.",
|
466
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr", reg_size: 32}, name: "Content"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Address"}, {type: "immediate", name: "Address Offset"}],
|
467
|
+
mc_constructor: [
|
468
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
469
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
470
|
+
["get_bits", ["get_operand", 2], 0, 12],
|
471
|
+
["bits", 0,0, 1,0, 0, 1,1,1, 0,0],
|
472
|
+
],
|
473
|
+
bitsize: 32
|
474
|
+
},
|
475
|
+
|
476
|
+
{
|
477
|
+
keyword: "strb_post_index",
|
478
|
+
name: "Store byte (immediate), signed post-index offset",
|
479
|
+
description: "Stores the least significant byte of a 32-bit general purpose register at the address specified by the second register with an immediate offset added after writing.",
|
480
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr", reg_size: 32}, name: "Content"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Address"}, {type: "immediate", name: "Address Offset"}],
|
481
|
+
mc_constructor: [
|
482
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
483
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
484
|
+
["bits", 1,0],
|
485
|
+
["get_bits", ["get_operand", 2], 0, 9],
|
486
|
+
["bits", 0, 0,0, 0,0, 0, 1,1,1, 0,0],
|
487
|
+
],
|
488
|
+
bitsize: 32
|
489
|
+
},
|
397
490
|
|
491
|
+
{
|
492
|
+
keyword: "strb_pre_index",
|
493
|
+
name: "Store byte (immediate), signed pre-index offset",
|
494
|
+
description: "Stores the least significant byte of a 32-bit general purpose register at the address specified by the second register with an immediate offset added before writing.",
|
495
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr", reg_size: 32}, name: "Content"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Address"}, {type: "immediate", name: "Address Offset"}],
|
496
|
+
mc_constructor: [
|
497
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
498
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
499
|
+
["bits", 1,1],
|
500
|
+
["get_bits", ["get_operand", 2], 0, 9],
|
501
|
+
["bits", 0, 0,0, 0,0, 0, 1,1,1, 0,0],
|
502
|
+
],
|
503
|
+
bitsize: 32
|
504
|
+
},
|
398
505
|
|
506
|
+
|
399
507
|
{
|
400
508
|
keyword: "cmp",
|
401
509
|
name: "Compare (immediate)",
|
@@ -448,6 +556,26 @@ end
|
|
448
556
|
bitsize: 32
|
449
557
|
},
|
450
558
|
|
559
|
+
{
|
560
|
+
keyword: "sub",
|
561
|
+
name: "Subtract (register)",
|
562
|
+
description: "Subtract the second register value from the first register value, and store the result in the destination register",
|
563
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Register 1 (Source)"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Register 2 (To subtract)"}],
|
564
|
+
mc_constructor: [
|
565
|
+
# Check for size
|
566
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "sub Error: Register sizes are not the same"]],
|
567
|
+
["if_eq_else", ["get_key", ["get_operand", 1], :reg_size], ["get_key", ["get_operand", 2], :reg_size], [], ["raise_error", "sub Error: Register sizes are not the same"]],
|
568
|
+
|
569
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
|
570
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rn
|
571
|
+
["get_bits", 0, 0, 6], # shift amount zero
|
572
|
+
["get_bits", ["encode_gp_register", ["get_operand", 2]], 0, 5], # Rm
|
573
|
+
["bits", 0, 0,0, 1,1,0,1,0, 0, 1],
|
574
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []], # sf
|
575
|
+
],
|
576
|
+
bitsize: 32
|
577
|
+
},
|
578
|
+
|
451
579
|
{
|
452
580
|
keyword: "mul",
|
453
581
|
name: "Multiply",
|
@@ -461,8 +589,7 @@ end
|
|
461
589
|
["bits", 1,1,1,1,1, 0], # Ra o0
|
462
590
|
["get_bits", ["encode_gp_register", ["get_operand", 2]], 0, 5], # Rm
|
463
591
|
["bits", 0,0,0, 1,1,0,1,1, 0,0],
|
464
|
-
["
|
465
|
-
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], 32, ["bits", 0], []], # SF = 0 if 32-bit
|
592
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []], # sf
|
466
593
|
],
|
467
594
|
bitsize: 32
|
468
595
|
},
|
@@ -491,14 +618,74 @@ end
|
|
491
618
|
},
|
492
619
|
|
493
620
|
|
621
|
+
{
|
622
|
+
keyword: "msub",
|
623
|
+
name: "Multiply-Subtract",
|
624
|
+
description: "Multiplies two register values, subtracts the product from a third register value, and writes the result to the destination register.",
|
625
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Register 1 (to multiply)"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Register 2 (to multiply)"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Register 3 (To subtract from)"}],
|
626
|
+
mc_constructor: [
|
627
|
+
# Checks for register sizes being the same
|
628
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "madd Error: Register sizes are not the same"]],
|
629
|
+
["if_eq_else", ["get_key", ["get_operand", 1], :reg_size], ["get_key", ["get_operand", 2], :reg_size], [], ["raise_error", "madd Error: Register sizes are not the same"]],
|
630
|
+
["if_eq_else", ["get_key", ["get_operand", 2], :reg_size], ["get_key", ["get_operand", 3], :reg_size], [], ["raise_error", "madd Error: Register sizes are not the same"]],
|
631
|
+
|
632
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
|
633
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rn
|
634
|
+
["get_bits", ["encode_gp_register", ["get_operand", 3]], 0, 5], #Ra
|
635
|
+
["bits", 1], # o0
|
636
|
+
["get_bits", ["encode_gp_register", ["get_operand", 2]], 0, 5], # Rm
|
637
|
+
["bits", 0,0,0, 1,1,0,1,1, 0,0],
|
638
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []], # sf
|
639
|
+
],
|
640
|
+
bitsize: 32,
|
641
|
+
},
|
642
|
+
|
643
|
+
|
644
|
+
{
|
645
|
+
keyword: "udiv",
|
646
|
+
name: "Unsigned Divide",
|
647
|
+
description: "Divides an unsigned integer register value by another unsigned integer register value, and writes the result to the destination register.",
|
648
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Register 2"}],
|
649
|
+
mc_constructor: [
|
650
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "udiv Error: Register sizes are not the same"]],
|
651
|
+
["if_eq_else", ["get_key", ["get_operand", 1], :reg_size], ["get_key", ["get_operand", 2], :reg_size], [], ["raise_error", "udiv Error: Register sizes are not the same"]],
|
652
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
|
653
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rn
|
654
|
+
["bits", 0, 1,0,0,0,0],
|
655
|
+
["get_bits", ["encode_gp_register", ["get_operand", 2]], 0, 5], # Rm
|
656
|
+
["bits", 0,1,1,0,1,0,1,1, 0, 0],
|
657
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []], # sf
|
658
|
+
],
|
659
|
+
bitsize: 32
|
660
|
+
},
|
661
|
+
|
662
|
+
{
|
663
|
+
keyword: "sdiv",
|
664
|
+
name: "Signed Divide",
|
665
|
+
description: "Divides a signed integer register value by another signed integer register value, and writes the result to the destination register.",
|
666
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Register 2"}],
|
667
|
+
mc_constructor: [
|
668
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "udiv Error: Register sizes are not the same"]],
|
669
|
+
["if_eq_else", ["get_key", ["get_operand", 1], :reg_size], ["get_key", ["get_operand", 2], :reg_size], [], ["raise_error", "udiv Error: Register sizes are not the same"]],
|
670
|
+
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
|
671
|
+
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rn
|
672
|
+
["bits", 1, 1,0,0,0,0],
|
673
|
+
["get_bits", ["encode_gp_register", ["get_operand", 2]], 0, 5], # Rm
|
674
|
+
["bits", 0,1,1,0,1,0,1,1, 0, 0],
|
675
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []], # sf
|
676
|
+
],
|
677
|
+
bitsize: 32
|
678
|
+
},
|
679
|
+
|
680
|
+
|
494
681
|
#
|
495
682
|
# B.cond instructions
|
496
683
|
#
|
497
684
|
|
498
685
|
{
|
499
686
|
keyword: "b.eq",
|
500
|
-
name: "Branch
|
501
|
-
description: "Branches to a label if the condition
|
687
|
+
name: "Branch if equal (label)",
|
688
|
+
description: "Branches to a label if the condition is met",
|
502
689
|
operands: [{type: "label"}],
|
503
690
|
mc_constructor: [
|
504
691
|
["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
|
@@ -511,8 +698,9 @@ end
|
|
511
698
|
},
|
512
699
|
{
|
513
700
|
keyword: "b.eq",
|
701
|
+
name: "Branch if equal (immediate)",
|
702
|
+
description: "Changes the PC relatively by the immediate value if the condition is met",
|
514
703
|
operands: [{type: "immediate"}],
|
515
|
-
description: "Changes the PC relatively by the immediate value if the condition is met (equality)",
|
516
704
|
mc_constructor: [
|
517
705
|
["bits", 0,0,0,0], # eq condition
|
518
706
|
["bits", 0],
|
@@ -521,8 +709,157 @@ end
|
|
521
709
|
],
|
522
710
|
bitsize: 32
|
523
711
|
},
|
712
|
+
|
713
|
+
|
714
|
+
{
|
715
|
+
keyword: "b.ne",
|
716
|
+
name: "Branch if not equal (label)",
|
717
|
+
description: "Branches to a label if the condition is met",
|
718
|
+
operands: [{type: "label"}],
|
719
|
+
mc_constructor: [
|
720
|
+
["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
|
721
|
+
["bits", 1,0,0,0], # condition
|
722
|
+
["bits", 0],
|
723
|
+
["get_bits", ["divide", ["subtract", ["get_label_address", ["get_operand", 0]], ["get_current_address"]], 4], 0, 19],
|
724
|
+
["bits", 0, 0,1,0,1,0,1,0],
|
725
|
+
],
|
726
|
+
bitsize: 32
|
727
|
+
},
|
728
|
+
{
|
729
|
+
keyword: "b.ne",
|
730
|
+
name: "Branch if not equal (immediate)",
|
731
|
+
description: "Changes the PC relatively by the immediate value if the condition is met",
|
732
|
+
operands: [{type: "immediate"}],
|
733
|
+
mc_constructor: [
|
734
|
+
["bits", 1,0,0,0], # condition
|
735
|
+
["bits", 0],
|
736
|
+
["get_bits", ["get_operand", 0], 0, 19],
|
737
|
+
["bits", 0, 0,1,0,1,0,1,0],
|
738
|
+
],
|
739
|
+
bitsize: 32
|
740
|
+
},
|
741
|
+
|
742
|
+
|
743
|
+
{
|
744
|
+
keyword: "b.ge",
|
745
|
+
name: "Branch if greater or equal (label)",
|
746
|
+
description: "Branches to a label if the condition is met",
|
747
|
+
operands: [{type: "label"}],
|
748
|
+
mc_constructor: [
|
749
|
+
["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
|
750
|
+
["bits", 0,1,0,1], # condition
|
751
|
+
["bits", 0],
|
752
|
+
["get_bits", ["divide", ["subtract", ["get_label_address", ["get_operand", 0]], ["get_current_address"]], 4], 0, 19],
|
753
|
+
["bits", 0, 0,1,0,1,0,1,0],
|
754
|
+
],
|
755
|
+
bitsize: 32
|
756
|
+
},
|
757
|
+
{
|
758
|
+
keyword: "b.ge",
|
759
|
+
name: "Branch if greater or equal (immediate)",
|
760
|
+
description: "Changes the PC relatively by the immediate value if the condition is met",
|
761
|
+
operands: [{type: "immediate"}],
|
762
|
+
mc_constructor: [
|
763
|
+
["bits", 0,1,0,1], # condition
|
764
|
+
["bits", 0],
|
765
|
+
["get_bits", ["get_operand", 0], 0, 19],
|
766
|
+
["bits", 0, 0,1,0,1,0,1,0],
|
767
|
+
],
|
768
|
+
bitsize: 32
|
769
|
+
},
|
770
|
+
|
771
|
+
|
772
|
+
|
773
|
+
{
|
774
|
+
keyword: "b.lt",
|
775
|
+
name: "Branch if less than (label)",
|
776
|
+
description: "Branches to a label if the condition is met",
|
777
|
+
operands: [{type: "label"}],
|
778
|
+
mc_constructor: [
|
779
|
+
["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
|
780
|
+
["bits", 1,1,0,1], # condition
|
781
|
+
["bits", 0],
|
782
|
+
["get_bits", ["divide", ["subtract", ["get_label_address", ["get_operand", 0]], ["get_current_address"]], 4], 0, 19],
|
783
|
+
["bits", 0, 0,1,0,1,0,1,0],
|
784
|
+
],
|
785
|
+
bitsize: 32
|
786
|
+
},
|
787
|
+
{
|
788
|
+
keyword: "b.lt",
|
789
|
+
name: "Branch if less than (immediate)",
|
790
|
+
description: "Changes the PC relatively by the immediate value if the condition is met",
|
791
|
+
operands: [{type: "immediate"}],
|
792
|
+
mc_constructor: [
|
793
|
+
["bits", 1,1,0,1], # condition
|
794
|
+
["bits", 0],
|
795
|
+
["get_bits", ["get_operand", 0], 0, 19],
|
796
|
+
["bits", 0, 0,1,0,1,0,1,0],
|
797
|
+
],
|
798
|
+
bitsize: 32
|
799
|
+
},
|
800
|
+
|
801
|
+
|
802
|
+
|
803
|
+
|
804
|
+
{
|
805
|
+
keyword: "b.gt",
|
806
|
+
name: "Branch if greater than (label)",
|
807
|
+
description: "Branches to a label if the condition is met",
|
808
|
+
operands: [{type: "label"}],
|
809
|
+
mc_constructor: [
|
810
|
+
["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
|
811
|
+
["bits", 0,0,1,1], # condition
|
812
|
+
["bits", 0],
|
813
|
+
["get_bits", ["divide", ["subtract", ["get_label_address", ["get_operand", 0]], ["get_current_address"]], 4], 0, 19],
|
814
|
+
["bits", 0, 0,1,0,1,0,1,0],
|
815
|
+
],
|
816
|
+
bitsize: 32
|
817
|
+
},
|
818
|
+
{
|
819
|
+
keyword: "b.gt",
|
820
|
+
name: "Branch if greater than (immediate)",
|
821
|
+
description: "Changes the PC relatively by the immediate value if the condition is met",
|
822
|
+
operands: [{type: "immediate"}],
|
823
|
+
mc_constructor: [
|
824
|
+
["bits", 0,0,1,1], # condition
|
825
|
+
["bits", 0],
|
826
|
+
["get_bits", ["get_operand", 0], 0, 19],
|
827
|
+
["bits", 0, 0,1,0,1,0,1,0],
|
828
|
+
],
|
829
|
+
bitsize: 32
|
830
|
+
},
|
831
|
+
|
832
|
+
|
833
|
+
{
|
834
|
+
keyword: "b.le",
|
835
|
+
name: "Branch if less or equal (label)",
|
836
|
+
description: "Branches to a label if the condition is met",
|
837
|
+
operands: [{type: "label"}],
|
838
|
+
mc_constructor: [
|
839
|
+
["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
|
840
|
+
["bits", 1,0,1,1], # condition
|
841
|
+
["bits", 0],
|
842
|
+
["get_bits", ["divide", ["subtract", ["get_label_address", ["get_operand", 0]], ["get_current_address"]], 4], 0, 19],
|
843
|
+
["bits", 0, 0,1,0,1,0,1,0],
|
844
|
+
],
|
845
|
+
bitsize: 32
|
846
|
+
},
|
847
|
+
{
|
848
|
+
keyword: "b.le",
|
849
|
+
name: "Branch if less or equal (immediate)",
|
850
|
+
description: "Changes the PC relatively by the immediate value if the condition is met",
|
851
|
+
operands: [{type: "immediate"}],
|
852
|
+
mc_constructor: [
|
853
|
+
["bits", 1,0,1,1], # condition
|
854
|
+
["bits", 0],
|
855
|
+
["get_bits", ["get_operand", 0], 0, 19],
|
856
|
+
["bits", 0, 0,1,0,1,0,1,0],
|
857
|
+
],
|
858
|
+
bitsize: 32
|
859
|
+
},
|
860
|
+
|
524
861
|
]
|
525
862
|
|
526
863
|
end # Kompiler::ARMv8A
|
527
864
|
|
528
|
-
end # Kompiler
|
865
|
+
end # Kompiler
|
data/lib/kompiler/mc_builder.rb
CHANGED
@@ -40,6 +40,7 @@ MC_AST_NODES = [
|
|
40
40
|
end},
|
41
41
|
{name: "raise_error", n_args: 1, func: lambda {|args, state| raise args[0] } },
|
42
42
|
{name: "get_key", n_args: 2, func: lambda {|args, state| args[0][args[1]] }},
|
43
|
+
{name: "concat", n_args: "any", func: lambda {|args, state| args.flatten}},
|
43
44
|
]
|
44
45
|
|
45
46
|
def self.is_ast_node(val)
|
data/lib/kompiler/parsers.rb
CHANGED
@@ -9,6 +9,8 @@ def self.parse_str(code)
|
|
9
9
|
|
10
10
|
# Skip the "
|
11
11
|
i = 1
|
12
|
+
|
13
|
+
quote = code[0]
|
12
14
|
|
13
15
|
next_char_backslashed = false
|
14
16
|
|
@@ -20,17 +22,14 @@ def self.parse_str(code)
|
|
20
22
|
str_content << "\n"
|
21
23
|
elsif code[i] == "r"
|
22
24
|
str_content << "\r"
|
23
|
-
elsif code[i] == "\\"
|
24
|
-
str_content << "\\"
|
25
25
|
elsif code[i] == "0"
|
26
26
|
str_content << "\0"
|
27
27
|
else
|
28
|
-
str_content << "\\"
|
29
28
|
str_content << code[i]
|
30
29
|
end
|
31
30
|
next_char_backslashed = false
|
32
31
|
else
|
33
|
-
if code[i] ==
|
32
|
+
if code[i] == quote
|
34
33
|
break
|
35
34
|
elsif code[i] == "\\"
|
36
35
|
next_char_backslashed = true
|
@@ -207,7 +206,6 @@ end
|
|
207
206
|
|
208
207
|
def self.parse_operand_str(operand_str)
|
209
208
|
|
210
|
-
|
211
209
|
# Check if the operand is a register
|
212
210
|
is_register, register = check_register_operand(operand_str)
|
213
211
|
return {type: "register", value: register, register: register} if is_register
|
@@ -288,9 +286,9 @@ def self.parse_instruction_line(line)
|
|
288
286
|
end
|
289
287
|
|
290
288
|
# If a string definition, parse to the end of the string
|
291
|
-
if
|
289
|
+
if ["\"", "'"].include?(line[i])
|
292
290
|
str_content, parsed_size = parse_str(line[i..])
|
293
|
-
operand_content +=
|
291
|
+
operand_content += line[i] + str_content + line[i]
|
294
292
|
i += parsed_size
|
295
293
|
next
|
296
294
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kompiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kyryl Shyshko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: 'Kompiler is a low-level, modular and extendable compiler for any architecture.
|
14
14
|
By default Kompiler supports ARMv8-a, but other architecture extensions can be downloaded
|