kompiler 0.2.0 → 0.3.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|