kompiler 0.3.0.pre.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b00e5940820b7f2798ede46f7014a87ab43d7ade0ca171c223eae550668673c0
4
- data.tar.gz: dcd9d7bd8d170a37206d51a6b427c48217d115f048620404b045a8f6005eb6e0
3
+ metadata.gz: 90ed49bc46f0641a23f0d7d561489d4ec326e8f3bb933a638ed789831e9ee362
4
+ data.tar.gz: 9c0d4b1f795b9e7a2b73a145218a972854fdd8372808a6fb68b3c210899d2ad8
5
5
  SHA512:
6
- metadata.gz: 023ae20fa5229d793e71ebea06bc46dea243170129e12eaf5c099c16dabdabcecb6302f0893ef17cbf0128c30a8d7d9f0b77841ecfa6ddb871d18e0c517373d4
7
- data.tar.gz: ae856004b38f75b46b4b62c7455c5f94cbeb2f21dd34e54443ff776f4fbb23432eb42f389bd706f3d649c8b2d69bee3a3e2d2cf7095d24178c32e50f32b47149
6
+ metadata.gz: 8a18cb49c4740e3f5d86a074c75a87c90db0de718dad6ec2547b802d1acf70dd4a726fcc163ba6bf17f83b58c91e02a0e331f48b707a2ac6d80ac331f4c852fc
7
+ data.tar.gz: c54ac313fed9b03a22810678244e0809dc29f25c0974c2ded1251fac7e6d01f2c28f50a0844938532eda6d7ec90b78ddf8afb0634485662ef1246677c18bc5d5
data/bin/kompile CHANGED
@@ -16,29 +16,117 @@
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 (ARGV.size == 1) && ["--help", "-h"].include?(ARGV[0])
21
- puts """Usage: kompile [options] | [<input_file> <output_file> [architecture]]
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
- Available options:
24
- --help, -h Prints this screen
25
- --list-architectures Prints available architectures
26
- -L Alias to --list-architectures
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)
27
101
 
28
- To compile, run:
29
- kompile <input_file> <output_file> [architecture]
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)
30
105
 
31
- Arguments:
32
- <input_file> The path to the input file
33
- <output_file> The path where the compiled output will be saved
34
- [architecture] (Optional) One of the installed architectures to use for compilation (defaults to \"armv8a\")
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]
112
+
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
+ --mach-o-machine=<cputype.subtype> Specifies Mach-O header's cputype and subtype
116
+ to be the type provided
117
+
118
+ Available options:
119
+ --help, -h Prints this information
120
+ --list-architectures Lists available architectures
121
+ --list-instructions [arch] Lists available instructions for the specified architecture
122
+ --list-registers [arch] Lists available registers for the specified architecture
35
123
  """
36
124
  exit # Exit
37
125
  end
38
126
 
39
127
 
40
128
  # Print the available architectures if requested
41
- if (ARGV.size == 1) && ["--list-architectures", "-L"].include?(ARGV[0])
129
+ if arg_opts == ["list-architectures"]
42
130
  Kompiler::ArchManager.load_all_entries()
43
131
  puts "Available architectures:"
44
132
 
@@ -48,52 +136,161 @@ if (ARGV.size == 1) && ["--list-architectures", "-L"].include?(ARGV[0])
48
136
  exit # Exit
49
137
  end
50
138
 
51
- in_filename = ARGV[0]
52
- out_filename = ARGV[1]
53
- arch_name = ARGV[2] || "armv8a"
139
+ if arg_opts == ["list-instructions"]
140
+ arch_name = arg_words[0] || "armv8a"
141
+ Kompiler::ArchManager.load_all_entries()
142
+ arch = Kompiler::ArchManager.get_arch(arch_name)
143
+
144
+ require arch[:include_path]
145
+
146
+ Kompiler::Architecture.instructions.each do |instr|
147
+ puts "#{instr[:keyword]} (#{instr[:operands].size} operands): #{instr[:name]}"
148
+ puts instr[:description]
149
+ puts
150
+ end
151
+
152
+ exit
153
+ end
154
+
155
+ if arg_opts == ["list-registers"]
156
+ arch_name = arg_words[0] || "armv8a"
157
+ Kompiler::ArchManager.load_all_entries()
158
+ arch = Kompiler::ArchManager.get_arch(arch_name)
159
+
160
+ require arch[:include_path]
161
+
162
+ Kompiler::Architecture.registers.each do |reg|
163
+ puts "#{reg[:reg_name]}"
164
+ end
165
+
166
+ exit
167
+ end
168
+
169
+
170
+
171
+ if arg_words.size < 1
172
+ puts "kompile: No input file path provided."
173
+ puts "Type \"kompile --help\" for more information."
174
+ exit
175
+ end
176
+
177
+ in_filename = arg_words[0]
178
+ out_filename = (arg_words.size > 1) ? arg_words[1] : "out.bin"
179
+
54
180
 
55
181
  if !in_filename
56
182
  puts "Error: No input file provided"
57
183
  exit
58
184
  end
59
185
 
186
+ if !File.exist?(in_filename)
187
+ puts "Error: File \"#{in_filename}\" doesn't exist"
188
+ exit
189
+ end
190
+
191
+
60
192
  if !out_filename
61
193
  puts "Error: No output file provided"
62
194
  exit
63
195
  end
64
196
 
65
- if !File.exist?(in_filename)
66
- puts "Error: #{in_filename} doesn't exist"
197
+
198
+
199
+
200
+
201
+ wrap_opt = arg_keys.select{_1[0] == "wrap"}
202
+
203
+
204
+ if wrap_opt.size > 1
205
+ puts "kompile: Only one wrapping option can be provided with \"--wrap\"."
206
+ puts "Type \"kompile --help\" for more information."
67
207
  exit
