kompiler 0.3.0.pre.4 → 0.3.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/bin/kompile +241 -33
- data/lib/kompiler/arch_manager.rb +10 -1
- data/lib/kompiler/architecture.rb +5 -1
- data/lib/kompiler/architectures/armv8a/instructions.rb +76 -27
- data/lib/kompiler/architectures/armv8a/load.rb +3 -1
- data/lib/kompiler/architectures/armv8a/simd_fp_instructions.rb +1308 -0
- data/lib/kompiler/architectures/armv8a/simd_fp_registers.rb +23 -0
- data/lib/kompiler/architectures/armv8a/sys_registers.rb +3 -0
- data/lib/kompiler/compiler_functions.rb +32 -8
- data/lib/kompiler/config.rb +12 -1
- data/lib/kompiler/directives.rb +13 -0
- data/lib/kompiler/math_ast.rb +29 -1
- data/lib/kompiler/mc_builder.rb +48 -0
- data/lib/kompiler/parsers.rb +21 -0
- data/lib/kompiler/wrappers/elf_wrapper.rb +697 -0
- data/lib/kompiler/wrappers/packed_bytes.rb +68 -0
- data/lib/kompiler/wrappers.rb +1 -0
- data/lib/kompiler.rb +2 -1
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 18cda0db09b288b5ad14ebb5feb99e13fe03ea5a7897d603285b0aab0c8bdb77
|
4
|
+
data.tar.gz: e84247276f40846adef9798d8ea6584dc3fe156caaa18495c668ee7f99506e9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d682ae38a0d09b9ca8c584de5a3687554a97962ab227fcfb1bd7f458d0f5c48ff1ca0386db8ddcd6f80832e5d94a53b12a655164a23e58bd168128dd8a05106e
|
7
|
+
data.tar.gz: 04e832aff94a2948615b3f9ca03db1cc75648673873ec9a4678aab6f09aa24b595d9a276910cf53f00de34dffebb0bfc7675b1150749bdfcbe6225bae2778401
|
data/bin/kompile
CHANGED
@@ -16,29 +16,118 @@
|
|
16
16
|
|
17
17
|
require 'kompiler'
|
18
18
|
|
19
|
+
|
20
|
+
arg_string = ARGV.join(" ")
|
21
|
+
|
22
|
+
arg_words = []
|
23
|
+
arg_keys = []
|
24
|
+
arg_opts = []
|
25
|
+
arg_letters = []
|
26
|
+
|
27
|
+
current_i = 0
|
28
|
+
|
29
|
+
permitted_word_chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a + ["_", ".", "-"]
|
30
|
+
|
31
|
+
whitespace_chars = ["\t", " "]
|
32
|
+
|
33
|
+
def get_word string, permitted_word_chars, offset = 0
|
34
|
+
if string[0] == '"'
|
35
|
+
str_content, n_parsed = Kompiler::Parsers.parse_str(string[offset..])
|
36
|
+
return str_content, n_parsed + offset
|
37
|
+
else
|
38
|
+
current_i = offset
|
39
|
+
word = ""
|
40
|
+
while permitted_word_chars.include? string[current_i]
|
41
|
+
word << string[current_i]
|
42
|
+
current_i += 1
|
43
|
+
end
|
44
|
+
return word, current_i
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
while current_i < arg_string.size
|
50
|
+
|
51
|
+
if whitespace_chars.include? arg_string[current_i]
|
52
|
+
current_i += 1
|
53
|
+
end
|
54
|
+
|
55
|
+
if arg_string[current_i] == "-" && arg_string[current_i + 1] == "-"
|
56
|
+
current_i += 2
|
57
|
+
keyword, current_i = get_word(arg_string, permitted_word_chars, current_i)
|
58
|
+
|
59
|
+
|
60
|
+
if arg_string[current_i] == "="
|
61
|
+
current_i += 1
|
62
|
+
value, current_i = get_word(arg_string, permitted_word_chars, current_i)
|
63
|
+
|
64
|
+
arg_keys << [keyword, value]
|
65
|
+
elsif whitespace_chars.include?(arg_string[current_i]) || current_i == arg_string.size
|
66
|
+
arg_opts << keyword
|
67
|
+
else
|
68
|
+
puts "Unrecognized argument syntax at index #{current_i}"
|
69
|
+
exit
|
70
|
+
end
|
71
|
+
|
72
|
+
next
|
73
|
+
end
|
74
|
+
|
75
|
+
if arg_string[current_i] == "-"
|
76
|
+
current_i += 1
|
77
|
+
|
78
|
+
letters, current_i = get_word(arg_string, permitted_word_chars, current_i)
|
79
|
+
|
80
|
+
arg_letters += letters.chars
|
81
|
+
|
82
|
+
next
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
word, current_i = get_word(arg_string, permitted_word_chars, current_i)
|
87
|
+
arg_words << word
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
|
19
93
|
# Print the help screen if requested
|
20
|
-
if (
|
21
|
-
puts """Usage: kompile
|
94
|
+
if arg_opts.include?("help") || arg_letters.include?("h")
|
95
|
+
puts """Usage: kompile <input_file> [<output_file>] [compile_options]
|
96
|
+
or: kompile OPTION
|
22
97
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
98
|
+
Compile a file:
|
99
|
+
input_file Path to the input file
|
100
|
+
output_file Path to the output file (optional, default is out.bin)
|
101
|
+
|
102
|
+
Compilation options:
|
103
|
+
--arch=<arch_name> Compile for the specified architecture (optional, default is armv8a)
|
104
|
+
--wrap=<format> Wrap the compiled program in the specified format (default is none)
|
27
105
|
|
28
|
-
|
29
|
-
|
106
|
+
Available wrapping formats:
|
107
|
+
none
|
108
|
+
elf.obj
|
109
|
+
elf.exec
|
110
|
+
mach-o.obj [not implemented yet]
|
111
|
+
mach-o.exec [not implemented yet]
|
30
112
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
113
|
+
Additional options for wrapping are:
|
114
|
+
--elf-machine=<type> Specifies ELF header's e_machine to be the type provided (default is 0)
|
115
|
+
--elf-class=<class> Specifies the ELF file's class to either 32 or 64 (default is 64)
|
116
|
+
--mach-o-machine=<cputype.subtype> Specifies Mach-O header's cputype and subtype
|
117
|
+
to be the type provided
|
118
|
+
|
119
|
+
Available options:
|
120
|
+
--help, -h Prints this information
|
121
|
+
--list-architectures Lists available architectures
|
122
|
+
--list-instructions [arch] Lists available instructions for the specified architecture
|
123
|
+
--list-registers [arch] Lists available registers for the specified architecture
|
35
124
|
"""
|
36
125
|
exit # Exit
|
37
126
|
end
|
38
127
|
|
39
128
|
|
40
129
|
# Print the available architectures if requested
|
41
|
-
if
|
130
|
+
if arg_opts == ["list-architectures"]
|
42
131
|
Kompiler::ArchManager.load_all_entries()
|
43
132
|
puts "Available architectures:"
|
44
133
|
|
@@ -48,52 +137,171 @@ if (ARGV.size == 1) && ["--list-architectures", "-L"].include?(ARGV[0])
|
|
48
137
|
exit # Exit
|
49
138
|
end
|
50
139
|
|
51
|
-
|
52
|
-
|
53
|
-
|
140
|
+
if arg_opts == ["list-instructions"]
|
141
|
+
arch_name = arg_words[0] || "armv8a"
|
142
|
+
Kompiler::ArchManager.load_all_entries()
|
143
|
+
arch = Kompiler::ArchManager.get_arch(arch_name)
|
144
|
+
|
145
|
+
require arch[:include_path]
|
146
|
+
|
147
|
+
Kompiler::Architecture.instructions.each do |instr|
|
148
|
+
puts "#{instr[:keyword]} (#{instr[:operands].size} operands): #{instr[:name]}"
|
149
|
+
puts instr[:description]
|
150
|
+
puts
|
151
|
+
end
|
152
|
+
|
153
|
+
exit
|
154
|
+
end
|
155
|
+
|
156
|
+
if arg_opts == ["list-registers"]
|
157
|
+
arch_name = arg_words[0] || "armv8a"
|
158
|
+
Kompiler::ArchManager.load_all_entries()
|
159
|
+
arch = Kompiler::ArchManager.get_arch(arch_name)
|
160
|
+
|
161
|
+
require arch[:include_path]
|
162
|
+
|
163
|
+
Kompiler::Architecture.registers.each do |reg|
|
164
|
+
puts "#{reg[:reg_name]}"
|
165
|
+
end
|
166
|
+
|
167
|
+
exit
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
|
172
|
+
if arg_words.size < 1
|
173
|
+
puts "kompile: No input file path provided."
|
174
|
+
puts "Type \"kompile --help\" for more information."
|
175
|
+
exit
|
176
|
+
end
|
177
|
+
|
178
|
+
in_filename = arg_words[0]
|
179
|
+
out_filename = (arg_words.size > 1) ? arg_words[1] : "out.bin"
|
180
|
+
|
54
181
|
|
55
182
|
if !in_filename
|
56
183
|
puts "Error: No input file provided"
|
57
184
|
exit
|
58
185
|
end
|
59
186
|
|
187
|
+
if !File.exist?(in_filename)
|
188
|
+
puts "Error: File \"#{in_filename}\" doesn't exist"
|
189
|
+
exit
|
190
|
+
end
|
191
|
+
|
192
|
+
|
60
193
|
if !out_filename
|
61
194
|
puts "Error: No output file provided"
|
62
195
|
exit
|
63
196
|
end
|
64
197
|
|
65
|
-
|
66
|
-
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
wrap_opt = arg_keys.select{_1[0] == "wrap"}
|
203
|
+
|
204
|
+
|
205
|
+
if wrap_opt.size > 1
|
206
|
+
puts "kompile: Only one wrapping option can be provided with \"--wrap\"."
|
207
|
+
puts "Type \"kompile --help\" for more information."
|
67
208
|
exit
|
209
|
+
elsif wrap_opt.size == 1
|
210
|
+
wrap_opt = wrap_opt[0][1]
|
211
|
+
else
|
212
|
+
wrap_opt = "none"
|
68
213
|
end
|
69
214
|
|
70
|
-
# Load all the architecture entries
|
71
215
|
|
72
|
-
|
216
|
+
if !["elf.obj", "elf.exec", "mach-o.obj", "mach-o.exec", "none"].include?(wrap_opt)
|
217
|
+
puts "kompile: Unknown wrapping option \"#{wrap_opt}\"."
|
218
|
+
puts "Type \"kompile --help\" for more information."
|
219
|
+
exit
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
|
73
224
|
|
74
|
-
|
75
|
-
arch = Kompiler::ArchManager.get_arch(arch_name)
|
225
|
+
arch_opt = arg_keys.select{_1[0] == "arch"}
|
76
226
|
|
77
|
-
if
|
78
|
-
puts "
|
227
|
+
if arch_opt.size > 1
|
228
|
+
puts "kompile: Only one architecture can be provided with \"--arch\"."
|
229
|
+
puts "Type \"kompile --help\" for more information."
|
79
230
|
exit
|
231
|
+
elsif arch_opt.size == 1
|
232
|
+
arch_name = arch_opt[0][1]
|
233
|
+
else
|
234
|
+
arch_name = "armv8a"
|
80
235
|
end
|
81
236
|
|
82
|
-
#
|
83
|
-
|
237
|
+
# Load all the architecture entries
|
238
|
+
|
239
|
+
Kompiler::ArchManager.load_all_entries()
|
84
240
|
|
85
241
|
# Load the architecture
|
242
|
+
|
243
|
+
arch_config = Kompiler::ArchManager.get_arch(arch_name)
|
244
|
+
|
245
|
+
if arch_config == nil
|
246
|
+
puts "kompile: Could not find the architecture \"#{arch_name}\"."
|
247
|
+
puts "Type \"kompile --list-architectures\" for the list of known architectures."
|
248
|
+
exit
|
249
|
+
end
|
250
|
+
|
86
251
|
begin
|
87
|
-
|
88
|
-
rescue
|
89
|
-
puts "
|
252
|
+
Kompiler::ArchManager.load_arch(arch_name)
|
253
|
+
rescue
|
254
|
+
puts "kompile: Could not load the architecture \"#{arch_name}\"."
|
90
255
|
exit
|
91
256
|
end
|
92
257
|
|
93
|
-
code = File.read(in_filename)
|
94
258
|
|
95
|
-
compiled_bytes_str = Kompiler::CompilerFunctions.compile(code, [in_filename])
|
96
259
|
|
97
|
-
File.
|
98
|
-
|
260
|
+
code = File.binread(in_filename)
|
261
|
+
|
262
|
+
detailed_out = Kompiler::CompilerFunctions.detailed_compile(code)
|
263
|
+
|
264
|
+
# p detailed_out
|
265
|
+
|
266
|
+
out = nil
|
267
|
+
|
268
|
+
code = detailed_out[:machine_code]
|
269
|
+
labels = detailed_out[:labels]
|
270
|
+
|
271
|
+
labels.delete "here"
|
272
|
+
|
273
|
+
|
274
|
+
case wrap_opt
|
275
|
+
when "none"
|
276
|
+
out = code
|
277
|
+
when "elf.obj"
|
278
|
+
elf_machine = arg_keys.filter{_1[0] == "elf-machine"}[0]
|
279
|
+
elf_machine = (elf_machine != nil) ? elf_machine[1].to_i : 0
|
280
|
+
|
281
|
+
elf_class = arg_keys.filter{_1[0] == "elf-class"}[0]
|
282
|
+
elf_class ||= ["elf-class", "64"]
|
283
|
+
elf_class = elf_class[1].to_i
|
284
|
+
|
285
|
+
symbols = Kompiler::Wrappers::ELF.labels_to_symbols(labels)
|
286
|
+
out = Kompiler::Wrappers::ELF.wrap_obj(code, symbols, machine: elf_machine, elf_class: elf_class)
|
287
|
+
when "elf.exec"
|
288
|
+
elf_machine = arg_keys.filter{_1[0] == "elf-machine"}[0]
|
289
|
+
elf_machine = (elf_machine != nil) ? elf_machine[1].to_i : 0
|
290
|
+
|
291
|
+
elf_class = arg_keys.filter{_1[0] == "elf-class"}[0]
|
292
|
+
elf_class ||= ["elf-class", "64"]
|
293
|
+
elf_class = elf_class[1].to_i
|
294
|
+
|
295
|
+
symbols = Kompiler::Wrappers::ELF.labels_to_symbols(labels)
|
296
|
+
out = Kompiler::Wrappers::ELF.wrap_exec(code, symbols, machine: elf_machine, elf_class: elf_class)
|
297
|
+
when "mach-o.obj"
|
298
|
+
puts "Mach-O not yet implemented."
|
299
|
+
exit
|
300
|
+
when "mach-o.exec"
|
301
|
+
puts "Mach-O not yet implemented."
|
302
|
+
exit
|
99
303
|
end
|
304
|
+
|
305
|
+
|
306
|
+
File.binwrite out_filename, out
|
307
|
+
|
@@ -1,6 +1,11 @@
|
|
1
1
|
# Copyright 2024 Kyrylo Shyshko
|
2
2
|
# Licensed under the Apache License, Version 2.0. See LICENSE file for details.
|
3
3
|
|
4
|
+
#
|
5
|
+
# Implements logic for managing all available architectures.
|
6
|
+
#
|
7
|
+
|
8
|
+
|
4
9
|
module Kompiler
|
5
10
|
|
6
11
|
# Object for managing architecture entries / available architectures
|
@@ -22,6 +27,10 @@ module Kompiler
|
|
22
27
|
def self.load_all_entries
|
23
28
|
Gem.find_files("kompiler/arch_entries/*").each { |file| require file }
|
24
29
|
end
|
30
|
+
|
31
|
+
def self.load_arch arch_name
|
32
|
+
require get_arch(arch_name)[:include_path]
|
33
|
+
end
|
25
34
|
end
|
26
35
|
|
27
|
-
end
|
36
|
+
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
# Copyright 2024 Kyrylo Shyshko
|
2
2
|
# Licensed under the Apache License, Version 2.0. See LICENSE file for details.
|
3
3
|
|
4
|
+
#
|
5
|
+
# Implements logic to set and read info of the currently used architecture.
|
6
|
+
#
|
7
|
+
|
4
8
|
module Kompiler
|
5
9
|
|
6
10
|
module Architecture
|
@@ -27,4 +31,4 @@ end
|
|
27
31
|
|
28
32
|
end
|
29
33
|
|
30
|
-
end
|
34
|
+
end
|
@@ -13,7 +13,7 @@ end
|
|
13
13
|
{ keyword: "mov",
|
14
14
|
name: "Move (immediate)",
|
15
15
|
description: "Moves an immediate value to the destination register",
|
16
|
-
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination"}, {type: "immediate", restrictions: {}, name: "Immediate value"}],
|
16
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination register"}, {type: "immediate", restrictions: {}, name: "Immediate value"}],
|
17
17
|
mc_constructor: [
|
18
18
|
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
19
19
|
["get_bits", ["get_operand", 1], 0, 16],
|
@@ -25,7 +25,7 @@ end
|
|
25
25
|
{ keyword: "mov",
|
26
26
|
name: "Move (register)",
|
27
27
|
description: "Copies the value in the source register to the destination register",
|
28
|
-
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source"}],
|
28
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination register"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source register"}],
|
29
29
|
mc_constructor: [
|
30
30
|
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "mov Error: Register sizes are not the same"]],
|
31
31
|
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
|
@@ -40,7 +40,7 @@ end
|
|
40
40
|
{ keyword: "mov_sp",
|
41
41
|
name: "Move (to/from SP)",
|
42
42
|
description: "Move between a general-purpose register and the stack pointer.",
|
43
|
-
operands: [{type: "register", restrictions: {reg_type: "gpr"}}, {type: "register", restrictions: {reg_type: "gpr"}}],
|
43
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination register"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source register"}],
|
44
44
|
mc_constructor: [
|
45
45
|
# Get the non-SP register
|
46
46
|
["if_eq_else", ["downcase_str", ["get_key", ["get_operand", 0], :reg_name]], "sp", ["set_var", "non_sp_reg", ["get_operand", 1]], ["set_var", "non_sp_reg", ["get_operand", 0]]],
|
@@ -53,32 +53,26 @@ end
|
|
53
53
|
bitsize: 32
|
54
54
|
},
|
55
55
|
{ keyword: "mvn", # MVN writes the bitwise opposite of the source register to a destination register
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
|
60
|
-
["bits", 1,1,1,1,1], # Rn
|
61
|
-
["bits", 0,0,0,0,0,0], # imm6 (shift amount) set to zero
|
62
|
-
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rm
|
63
|
-
["bits", 1, 0,0, 0,1,0,1,0,1,0, 1] # N - shift type (zero / LSL) - bits
|
64
|
-
],
|
65
|
-
bitsize: 32
|
66
|
-
},
|
67
|
-
{ keyword: "mvn", # MVN writes the bitwise opposite of the source register to a destination register
|
68
|
-
description: "MVN writes the bitwise opposite of the source register to the destination register",
|
69
|
-
operands: [{type: "register", restrictions: {reg_size: 32}, name: "Destination"}, {type: "register", restrictions: {reg_size: 32}, name: "Source"}],
|
56
|
+
name: "Move inverse",
|
57
|
+
description: "Writes the bitwise opposite of the source register value to the destination register.",
|
58
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination register"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source register"}],
|
70
59
|
mc_constructor: [
|
60
|
+
["ensure_eq", ["get_operand_key", 0, :reg_size], ["get_operand_key", 1, :reg_size], "mvn Error: Register sizes are not the same."],
|
61
|
+
|
71
62
|
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
|
72
63
|
["bits", 1,1,1,1,1], # Rn
|
73
64
|
["bits", 0,0,0,0,0,0], # imm6 (shift amount) set to zero
|
74
65
|
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rm
|
75
|
-
["bits", 1, 0,0, 0,1,0,1,0,1,0,
|
66
|
+
["bits", 1, 0,0, 0,1,0,1,0,1,0], # N - shift type (zero / LSL) - bits
|
67
|
+
["case", ["get_operand_key", 0, :reg_size], 32, ["bits", 0], 64, ["bits", 1], [0]]
|
76
68
|
],
|
77
69
|
bitsize: 32
|
78
70
|
},
|
79
71
|
{
|
80
72
|
keyword: "add",
|
81
|
-
|
73
|
+
name: "Add (immediate)",
|
74
|
+
description: "Adds the source register value and the immediate value, and writes the result to the destination register.",
|
75
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination register"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source register"}, {type: "immediate", name: "Immediate value"}],
|
82
76
|
mc_constructor: [
|
83
77
|
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "add Error: Register sizes are not the same"]],
|
84
78
|
|
@@ -95,7 +89,7 @@ end
|
|
95
89
|
keyword: "add",
|
96
90
|
name: "ADD (registers)",
|
97
91
|
description: "Adds two source registers and writes the result to the destination register",
|
98
|
-
operands: [{type: "register", restrictions: {reg_type: "gpr"}}, {type: "register", restrictions: {reg_type: "gpr"}}, {type: "register", restrictions: {reg_type: "gpr"}}],
|
92
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination register"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source register 2"}],
|
99
93
|
mc_constructor: [
|
100
94
|
# Make sure register sizes are the same
|
101
95
|
["if_eq_else", ["get_key", ["get_operand", 0], :reg_size], ["get_key", ["get_operand", 1], :reg_size], [], ["raise_error", "add Error: Register sizes are not the same"]],
|
@@ -115,9 +109,9 @@ end
|
|
115
109
|
|
116
110
|
{
|
117
111
|
keyword: "and",
|
118
|
-
name: "And (register)",
|
112
|
+
name: "Bitwise And (register)",
|
119
113
|
description: "Performs a bitwise AND of two register values and writes the result to the destination register.",
|
120
|
-
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "
|
114
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination register"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source register 2"}],
|
121
115
|
mc_constructor: [
|
122
116
|
["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"]],
|
123
117
|
["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"]],
|
@@ -135,17 +129,21 @@ end
|
|
135
129
|
|
136
130
|
{
|
137
131
|
keyword: "orr", # And between registers, with shift set to zero
|
138
|
-
name: "
|
132
|
+
name: "Bitwise OR (register)",
|
139
133
|
description: "Computes a logical bit-wise OR operation between two registers and writes the result to the destination register.",
|
140
|
-
operands: [{type: "register", restrictions: {
|
134
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination register"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Source register 2"}],
|
141
135
|
mc_constructor: [
|
136
|
+
["ensure_eq", ["get_operand_key", 0, :reg_size], ["get_operand_key", 1, :reg_size], "orr Error: Register sizes are not the same."],
|
137
|
+
|
142
138
|
["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5],
|
143
139
|
["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5],
|
144
140
|
["get_bits", 0, 0, 6], # imm6 (shift amount) set to zero
|
145
141
|
["get_bits", ["encode_gp_register", ["get_operand", 2]], 0, 5],
|
146
142
|
["bits", 0], # N
|
147
143
|
["bits", 0,0], # shift type
|
148
|
-
["bits", 0,1,0,1,0, 1,0
|
144
|
+
["bits", 0,1,0,1,0, 1,0],
|
145
|
+
|
146
|
+
["case", ["get_operand_key", 0, :reg_size], 32, ["bits", 0], 64, ["bits", 1], ["bits", 0]],
|
149
147
|
],
|
150
148
|
bitsize: 32
|
151
149
|
},
|
@@ -180,13 +178,17 @@ end
|
|
180
178
|
},
|
181
179
|
{
|
182
180
|
keyword: "b",
|
183
|
-
|
181
|
+
name: "Branch (immediate)",
|
182
|
+
description: "Branches (jumps) to a PC-relative offset specified by the immediae value.",
|
183
|
+
operands: [{type: "immediate", name: "Immediate PC Offset"}],
|
184
184
|
mc_constructor: [["get_bits", ["get_operand", 0], 0, 26], ["bits", 1,0,1,0,0,0]],
|
185
185
|
bitsize: 32
|
186
186
|
},
|
187
187
|
{
|
188
188
|
keyword: "b",
|
189
|
-
|
189
|
+
name: "Branch (label)",
|
190
|
+
description: "Branches (jumps) to a label using a PC-relative offset.",
|
191
|
+
operands: [{type: "label", name: "Program label"}],
|
190
192
|
mc_constructor: [
|
191
193
|
["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
|
192
194
|
["get_bits", ["divide", ["subtract", ["get_label_address", ["get_operand", 0]], ["get_current_address"]], 4], 0, 26],
|
@@ -196,6 +198,8 @@ end
|
|
196
198
|
},
|
197
199
|
{
|
198
200
|
keyword: "br",
|
201
|
+
name: "Branch (register)",
|
202
|
+
description: "Branches (jumps) to an address in a register.",
|
199
203
|
operands: [{type: "register", restrictions: {reg_size: 64}}],
|
200
204
|
mc_constructor: [
|
201
205
|
["bits", 0,0,0,0,0],
|
@@ -206,6 +210,8 @@ end
|
|
206
210
|
},
|
207
211
|
{
|
208
212
|
keyword: "bl",
|
213
|
+
name: "Branch with link (label)",
|
214
|
+
description: "Branches (jumps) to a label using a PC-relative offset, and sets the register X30 to PC + 4.",
|
209
215
|
operands: [{type: "label"}],
|
210
216
|
mc_constructor: [
|
211
217
|
["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
|
@@ -1148,6 +1154,49 @@ end
|
|
1148
1154
|
bitsize: 32
|
1149
1155
|
},
|
1150
1156
|
|
1157
|
+
{
|
1158
|
+
keyword: "sxtw",
|
1159
|
+
name: "Sign Extend Word",
|
1160
|
+
description: "Sign extends the 32-bit signed integer in the source general-purpose register to a 64-bit signed integer, and writes the result to the destination general-purpose register.",
|
1161
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr", reg_size: 64}, name: "Destination register"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 32}, name: "Source register"}],
|
1162
|
+
mc_constructor: [
|
1163
|
+
["get_bits", ["get_operand_key", 0, :reg_value], 0, 5],
|
1164
|
+
["get_bits", ["get_operand_key", 1, :reg_value], 0, 5],
|
1165
|
+
["bits", 1,1,1,1,1,0, 0,0,0,0,0,0, 1, 0,1,1,0,0,1, 0,0, 1],
|
1166
|
+
],
|
1167
|
+
bitsize: 32
|
1168
|
+
},
|
1169
|
+
{
|
1170
|
+
keyword: "sxth",
|
1171
|
+
name: "Sign Extend Halfword",
|
1172
|
+
description: "Sign extends the 16-bit signed integer in the source general-purpose register to the size of the destination register, and writes the result to the destination general-purpose register.",
|
1173
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination register"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 32}, name: "Source register"}],
|
1174
|
+
mc_constructor: [
|
1175
|
+
["get_bits", ["get_operand_key", 0, :reg_value], 0, 5],
|
1176
|
+
["get_bits", ["get_operand_key", 1, :reg_value], 0, 5],
|
1177
|
+
["bits", 1,1,1,1,0,0, 0,0,0,0,0,0],
|
1178
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []],
|
1179
|
+
["bits", 0,1,1,0,0,1, 0,0],
|
1180
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []],
|
1181
|
+
],
|
1182
|
+
bitsize: 32
|
1183
|
+
},
|
1184
|
+
{
|
1185
|
+
keyword: "sxtb",
|
1186
|
+
name: "Sign Extend Byte",
|
1187
|
+
description: "Sign extends the 8-bit signed integer in the source general-purpose register to the size of the destination register, and writes the result to the destination general-purpose register.",
|
1188
|
+
operands: [{type: "register", restrictions: {reg_type: "gpr"}, name: "Destination register"}, {type: "register", restrictions: {reg_type: "gpr", reg_size: 32}, name: "Source register"}],
|
1189
|
+
mc_constructor: [
|
1190
|
+
["get_bits", ["get_operand_key", 0, :reg_value], 0, 5],
|
1191
|
+
["get_bits", ["get_operand_key", 1, :reg_value], 0, 5],
|
1192
|
+
["bits", 1,1,1,0,0,0, 0,0,0,0,0,0],
|
1193
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []],
|
1194
|
+
["bits", 0,1,1,0,0,1, 0,0],
|
1195
|
+
["case", ["get_key", ["get_operand", 0], :reg_size], 64, ["bits", 1], 32, ["bits", 0], []],
|
1196
|
+
],
|
1197
|
+
bitsize: 32
|
1198
|
+
},
|
1199
|
+
|
1151
1200
|
]
|
1152
1201
|
|
1153
1202
|
end # Kompiler::ARMv8A
|
@@ -5,6 +5,8 @@ require 'kompiler/architectures/armv8a/instructions.rb'
|
|
5
5
|
require 'kompiler/architectures/armv8a/sys_instructions.rb'
|
6
6
|
require 'kompiler/architectures/armv8a/registers.rb'
|
7
7
|
require 'kompiler/architectures/armv8a/sys_registers.rb'
|
8
|
+
require 'kompiler/architectures/armv8a/simd_fp_instructions.rb'
|
9
|
+
require 'kompiler/architectures/armv8a/simd_fp_registers.rb'
|
8
10
|
|
9
11
|
|
10
|
-
Kompiler::Architecture.set_arch(Kompiler::ARMv8A.instructions + Kompiler::ARMv8A.sys_instructions, Kompiler::ARMv8A.registers + Kompiler::ARMv8A.sys_registers)
|
12
|
+
Kompiler::Architecture.set_arch(Kompiler::ARMv8A.instructions + Kompiler::ARMv8A.sys_instructions + Kompiler::ARMv8A.simd_fp_instructions, Kompiler::ARMv8A.registers + Kompiler::ARMv8A.sys_registers + Kompiler::ARMv8A.simd_fp_registers)
|