kompiler 0.2.0 → 0.3.0.pre.1
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 +4 -4
- data/lib/kompiler/architecture.rb +11 -11
- data/lib/kompiler/architectures/armv8a/instructions.rb +172 -3
- data/lib/kompiler/architectures/armv8a/load.rb +3 -1
- data/lib/kompiler/architectures/armv8a/registers.rb +19 -3
- data/lib/kompiler/architectures/armv8a/sys_instructions.rb +97 -0
- data/lib/kompiler/architectures/armv8a/sys_registers.rb +39 -0
- data/lib/kompiler/compiler_functions.rb +3 -2
- data/lib/kompiler/directives.rb +3 -3
- data/lib/kompiler/mc_builder.rb +20 -6
- data/lib/kompiler/parsers.rb +38 -123
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94839a8d70f8124e207b1c57efcefd4b97bc0b981a38f9319fddce27510954c7
|
4
|
+
data.tar.gz: 257358df8104b1e130361095b6d2c25f6fdac542918af69687313cc00a7bd4d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91804940ae6a1182841aa27d781c410ecae3644500c64907119409ae019e192c75d79bc3ef661ea8aac56b27113fce6ca2bb54c487cd0684f702a42913e445c7
|
7
|
+
data.tar.gz: 6e05374e4e6b0f279aedc8e3087d21bc0bfbc919b431453fd7f1382a0fa39777a37f3e65cfd646576cb806fc0cc07f119649ae080ad6d3b495d372e60c93ca8c
|
@@ -3,26 +3,26 @@
|
|
3
3
|
|
4
4
|
module Kompiler
|
5
5
|
|
6
|
-
|
6
|
+
module Architecture
|
7
|
+
|
8
|
+
@instructions = []
|
9
|
+
@registers = []
|
7
10
|
|
8
|
-
@@instructions = []
|
9
|
-
@@registers = []
|
10
|
-
|
11
11
|
def self.set_arch instructions, registers
|
12
|
-
|
13
|
-
|
12
|
+
@instructions = instructions
|
13
|
+
@registers = registers
|
14
14
|
end
|
15
15
|
|
16
|
-
def self.load_arch(arch_name)
|
17
|
-
|
18
|
-
end
|
16
|
+
# def self.load_arch(arch_name)
|
17
|
+
# require "kompiler/arch/#{arch_name.downcase}/load"
|
18
|
+
# end
|
19
19
|
|
20
20
|
def self.instructions
|
21
|
-
|
21
|
+
@instructions
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.registers
|
25
|
-
|
25
|
+
@registers
|
26
26
|
end
|
27
27
|
|
28
28
|
end
|
@@ -3,13 +3,13 @@
|
|
3
3
|
|
4
4
|
module Kompiler
|
5
5
|
|
6
|
-
|
6
|
+
module ARMv8A
|
7
7
|
|
8
8
|
def self.instructions
|
9
|
-
|
9
|
+
@instructions
|
10
10
|
end
|
11
11
|
|
12
|
-
|
12
|
+
@instructions = [
|
13
13
|
{ keyword: "mov",
|
14
14
|
operands: [{type: "register", restrictions: {reg_size: 64}}, {type: "immediate", restrictions: {}}],
|
15
15
|
mc_constructor: [
|
@@ -354,6 +354,91 @@ end
|
|
354
354
|
],
|
355
355
|
bitsize: 32
|
356
356
|
},
|
357
|
+
|
358
|
+
{
|
359
|
+
keyword: "ldp",
|
360
|
+
name: "Load Pair",
|
361
|
+
description: "Loads data for two registers from memory at the address specified by the third register, and writes the data to two general-purpose registers.",
|
362
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination Register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Destination Register 2"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Address Register"}],
|
363
|
+
bitsize: 32,
|
364
|
+
mc_constructor: [
|
365
|
+
# Check for register sizes
|
366
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "ldp Error: Register sizes are not the same"]],
|
367
|
+
["get_bits", ["get_key", ["get_operand", 0], :reg_value], 0, 5],
|
368
|
+
["get_bits", ["get_key", ["get_operand", 2], :reg_value], 0, 5],
|
369
|
+
["get_bits", ["get_key", ["get_operand", 1], :reg_value], 0, 5],
|
370
|
+
["get_bits", 0, 0, 7], # imm7
|
371
|
+
["bits", 1, 0,1,0, 0, 1,0,1, 0],
|
372
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []] # opc
|
373
|
+
]
|
374
|
+
},
|
375
|
+
{
|
376
|
+
keyword: "ldp_signed",
|
377
|
+
name: "Load Pair (signed offset)",
|
378
|
+
description: "Loads data for two registers from memory at the address specified by the third register, with a signed immediate offset added, and writes the data to two general-purpose registers.",
|
379
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 2"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Address Register"}, {type: "immediate", name: "Address Offset"}],
|
380
|
+
bitsize: 32,
|
381
|
+
mc_constructor: [
|
382
|
+
# Check for register sizes
|
383
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "ldp_signed Error: Register sizes are not the same"]],
|
384
|
+
# Establish the immediate offset alignment using the register size
|
385
|
+
["set_var", "imm_alignment", ["case", ["get_key", ["get_operand", 0], :reg_size], 32, 4, 64, 8, 0]],
|
386
|
+
# Check if the immediate offset is properly aligned
|
387
|
+
["if_eq_else", ["modulo", ["get_operand", 3], ["get_var", "imm_alignment"]], 0, [], ["raise_error", "ldp_signed Error: The immediate offset is not properly aligned"]],
|
388
|
+
|
389
|
+
["get_bits", ["get_key", ["get_operand", 0], :reg_value], 0, 5],
|
390
|
+
["get_bits", ["get_key", ["get_operand", 2], :reg_value], 0, 5],
|
391
|
+
["get_bits", ["get_key", ["get_operand", 1], :reg_value], 0, 5],
|
392
|
+
["get_bits", ["divide", ["get_operand", 3], ["get_var", "imm_alignment"]], 0, 7], # imm7
|
393
|
+
["bits", 1, 0,1,0, 0, 1,0,1, 0],
|
394
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []] # opc
|
395
|
+
]
|
396
|
+
},
|
397
|
+
{
|
398
|
+
keyword: "ldp_pre_index",
|
399
|
+
name: "Load Pair (pre-index, signed offset)",
|
400
|
+
description: "Loads data for two registers from memory at the address specified by the third register, with a signed immediate offset added permanently before reading, and writes the data to two general-purpose registers.",
|
401
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 2"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Address Register"}, {type: "immediate", name: "Address Offset"}],
|
402
|
+
bitsize: 32,
|
403
|
+
mc_constructor: [
|
404
|
+
# Check for register sizes
|
405
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "ldp_pre_index Error: Register sizes are not the same"]],
|
406
|
+
# Establish the immediate offset alignment using the register size
|
407
|
+
["set_var", "imm_alignment", ["case", ["get_key", ["get_operand", 0], :reg_size], 32, 4, 64, 8, 0]],
|
408
|
+
# Check if the immediate offset is properly aligned
|
409
|
+
["if_eq_else", ["modulo", ["get_operand", 3], ["get_var", "imm_alignment"]], 0, [], ["raise_error", "ldp_pre_index Error: The immediate offset is not properly aligned"]],
|
410
|
+
|
411
|
+
["get_bits", ["get_key", ["get_operand", 0], :reg_value], 0, 5],
|
412
|
+
["get_bits", ["get_key", ["get_operand", 2], :reg_value], 0, 5],
|
413
|
+
["get_bits", ["get_key", ["get_operand", 1], :reg_value], 0, 5],
|
414
|
+
["get_bits", ["divide", ["get_operand", 3], ["get_var", "imm_alignment"]], 0, 7], # imm7
|
415
|
+
["bits", 1, 1,1,0, 0, 1,0,1, 0],
|
416
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []] # opc
|
417
|
+
]
|
418
|
+
},
|
419
|
+
{
|
420
|
+
keyword: "ldp_post_index",
|
421
|
+
name: "Load Pair (post-index, signed offset)",
|
422
|
+
description: "Loads data for two registers from memory at the address specified by the third register, with a signed immediate offset added permanently after reading, and writes the data to two general-purpose registers.",
|
423
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 2"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Address Register"}, {type: "immediate", name: "Address Offset"}],
|
424
|
+
bitsize: 32,
|
425
|
+
mc_constructor: [
|
426
|
+
# Check for register sizes
|
427
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "ldp_post_index Error: Register sizes are not the same"]],
|
428
|
+
# Establish the immediate offset alignment using the register size
|
429
|
+
["set_var", "imm_alignment", ["case", ["get_key", ["get_operand", 0], :reg_size], 32, 4, 64, 8, 0]],
|
430
|
+
# Check if the immediate offset is properly aligned
|
431
|
+
["if_eq_else", ["modulo", ["get_operand", 3], ["get_var", "imm_alignment"]], 0, [], ["raise_error", "ldp_post_index Error: The immediate offset is not properly aligned"]],
|
432
|
+
|
433
|
+
["get_bits", ["get_key", ["get_operand", 0], :reg_value], 0, 5],
|
434
|
+
["get_bits", ["get_key", ["get_operand", 2], :reg_value], 0, 5],
|
435
|
+
["get_bits", ["get_key", ["get_operand", 1], :reg_value], 0, 5],
|
436
|
+
["get_bits", ["divide", ["get_operand", 3], ["get_var", "imm_alignment"]], 0, 7], # imm7
|
437
|
+
["bits", 1, 1,0,0, 0, 1,0,1, 0],
|
438
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []] # opc
|
439
|
+
]
|
440
|
+
},
|
441
|
+
|
357
442
|
{
|
358
443
|
keyword: "strh",
|
359
444
|
operands: [{type: "register", restrictions: {reg_size: 32}}, {type: "register", restrictions: {reg_size: 64}}],
|
@@ -503,6 +588,90 @@ end
|
|
503
588
|
bitsize: 32
|
504
589
|
},
|
505
590
|
|
591
|
+
{
|
592
|
+
keyword: "stp",
|
593
|
+
name: "Store Pair",
|
594
|
+
description: "Stores the contents of two general-purpose registers at the address specified by the third register.",
|
595
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 2"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Address Register"}],
|
596
|
+
bitsize: 32,
|
597
|
+
mc_constructor: [
|
598
|
+
# Check for register sizes
|
599
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "stp Error: Register sizes are not the same"]],
|
600
|
+
["get_bits", ["get_key", ["get_operand", 0], :reg_value], 0, 5],
|
601
|
+
["get_bits", ["get_key", ["get_operand", 2], :reg_value], 0, 5],
|
602
|
+
["get_bits", ["get_key", ["get_operand", 1], :reg_value], 0, 5],
|
603
|
+
["get_bits", 0, 0, 7], # imm7
|
604
|
+
["bits", 0, 0,1,0, 0, 1,0,1, 0],
|
605
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []] # opc
|
606
|
+
]
|
607
|
+
},
|
608
|
+
{
|
609
|
+
keyword: "stp_signed",
|
610
|
+
name: "Store Pair (signed offset)",
|
611
|
+
description: "Stores the contents of two general-purpose registers at the address specified by the third register, with a signed immediate offset added.",
|
612
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 2"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Address Register"}, {type: "immediate", name: "Address Offset"}],
|
613
|
+
bitsize: 32,
|
614
|
+
mc_constructor: [
|
615
|
+
# Check for register sizes
|
616
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "stp Error: Register sizes are not the same"]],
|
617
|
+
# Establish the immediate offset alignment using the register size
|
618
|
+
["set_var", "imm_alignment", ["case", ["get_key", ["get_operand", 0], :reg_size], 32, 4, 64, 8, 0]],
|
619
|
+
# Check if the immediate offset is properly aligned
|
620
|
+
["if_eq_else", ["modulo", ["get_operand", 3], ["get_var", "imm_alignment"]], 0, [], ["raise_error", "stp Error: The immediate offset is not properly aligned"]],
|
621
|
+
|
622
|
+
["get_bits", ["get_key", ["get_operand", 0], :reg_value], 0, 5],
|
623
|
+
["get_bits", ["get_key", ["get_operand", 2], :reg_value], 0, 5],
|
624
|
+
["get_bits", ["get_key", ["get_operand", 1], :reg_value], 0, 5],
|
625
|
+
["get_bits", ["divide", ["get_operand", 3], ["get_var", "imm_alignment"]], 0, 7], # imm7
|
626
|
+
["bits", 0, 0,1,0, 0, 1,0,1, 0],
|
627
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []] # opc
|
628
|
+
]
|
629
|
+
},
|
630
|
+
{
|
631
|
+
keyword: "stp_pre_index",
|
632
|
+
name: "Store Pair (pre-index, signed offset)",
|
633
|
+
description: "Stores the contents of two general-purpose registers at the address specified by the third register, with a permanent signed immediate offset added before writing.",
|
634
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 2"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Address Register"}, {type: "immediate", name: "Address Offset"}],
|
635
|
+
bitsize: 32,
|
636
|
+
mc_constructor: [
|
637
|
+
# Check for register sizes
|
638
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "stp Error: Register sizes are not the same"]],
|
639
|
+
# Establish the immediate offset alignment using the register size
|
640
|
+
["set_var", "imm_alignment", ["case", ["get_key", ["get_operand", 0], :reg_size], 32, 4, 64, 8, 0]],
|
641
|
+
# Check if the immediate offset is properly aligned
|
642
|
+
["if_eq_else", ["modulo", ["get_operand", 3], ["get_var", "imm_alignment"]], 0, [], ["raise_error", "stp Error: The immediate offset is not properly aligned"]],
|
643
|
+
|
644
|
+
["get_bits", ["get_key", ["get_operand", 0], :reg_value], 0, 5],
|
645
|
+
["get_bits", ["get_key", ["get_operand", 2], :reg_value], 0, 5],
|
646
|
+
["get_bits", ["get_key", ["get_operand", 1], :reg_value], 0, 5],
|
647
|
+
["get_bits", ["divide", ["get_operand", 3], ["get_var", "imm_alignment"]], 0, 7], # imm7
|
648
|
+
["bits", 0, 1,1,0, 0, 1,0,1, 0],
|
649
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []] # opc
|
650
|
+
]
|
651
|
+
},
|
652
|
+
{
|
653
|
+
keyword: "stp_post_index",
|
654
|
+
name: "Store Pair (post-index, signed offset)",
|
655
|
+
description: "Stores the contents of two general-purpose registers at the address specified by the third register, with a permanent signed immediate offset added after writing.",
|
656
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Content Register 2"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Address Register"}, {type: "immediate", name: "Address Offset"}],
|
657
|
+
bitsize: 32,
|
658
|
+
mc_constructor: [
|
659
|
+
# Check for register sizes
|
660
|
+
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "stp Error: Register sizes are not the same"]],
|
661
|
+
# Establish the immediate offset alignment using the register size
|
662
|
+
["set_var", "imm_alignment", ["case", ["get_key", ["get_operand", 0], :reg_size], 32, 4, 64, 8, 0]],
|
663
|
+
# Check if the immediate offset is properly aligned
|
664
|
+
["if_eq_else", ["modulo", ["get_operand", 3], ["get_var", "imm_alignment"]], 0, [], ["raise_error", "stp Error: The immediate offset is not properly aligned"]],
|
665
|
+
|
666
|
+
["get_bits", ["get_key", ["get_operand", 0], :reg_value], 0, 5],
|
667
|
+
["get_bits", ["get_key", ["get_operand", 2], :reg_value], 0, 5],
|
668
|
+
["get_bits", ["get_key", ["get_operand", 1], :reg_value], 0, 5],
|
669
|
+
["get_bits", ["divide", ["get_operand", 3], ["get_var", "imm_alignment"]], 0, 7], # imm7
|
670
|
+
["bits", 0, 1,0,0, 0, 1,0,1, 0],
|
671
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []] # opc
|
672
|
+
]
|
673
|
+
},
|
674
|
+
|
506
675
|
|
507
676
|
{
|
508
677
|
keyword: "cmp",
|
@@ -2,7 +2,9 @@
|
|
2
2
|
# Licensed under the Apache License, Version 2.0. See LICENSE file for details.
|
3
3
|
|
4
4
|
require 'kompiler/architectures/armv8a/instructions.rb'
|
5
|
+
require 'kompiler/architectures/armv8a/sys_instructions.rb'
|
5
6
|
require 'kompiler/architectures/armv8a/registers.rb'
|
7
|
+
require 'kompiler/architectures/armv8a/sys_registers.rb'
|
6
8
|
|
7
9
|
|
8
|
-
Kompiler::Architecture.set_arch(Kompiler::ARMv8A.instructions, Kompiler::ARMv8A.registers)
|
10
|
+
Kompiler::Architecture.set_arch(Kompiler::ARMv8A.instructions + Kompiler::ARMv8A.sys_instructions, Kompiler::ARMv8A.registers + Kompiler::ARMv8A.sys_registers)
|
@@ -3,13 +3,13 @@
|
|
3
3
|
|
4
4
|
module Kompiler
|
5
5
|
|
6
|
-
|
6
|
+
module ARMv8A
|
7
7
|
|
8
8
|
def self.registers
|
9
|
-
|
9
|
+
@registers
|
10
10
|
end
|
11
11
|
|
12
|
-
|
12
|
+
@registers = [
|
13
13
|
{:reg_name=>"w0", :reg_value=>0, :reg_size=>32, :reg_type=>"gpr"},
|
14
14
|
{:reg_name=>"w1", :reg_value=>1, :reg_size=>32, :reg_type=>"gpr"},
|
15
15
|
{:reg_name=>"w2", :reg_value=>2, :reg_size=>32, :reg_type=>"gpr"},
|
@@ -26,6 +26,22 @@ end
|
|
26
26
|
{:reg_name=>"w13", :reg_value=>13, :reg_size=>32, :reg_type=>"gpr"},
|
27
27
|
{:reg_name=>"w14", :reg_value=>14, :reg_size=>32, :reg_type=>"gpr"},
|
28
28
|
{:reg_name=>"w15", :reg_value=>15, :reg_size=>32, :reg_type=>"gpr"},
|
29
|
+
{:reg_name=>"w16", :reg_value=>16, :reg_size=>32, :reg_type=>"gpr"},
|
30
|
+
{:reg_name=>"w17", :reg_value=>17, :reg_size=>32, :reg_type=>"gpr"},
|
31
|
+
{:reg_name=>"w18", :reg_value=>18, :reg_size=>32, :reg_type=>"gpr"},
|
32
|
+
{:reg_name=>"w19", :reg_value=>19, :reg_size=>32, :reg_type=>"gpr"},
|
33
|
+
{:reg_name=>"w20", :reg_value=>20, :reg_size=>32, :reg_type=>"gpr"},
|
34
|
+
{:reg_name=>"w21", :reg_value=>21, :reg_size=>32, :reg_type=>"gpr"},
|
35
|
+
{:reg_name=>"w22", :reg_value=>22, :reg_size=>32, :reg_type=>"gpr"},
|
36
|
+
{:reg_name=>"w23", :reg_value=>23, :reg_size=>32, :reg_type=>"gpr"},
|
37
|
+
{:reg_name=>"w24", :reg_value=>24, :reg_size=>32, :reg_type=>"gpr"},
|
38
|
+
{:reg_name=>"w25", :reg_value=>25, :reg_size=>32, :reg_type=>"gpr"},
|
39
|
+
{:reg_name=>"w26", :reg_value=>26, :reg_size=>32, :reg_type=>"gpr"},
|
40
|
+
{:reg_name=>"w27", :reg_value=>27, :reg_size=>32, :reg_type=>"gpr"},
|
41
|
+
{:reg_name=>"w28", :reg_value=>28, :reg_size=>32, :reg_type=>"gpr"},
|
42
|
+
{:reg_name=>"w29", :reg_value=>29, :reg_size=>32, :reg_type=>"gpr"},
|
43
|
+
{:reg_name=>"w30", :reg_value=>30, :reg_size=>32, :reg_type=>"gpr"},
|
44
|
+
{:reg_name=>"w31", :reg_value=>31, :reg_size=>32, :reg_type=>"gpr"},
|
29
45
|
{:reg_name=>"x0", :reg_value=>0, :reg_size=>64, :reg_type=>"gpr"},
|
30
46
|
{:reg_name=>"x1", :reg_value=>1, :reg_size=>64, :reg_type=>"gpr"},
|
31
47
|
{:reg_name=>"x2", :reg_value=>2, :reg_size=>64, :reg_type=>"gpr"},
|
@@ -0,0 +1,97 @@
|
|
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
|
+
module ARMv8A
|
7
|
+
|
8
|
+
def self.sys_instructions
|
9
|
+
@sys_instructions
|
10
|
+
end
|
11
|
+
|
12
|
+
@sys_instructions = [
|
13
|
+
{
|
14
|
+
keyword: "mrs",
|
15
|
+
name: "Move from system register",
|
16
|
+
description: "Moves the contents of a system register to a 64-bit general-purpose register",
|
17
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Destination general-purpose register"}, {type: "register", restrictions: {reg_type: "sr"}, name: "Source system register"}],
|
18
|
+
mc_constructor: [
|
19
|
+
["set_var", "sr_encoding", ["get_key", ["get_operand", 1], :reg_encoding]],
|
20
|
+
["get_bits", ["get_key", ["get_operand", 0], :reg_value], 0, 5],
|
21
|
+
["get_bits", ["get_key", ["get_var", "sr_encoding"], "op2"], 0, 3],
|
22
|
+
["get_bits", ["get_key", ["get_var", "sr_encoding"], "CRm"], 0, 4],
|
23
|
+
["get_bits", ["get_key", ["get_var", "sr_encoding"], "CRn"], 0, 4],
|
24
|
+
["get_bits", ["get_key", ["get_var", "sr_encoding"], "op1"], 0, 3],
|
25
|
+
["get_bits", ["get_key", ["get_var", "sr_encoding"], "op0"], 0, 2],
|
26
|
+
["bits", 1], # L
|
27
|
+
["bits", 0,0,1,0,1,0,1,0,1,1]
|
28
|
+
],
|
29
|
+
bitsize: 32
|
30
|
+
},
|
31
|
+
{
|
32
|
+
keyword: "msr",
|
33
|
+
name: "Move general-purpose register to system register",
|
34
|
+
description: "Writes the contents of a general-purpose register to a system register",
|
35
|
+
operands: [{type: "register", restrictions: {reg_type: "sr"}, name: "Destination system register"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source general-purpose register"}],
|
36
|
+
mc_constructor: [
|
37
|
+
["set_var", "sr_encoding", ["get_key", ["get_operand", 0], :reg_encoding]],
|
38
|
+
["get_bits", ["get_key", ["get_operand", 1], :reg_value], 0, 5],
|
39
|
+
["get_bits", ["get_key", ["get_var", "sr_encoding"], "op2"], 0, 3],
|
40
|
+
["get_bits", ["get_key", ["get_var", "sr_encoding"], "CRm"], 0, 4],
|
41
|
+
["get_bits", ["get_key", ["get_var", "sr_encoding"], "CRn"], 0, 4],
|
42
|
+
["get_bits", ["get_key", ["get_var", "sr_encoding"], "op1"], 0, 3],
|
43
|
+
["get_bits", ["get_key", ["get_var", "sr_encoding"], "op0"], 0, 2],
|
44
|
+
["bits", 0], # L
|
45
|
+
["bits", 0,0,1,0,1,0,1,0,1,1]
|
46
|
+
],
|
47
|
+
bitsize: 32
|
48
|
+
},
|
49
|
+
{
|
50
|
+
keyword: "msr",
|
51
|
+
name: "Move immediate value to special register",
|
52
|
+
description: "Moves an immediate value to selected bits of the PSTATE",
|
53
|
+
operands: [{type: "register", name: "Destination system register"}, {type: "immediate", name: "Immediate value"}],
|
54
|
+
mc_constructor: [
|
55
|
+
# Case for PSTATE special register encodings
|
56
|
+
["case", ["downcase_str", ["get_key", ["get_operand_hash", 0], :definition]],
|
57
|
+
"spsel", ["concat", ["set_var", "op1", 0b000], ["set_var", "op2", 0b101]],
|
58
|
+
"daifset", ["concat", ["set_var", "op1", 0b011], ["set_var", "op2", 0b110]],
|
59
|
+
"daifclr", ["concat", ["set_var", "op1", 0b011], ["set_var", "op2", 0b111]],
|
60
|
+
"uao", ["concat", ["set_var", "op1", 0b000], ["set_var", "op2", 0b011]],
|
61
|
+
"pan", ["concat", ["set_var", "op1", 0b000], ["set_var", "op2", 0b100]],
|
62
|
+
"allint", ["concat", ["set_var", "op1", 0b001], ["set_var", "op2", 0b000], ["if_eq_else", ["bit_and", ["get_operand", 1], 0b001], ["get_operand", 1], [], ["raise_warning", "msr ALLINT Warning: The immediate value is not valid for the instruction - Continuing build."]] ],
|
63
|
+
"pm", ["concat", ["set_var", "op1", 0b001], ["set_var", "op2", 0b000], ["if_eq_else", ["bit_and", ["get_operand", 1], 0b011], ["get_operand", 1], [], ["raise_warning", "msr PM Warning: The immediate value is not valid for the instruction - Continuing build."]]],
|
64
|
+
"ssbs", ["concat", ["set_var", "op1", 0b011], ["set_var", "op2", 0b001]],
|
65
|
+
"dit", ["concat", ["set_var", "op1", 0b011], ["set_var", "op2", 0b010]],
|
66
|
+
"svcrsm", ["concat", ["set_var", "op1", 0b011], ["set_var", "op2", 0b011], ["if_eq_else", ["bit_and", ["get_operand", 1], 0b0011], ["get_operand", 1], [], ["raise_warning", "msr SVCRSM Warning: The immediate value is not valid for the instruction - Continuing build."]]],
|
67
|
+
"svcrza", ["concat", ["set_var", "op1", 0b011], ["set_var", "op2", 0b011], ["if_eq_else", ["bit_and", ["get_operand", 1], 0b0101], ["get_operand", 1], [], ["raise_warning", "msr SVCRZA Warning: The immediate value is not valid for the instruction - Continuing build."]]],
|
68
|
+
"svcrsmza", ["concat", ["set_var", "op1", 0b011], ["set_var", "op2", 0b011], ["if_eq_else", ["bit_and", ["get_operand", 1], 0b0111], ["get_operand", 1], [], ["raise_warning", "msr SVCRSMZA Warning: The immediate value is not valid for the instruction - Continuing build."]]],
|
69
|
+
"tco", ["concat", ["set_var", "op1", 0b011], ["set_var", "op2", 0b100]],
|
70
|
+
["raise_error", "msr Error: The specified PSTATE special register was not found - Program build not possible."]
|
71
|
+
],
|
72
|
+
["bits", 1,1,1,1,1],
|
73
|
+
["get_bits", ["get_var", "op2"], 0, 3],
|
74
|
+
["get_bits", ["get_operand", 1], 0, 4],
|
75
|
+
["bits", 0,0,1,0],
|
76
|
+
["get_bits", ["get_var", "op1"], 0, 3],
|
77
|
+
["bits", 0,0, 0, 0,0,1,0,1,0,1,0,1,1],
|
78
|
+
],
|
79
|
+
bitsize: 32
|
80
|
+
},
|
81
|
+
|
82
|
+
|
83
|
+
{
|
84
|
+
keyword: "eret",
|
85
|
+
name: "Exception Return",
|
86
|
+
description: "Restores PSTATE from SPSR, and branches to the address held in ELR. ",
|
87
|
+
operands: [],
|
88
|
+
mc_constructor: [
|
89
|
+
["bits", 0,0,0,0,0, 1,1,1,1,1, 0, 0, 0,0,0,0, 1,1,1,1,1, 0,0,1, 0, 1,1,0,1,0,1,1],
|
90
|
+
],
|
91
|
+
bitsize: 32
|
92
|
+
},
|
93
|
+
]
|
94
|
+
|
95
|
+
end # Kompiler::ARMv8A
|
96
|
+
|
97
|
+
end # Kompiler
|
@@ -0,0 +1,39 @@
|
|
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
|
+
module ARMv8A
|
7
|
+
|
8
|
+
def self.sys_registers
|
9
|
+
@sys_registers
|
10
|
+
end
|
11
|
+
|
12
|
+
@sys_registers = [
|
13
|
+
{reg_name: "mpidr_el0", reg_size: 64, reg_type: "sr", reg_encoding: {"op0"=>3, "op1"=>0, "CRn"=>0, "CRm"=>0, "op2"=>5}, rw_type: "ro"},
|
14
|
+
|
15
|
+
{reg_name: "vbar_el1", reg_size: 64, reg_type: "sr", reg_encoding: {"op0"=>0b11, "op1"=>0, "CRn"=>0b1100, "CRm"=>0, "op2"=>0}, rw_type: "rw"},
|
16
|
+
{reg_name: "vbar_el12", reg_size: 64, reg_type: "sr", reg_encoding: {"op0"=>0b11, "op1"=>0b101, "CRn"=>0b1100, "CRm"=>0, "op2"=>0}, rw_type: "rw"},
|
17
|
+
{reg_name: "vbar_el2", reg_size: 64, reg_type: "sr", reg_encoding: {"op0"=>0b11, "op1"=>0b100, "CRn"=>0b1100, "CRm"=>0, "op2"=>0}, rw_type: "rw"},
|
18
|
+
{reg_name: "vbar_el3", reg_size: 64, reg_type: "sr", reg_encoding: {"op0"=>0b11, "op1"=>0b110, "CRn"=>0b1100, "CRm"=>0, "op2"=>0}, rw_type: "rw"},
|
19
|
+
|
20
|
+
|
21
|
+
# Special registers for the MSR (immediate) instruction (some of them were previously defined already)
|
22
|
+
{reg_name: "SPSel", reg_type: "pstate_reg"},
|
23
|
+
{reg_name: "DAIFSet", reg_type: "pstate_reg"},
|
24
|
+
{reg_name: "DAIFClr", reg_type: "pstate_reg"},
|
25
|
+
{reg_name: "UAO", reg_type: "pstate_reg"},
|
26
|
+
{reg_name: "PAN", reg_type: "pstate_reg"},
|
27
|
+
{reg_name: "ALLINT", reg_type: "pstate_reg"},
|
28
|
+
{reg_name: "PM", reg_type: "pstate_reg"},
|
29
|
+
{reg_name: "SSBS", reg_type: "pstate_reg"},
|
30
|
+
{reg_name: "DIT", reg_type: "pstate_reg"},
|
31
|
+
{reg_name: "SVCRSM", reg_type: "pstate_reg"},
|
32
|
+
{reg_name: "SVCRZA", reg_type: "pstate_reg"},
|
33
|
+
{reg_name: "SVCRSMZA", reg_type: "pstate_reg"},
|
34
|
+
{reg_name: "TCO", reg_type: "pstate_reg"},
|
35
|
+
]
|
36
|
+
|
37
|
+
end # Kompiler::ARMv8A
|
38
|
+
|
39
|
+
end # Kompiler
|
@@ -168,7 +168,7 @@ def self.construct_program_mc(parsed_lines, labels)
|
|
168
168
|
lines_bytes = ""
|
169
169
|
|
170
170
|
|
171
|
-
program_state = {labels: labels, current_address: 0}
|
171
|
+
program_state = {labels: labels, current_address: 0, instruction_variables: {}}
|
172
172
|
|
173
173
|
parsed_lines.each do |line|
|
174
174
|
case line[:type]
|
@@ -179,6 +179,7 @@ def self.construct_program_mc(parsed_lines, labels)
|
|
179
179
|
mc_constructor = line[:instruction][:mc_constructor]
|
180
180
|
|
181
181
|
instr_bits = Kompiler::MachineCode_AST.build_mc(mc_constructor, program_state)
|
182
|
+
program_state[:instruction_variables] = Hash.new # Clear the instruction variables after running the instruction
|
182
183
|
|
183
184
|
instr_bytes = bits_to_bytes(instr_bits)
|
184
185
|
|
@@ -259,4 +260,4 @@ end
|
|
259
260
|
|
260
261
|
end # Kompiler::CompilerFunctions
|
261
262
|
|
262
|
-
end # Kompiler
|
263
|
+
end # Kompiler
|
data/lib/kompiler/directives.rb
CHANGED
data/lib/kompiler/mc_builder.rb
CHANGED
@@ -3,10 +3,11 @@
|
|
3
3
|
|
4
4
|
module Kompiler
|
5
5
|
|
6
|
-
|
6
|
+
module MachineCode_AST
|
7
7
|
|
8
|
-
MC_AST_NODES = [
|
8
|
+
@MC_AST_NODES = [
|
9
9
|
{name: "get_operand", n_args: 1, func: lambda {|args, state| state[:operands][args[0]][:value]} },
|
10
|
+
{name: "get_operand_hash", n_args: 1, func: lambda {|args, state| state[:operands][args[0]] } },
|
10
11
|
{name: "get_bits", n_args: 3, func: lambda {|args, state| (args[1]...(args[1] + args[2])).map{|bit_i| args[0][bit_i]} } },
|
11
12
|
{name: "get_bits_signed", n_args: 3, func: lambda do |args, state|
|
12
13
|
if args[1] == 0
|
@@ -38,9 +39,21 @@ MC_AST_NODES = [
|
|
38
39
|
end
|
39
40
|
eval_mc_node_arg(args.last, state)
|
40
41
|
end},
|
41
|
-
|
42
|
-
{name: "
|
42
|
+
|
43
|
+
{name: "raise_error", n_args: 1, func: lambda {|args, state| raise args[0]; [] } },
|
44
|
+
{name: "raise_warning", n_args: 1, func: lambda {|args, state| puts args[0]; [] } },
|
45
|
+
|
46
|
+
{name: "get_key", n_args: 2, func: lambda {|args, state| args[0].keys.include?(args[1]) ? args[0][args[1]] : raise("MC Constructor get_key Error: The key \"#{args[1]}\" doesn't exist - Program build not possible. This is likely a problem with the ISA configuration, not the program being compiled.") }},
|
43
47
|
{name: "concat", n_args: "any", func: lambda {|args, state| args.flatten}},
|
48
|
+
{name: "set_var", n_args: 2, func: lambda {|args, state| state[:instruction_variables][args[0]] = args[1]; [] }},
|
49
|
+
{name: "get_var", n_args: 1, func: lambda {|args, state| state[:instruction_variables].keys.include?(args[0]) ? state[:instruction_variables][args[0]] : raise("Instruction variable \"#{args[0]}\" not found: Program build not possible. This is likely a program with the ISA configuration, not the program being compiled.") }},
|
50
|
+
|
51
|
+
# String manipulations
|
52
|
+
{name: "downcase_str", n_args: 1, func: lambda {|args, state| args[0].downcase }},
|
53
|
+
|
54
|
+
# Bit manipulations
|
55
|
+
{name: "bit_and", n_args: 2, func: lambda {|args, state| args[0] & args[1] }},
|
56
|
+
{name: "bit_or", n_args: 2, func: lambda {|args, state| args[0] | args[1] }},
|
44
57
|
]
|
45
58
|
|
46
59
|
def self.is_ast_node(val)
|
@@ -57,7 +70,8 @@ def self.run_mc_ast(node, state)
|
|
57
70
|
node_name = node[0]
|
58
71
|
node_args = node[1..]
|
59
72
|
|
60
|
-
|
73
|
+
|
74
|
+
node_logic = @MC_AST_NODES.filter{|any_node| any_node[:name] == node_name}[0]
|
61
75
|
|
62
76
|
if !node_logic
|
63
77
|
raise "MC Node \"#{node_name}\" wasn't found. Cannot build the program"
|
@@ -97,4 +111,4 @@ end
|
|
97
111
|
|
98
112
|
end # Kompiler::MC_AST
|
99
113
|
|
100
|
-
end # Kompiler
|
114
|
+
end # Kompiler
|
data/lib/kompiler/parsers.rb
CHANGED
@@ -86,7 +86,10 @@ end
|
|
86
86
|
|
87
87
|
def self.check_register_operand(str)
|
88
88
|
Kompiler::Architecture.registers.each do |register|
|
89
|
-
|
89
|
+
# Downcase both the string and the register if the register name is not case sensitive (the default)
|
90
|
+
processed_str = register[:case_sensitive] ? str : str.downcase
|
91
|
+
processed_reg_name = register[:case_sensitive] ? register[:reg_name] : register[:reg_name].downcase
|
92
|
+
return [true, register] if processed_str == processed_reg_name
|
90
93
|
end
|
91
94
|
return [false, nil]
|
92
95
|
end
|
@@ -172,16 +175,16 @@ end
|
|
172
175
|
def self.check_immediate_operand(operand_str)
|
173
176
|
|
174
177
|
is_bin, bin_value = check_binary_operand(operand_str)
|
175
|
-
return [true, {type: "immediate", value: bin_value, def_type: "binary"}] if is_bin
|
178
|
+
return [true, {type: "immediate", value: bin_value, def_type: "binary", definition: operand_str}] if is_bin
|
176
179
|
|
177
180
|
is_decimal, decimal_value = check_decimal_operand(operand_str)
|
178
|
-
return [true, {type: "immediate", value: decimal_value, def_type: "decimal"}] if is_decimal
|
181
|
+
return [true, {type: "immediate", value: decimal_value, def_type: "decimal", definition: operand_str}] if is_decimal
|
179
182
|
|
180
183
|
is_hex, hex_value = check_hex_operand(operand_str)
|
181
|
-
return [true, {type: "immediate", value: hex_value, def_type: "hex"}] if is_hex
|
184
|
+
return [true, {type: "immediate", value: hex_value, def_type: "hex", definition: operand_str}] if is_hex
|
182
185
|
|
183
186
|
is_char, char_value = check_char_operand(operand_str)
|
184
|
-
return [true, {type: "immediate", value: char_value, def_type: "char"}] if is_char
|
187
|
+
return [true, {type: "immediate", value: char_value, def_type: "char", definition: operand_str}] if is_char
|
185
188
|
|
186
189
|
return [false, nil]
|
187
190
|
end
|
@@ -208,11 +211,11 @@ def self.parse_operand_str(operand_str)
|
|
208
211
|
|
209
212
|
# Check if the operand is a register
|
210
213
|
is_register, register = check_register_operand(operand_str)
|
211
|
-
return {type: "register", value: register, register: register} if is_register
|
214
|
+
return {type: "register", value: register, register: register, definition: operand_str} if is_register
|
212
215
|
|
213
216
|
# Check if the operand is a string
|
214
217
|
is_string = operand_str[0] == "\""
|
215
|
-
return {type: "string", value: operand_str[1...-1], string: operand_str[1...-1]} if is_string
|
218
|
+
return {type: "string", value: operand_str[1...-1], string: operand_str[1...-1], definition: operand_str} if is_string
|
216
219
|
|
217
220
|
# Checks if it's an immediate
|
218
221
|
is_immediate, immediate_val = check_immediate_operand(operand_str)
|
@@ -225,7 +228,7 @@ def self.parse_operand_str(operand_str)
|
|
225
228
|
|
226
229
|
# The operand is a label if it doesn't start with a number and doesn't include spaces
|
227
230
|
is_label = check_label_operand(operand_str)
|
228
|
-
return {type: "label", value: operand_str} if is_label
|
231
|
+
return {type: "label", value: operand_str, definition: operand_str} if is_label
|
229
232
|
|
230
233
|
|
231
234
|
# If no checks succeeded, return false
|
@@ -319,128 +322,37 @@ end
|
|
319
322
|
|
320
323
|
|
321
324
|
|
322
|
-
|
323
|
-
|
324
|
-
# def self.parse_instruction_line(line)
|
325
|
-
# keyword = ""
|
326
|
-
# i = 0
|
327
|
-
#
|
328
|
-
# # Loop until a non-whitespace character
|
329
|
-
# while i < line.size
|
330
|
-
# break if ![" ", "\t"].include?(line[i])
|
331
|
-
# i += 1
|
332
|
-
# end
|
333
|
-
#
|
334
|
-
# # Loop to get the keyword
|
335
|
-
# loop do
|
336
|
-
# # Exit out of the loop if the character is a whitespace
|
337
|
-
# break if [" ", "\t"].include?(line[i]) || i >= line.size
|
338
|
-
# # Add the character if not a whitespace
|
339
|
-
# keyword << line[i]
|
340
|
-
# # Proceed to the next character
|
341
|
-
# i += 1
|
342
|
-
# end
|
343
|
-
#
|
344
|
-
# operand_strings = []
|
345
|
-
#
|
346
|
-
# # Loop for operands
|
347
|
-
# loop do
|
348
|
-
# break if i >= line.size
|
349
|
-
#
|
350
|
-
# # Whitespace - skip
|
351
|
-
# if [" ", "\t"].include? line[i]
|
352
|
-
# i += 1
|
353
|
-
# next
|
354
|
-
# end
|
355
|
-
#
|
356
|
-
# # If a string operand - parse the string
|
357
|
-
# if line[i] == "\""
|
358
|
-
#
|
359
|
-
# str_content, parsed_size = parse_str(line[i..])
|
360
|
-
# operand_strings << line[i...(i + parsed_size)]
|
361
|
-
# i += parsed_size
|
362
|
-
#
|
363
|
-
# # If anything else - parse until whitespace, comma or end of line
|
364
|
-
# else
|
365
|
-
# content = ""
|
366
|
-
#
|
367
|
-
# while i < line.size
|
368
|
-
# break if [" ", ","].include? line[i]
|
369
|
-
# content << line[i]
|
370
|
-
# i += 1
|
371
|
-
# end
|
372
|
-
#
|
373
|
-
# operand_strings << content
|
374
|
-
# end
|
375
|
-
#
|
376
|
-
#
|
377
|
-
# # After operand parsed
|
378
|
-
# # Loop to meet a comma or end of line
|
379
|
-
# # Give error if stuff except whitespace
|
380
|
-
#
|
381
|
-
# while i < line.size
|
382
|
-
# # If comma, move to next character and repeat the bigger operand loop
|
383
|
-
# if line[i] == ","
|
384
|
-
# i += 1
|
385
|
-
# break
|
386
|
-
# end
|
387
|
-
# # If non-whitespace, raise an error
|
388
|
-
# # raise "Error: Unparsed content - exiting" if ![" ", "\t"].include?(line[i])
|
389
|
-
# return false if ![" ", "\t"].include?(line[i])
|
390
|
-
# i += 1
|
391
|
-
# end
|
392
|
-
# end
|
393
|
-
#
|
394
|
-
# # If end of line not reached, return an error
|
395
|
-
# if i != line.size
|
396
|
-
# return false
|
397
|
-
# end
|
398
|
-
#
|
399
|
-
#
|
400
|
-
# # Parse operand strings into operand types and values
|
401
|
-
#
|
402
|
-
# operands = []
|
403
|
-
#
|
404
|
-
# operand_strings.each do |operand_str|
|
405
|
-
# operand = parse_operand_str(operand_str)
|
406
|
-
# return false if operand == false
|
407
|
-
# operands << operand
|
408
|
-
# end
|
409
|
-
#
|
410
|
-
# return [keyword, operands]
|
411
|
-
# end
|
412
|
-
|
413
|
-
|
414
|
-
|
415
325
|
def self.check_operand_match(operand_description, operand)
|
416
326
|
|
417
327
|
# If operand type doesn't not match, return false
|
418
328
|
return false if operand[:type] != operand_description[:type]
|
419
329
|
|
420
|
-
#
|
421
|
-
|
330
|
+
# Get the restrictions
|
331
|
+
operand_restrictions = operand_description[:restrictions]
|
332
|
+
return true if !operand_restrictions # If no restrictions, return true
|
422
333
|
|
423
|
-
|
334
|
+
# Get the operand's values / encoding
|
335
|
+
case operand[:type]
|
424
336
|
when "register"
|
425
|
-
|
426
|
-
# Check register type match
|
427
|
-
if operand_description[:restrictions].keys.include?(:reg_type)
|
428
|
-
return false if operand[:register][:reg_type] != operand_description[:restrictions][:reg_type]
|
429
|
-
end
|
430
|
-
|
431
|
-
# Check register size match
|
432
|
-
if operand_description[:restrictions].keys.include?(:reg_size)
|
433
|
-
return false if operand[:register][:reg_size] != operand_description[:restrictions][:reg_size]
|
434
|
-
end
|
435
|
-
|
337
|
+
operand_encoding = operand[:value]
|
436
338
|
when "immediate"
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
339
|
+
operand_encoding = operand[:value]
|
340
|
+
when "string"
|
341
|
+
operand_encoding = Hash.new
|
342
|
+
end
|
343
|
+
|
344
|
+
# Loop through each restriction to see if the operand matches it
|
345
|
+
operand_restrictions.each do |r_key, r_spec|
|
346
|
+
# Get the restricted value of the operand
|
347
|
+
op_value = operand_encoding[r_key]
|
348
|
+
|
349
|
+
# Check if it matches the restriction specification
|
350
|
+
# If an array, the OR algorithm works (the operand key value must be one of the specified values in the r_spec list)
|
351
|
+
if r_spec.is_a? Array
|
352
|
+
return false if !r_spec.include?(op_value)
|
353
|
+
else # If not an array, just check of equality
|
354
|
+
return false if op_value != r_spec
|
355
|
+
end
|
444
356
|
end
|
445
357
|
|
446
358
|
|
@@ -448,6 +360,9 @@ def self.check_operand_match(operand_description, operand)
|
|
448
360
|
return true
|
449
361
|
end
|
450
362
|
|
363
|
+
|
364
|
+
|
365
|
+
|
451
366
|
|
452
367
|
# Returns array of [status, operands]
|
453
368
|
# If status = false, operands = nil; otherwise, status = true, operands = instruction operands
|
@@ -531,4 +446,4 @@ end
|
|
531
446
|
end # End Kompiler::Parsers
|
532
447
|
|
533
448
|
|
534
|
-
end # End Kompiler
|
449
|
+
end # End Kompiler
|
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.
|
4
|
+
version: 0.3.0.pre.1
|
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-12-
|
11
|
+
date: 2024-12-13 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
|
@@ -30,6 +30,8 @@ files:
|
|
30
30
|
- lib/kompiler/architectures/armv8a/instructions.rb
|
31
31
|
- lib/kompiler/architectures/armv8a/load.rb
|
32
32
|
- lib/kompiler/architectures/armv8a/registers.rb
|
33
|
+
- lib/kompiler/architectures/armv8a/sys_instructions.rb
|
34
|
+
- lib/kompiler/architectures/armv8a/sys_registers.rb
|
33
35
|
- lib/kompiler/compiler_functions.rb
|
34
36
|
- lib/kompiler/directives.rb
|
35
37
|
- lib/kompiler/mc_builder.rb
|