208
+ elsif wrap_opt.size == 1
209
+ wrap_opt = wrap_opt[0][1]
210
+ else
211
+ wrap_opt = "none"
68
212
  end
69
213
 
70
- # Load all the architecture entries
71
214
 
72
- Kompiler::ArchManager.load_all_entries()
215
+ if !["elf.obj", "elf.exec", "mach-o.obj", "mach-o.exec", "none"].include?(wrap_opt)
216
+ puts "kompile: Unknown wrapping option \"#{wrap_opt}\"."
217
+ puts "Type \"kompile --help\" for more information."
218
+ exit
219
+ end
73
220
 
74
- # Find the right architecture
75
- arch = Kompiler::ArchManager.get_arch(arch_name)
76
221
 
77
- if arch == nil
78
- puts "Error: Architecture \"#{arch_name}\" not found."
222
+
223
+
224
+ arch_opt = arg_keys.select{_1[0] == "arch"}
225
+
226
+ if arch_opt.size > 1
227
+ puts "kompile: Only one architecture can be provided with \"--arch\"."
228
+ puts "Type \"kompile --help\" for more information."
79
229
  exit
230
+ elsif arch_opt.size == 1
231
+ arch_name = arch_opt[0][1]
232
+ else
233
+ arch_name = "armv8a"
80
234
  end
81
235
 
82
- # Get the include path for the architecture
83
- arch_include_path = arch[:include_path]
236
+ # Load all the architecture entries
237
+
238
+ Kompiler::ArchManager.load_all_entries()
84
239
 
85
240
  # Load the architecture
241
+
242
+ arch_config = Kompiler::ArchManager.get_arch(arch_name)
243
+
244
+ if arch_config == nil
245
+ puts "kompile: Could not find the architecture \"#{arch_name}\"."
246
+ puts "Type \"kompile --list-architectures\" for the list of known architectures."
247
+ exit
248
+ end
249
+
86
250
  begin
87
- require arch_include_path
88
- rescue LoadError => e
89
- puts "Error: Could not load #{arch_name} architecture's configuration."
251
+ Kompiler::ArchManager.load_arch(arch_name)
252
+ rescue
253
+ puts "kompile: Could not load the architecture \"#{arch_name}\"."
90
254
  exit
91
255
  end
92
256
 
93
- code = File.read(in_filename)
94
257
 
95
- compiled_bytes_str = Kompiler::CompilerFunctions.compile(code, [in_filename])
96
258
 
97
- File.open(out_filename, "wb") do |file|
98
- file.write compiled_bytes_str
259
+ code = File.binread(in_filename)
260
+
261
+ detailed_out = Kompiler::CompilerFunctions.detailed_compile(code)
262
+
263
+ # p detailed_out
264
+
265
+ out = nil
266
+
267
+ code = detailed_out[:machine_code]
268
+ labels = detailed_out[:labels]
269
+
270
+ labels.delete "here"
271
+
272
+
273
+ case wrap_opt
274
+ when "none"
275
+ out = code
276
+ when "elf.obj"
277
+ elf_machine = arg_keys.filter{_1[0] == "elf-machine"}[0]
278
+ elf_machine = (elf_machine != nil) ? elf_machine[1].to_i : 0
279
+ symbols = Kompiler::Wrappers::ELF.labels_to_symbols(labels)
280
+ out = Kompiler::Wrappers::ELF.wrap_obj(code, symbols, machine: elf_machine)
281
+ when "elf.exec"
282
+ elf_machine = arg_keys.filter{_1[0] == "elf-machine"}[0]
283
+ elf_machine = (elf_machine != nil) ? elf_machine[1].to_i : 0
284
+ symbols = Kompiler::Wrappers::ELF.labels_to_symbols(labels)
285
+ out = Kompiler::Wrappers::ELF.wrap_exec(code, symbols, machine: elf_machine)
286
+ when "mach-o.obj"
287
+ puts "Mach-O not yet implemented."
288
+ exit
289
+ when "mach-o.exec"
290
+ puts "Mach-O not yet implemented."
291
+ exit
99
292
  end
293
+
294
+
295
+ File.binwrite out_filename, out
296
+
@@ -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
- description: "MVN writes the bitwise opposite of the source register to the destination register",
57
- operands: [{type: "register", restrictions: {reg_size: 64}, name: "Destination"}, {type: "register", restrictions: {reg_size: 64}, name: "Source"}],
58
- mc_constructor: [
59
- ["get_bits", ["encode_gp_register", ["get_operand", 0]], 0, 5], # Rd
60
- ["bits", 1,1,1,1,1], # Rn
61
- ["bits", 0,0,0,0,0,0], # imm6 (shift amount) set to zero
62
- ["get_bits", ["encode_gp_register", ["get_operand", 1]], 0, 5], # Rm
63
- ["bits", 1, 0,0, 0,1,0,1,0,1,0, 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, 0] # N - shift type (zero / LSL) - bits
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
- operands: [{type: "register", restrictions: {reg_type: "gpr"}}, {type: "register", restrictions: {reg_type: "gpr"}}, {type: "immediate"}],
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: "Register 1"}, {type: "register", restrictions: {reg_type: "gpr"}, name: "Register 2"}],
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: "Or",
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: {reg_size: 64}, name: "Destination"}, {type: "register", restrictions: {reg_size: 64}, name: "Register 1"}, {type: "register", restrictions: {reg_size: 64}, name: "Register 2"}],
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, 1],
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
- operands: [{type: "immediate"}],
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
- operands: [{type: "label"}],
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)