haxor 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,7 +4,7 @@ require_relative '../lib/haxor'
4
4
  require 'optparse'
5
5
 
6
6
  parser = OptionParser.new do |opts|
7
- opts.banner = 'Usage: hcc [options] [file.hax]'
7
+ opts.banner = 'Usage: hc [options] [file.hax]'
8
8
 
9
9
  opts.on_tail('-h', '--help', 'Show this message') do
10
10
  puts opts
@@ -28,12 +28,4 @@ end
28
28
  source = File.absolute_path ARGV[0]
29
29
 
30
30
  compiler = Haxor::Compiler::Core.new
31
- compiler.register_unit Haxor::Compiler::Component::Arithmetic.new
32
- compiler.register_unit Haxor::Compiler::Component::Data.new
33
- compiler.register_unit Haxor::Compiler::Component::Jumps.new
34
- compiler.register_unit Haxor::Compiler::Component::Logical.new
35
- compiler.register_unit Haxor::Compiler::Component::Other.new
36
- compiler.register_unit Haxor::Compiler::Component::Transfer.new
37
- compiler.register_unit Haxor::Compiler::Component::Various.new
38
-
39
31
  compiler.compile source
data/bin/hvm CHANGED
@@ -26,11 +26,16 @@ if ARGV[0].nil?
26
26
  exit
27
27
  end
28
28
 
29
- vm = Haxor::Vm::Core.new
30
-
31
- filename = ARGV[0]
32
- # make life easier ;)
33
- filename += '.e' if filename.end_with? '.hax'
34
-
35
- vm.load_program filename
36
- vm.execute
29
+ begin
30
+ vm = Haxor::Vm::Core.new
31
+
32
+ filename = ARGV[0]
33
+ # make life easier ;)
34
+ filename += '.e' if filename.end_with? '.hax'
35
+
36
+ vm.load_program filename
37
+ vm.execute
38
+ rescue => e
39
+ puts "An error occurred: #{e}."
40
+ exit 1
41
+ end
@@ -5,6 +5,6 @@ set -e
5
5
 
6
6
  for program in *.hax ; do
7
7
  echo "Compiling example $program ..."
8
- ../bin/hcc $program
8
+ ../bin/hc $program
9
9
  ../bin/hld -o $program.e $program.u
10
10
  done
@@ -11,90 +11,79 @@ dw min, 1
11
11
  dw max, 1000
12
12
 
13
13
  section .bss
14
- dw number, 0
15
- dw answer, 0
16
- dw tries, 0
14
+ dw number
15
+ dw answer
16
+ dw tries
17
17
 
18
18
  section .text
19
- label bigger
20
- mov sc, 02h
21
- lea r01, bigger_msg
22
- push r01
23
- push 1
24
- syscall
25
- jmp question
26
19
 
27
- label smaller
28
- mov sc, 02h
29
- lea r01, smaller_msg
30
- push r01
31
- push 1
32
- syscall
33
- jmp question
20
+ bigger:
21
+ addi $sc, $0, 01h
22
+ pushi bigger_msg
23
+ pushi 1
24
+ syscall
25
+ j question
34
26
 
35
- label win
36
- mov sc, 02h
37
- push tries
38
- lea r01, win_msg
39
- push r01
40
- push 1
41
- syscall
42
- jmp exit
27
+ smaller:
28
+ addi $sc, $0, 01h
29
+ pushi smaller_msg
30
+ pushi 1
31
+ syscall
32
+ j question
43
33
 
44
- label invalid_number
45
- mov sc, 02h
46
- lea r01, invalid_msg
47
- push r01
48
- push 1
49
- syscall
50
- jmp question
34
+ win:
35
+ addi $sc, $0, 01h
36
+ pushm tries
37
+ pushi win_msg
38
+ push 1
39
+ syscall
40
+ exiti 0
51
41
 
52
- label main
42
+ invalid_number:
43
+ addi $sc, $0, 01h
44
+ pushi invalid_msg
45
+ push 1
46
+ syscall
47
+ j question
53
48
 
54
- label welcome
55
- mov sc, 02h
56
- lea r01, welcome_msg
57
- push r01
58
- push 1
59
- syscall
49
+ main:
50
+ addi $sc, $0, 01h
51
+ pushi welcome_msg
52
+ push 1
53
+ syscall
60
54
 
61
- label generate
62
- mov sc, 02h
63
- push max
64
- push min
65
- lea r01, generate_msg
66
- push r01
67
- push 1
68
- syscall
69
- mov sc, 04h
70
- push max
71
- push min
72
- syscall
73
- pop number
55
+ generate:
56
+ addi $sc, $0, 01h
57
+ pushm max
58
+ pushm min
59
+ pushi generate_msg
60
+ pushi 1
61
+ syscall
62
+ addi $sc, $0, 03h
63
+ pushm max
64
+ pushm min
65
+ syscall
66
+ popm number
74
67
 
75
- label question
76
- mov sc, 02h
77
- lea r01, question_msg
78
- push r01
79
- push 1
80
- syscall
81
- mov sc, 03h
82
- lea r01, answer
83
- push r01
84
- lea r01, answer_fmt
85
- push r01
86
- push 0
87
- syscall
88
- cmp sc, -1
89
- je invalid_number
90
- inc tries
68
+ question:
69
+ addi $sc, $0, 01h
70
+ pushi question_msg
71
+ pushi 1
72
+ syscall
73
+ addi $sc, $0, 02h
74
+ pushi answer
75
+ pushi answer_fmt
76
+ pushi 0
77
+ syscall
91
78
 
92
- cmp number, answer
93
- je win
94
- jg bigger
95
- jl smaller
79
+ addi $5, $0, -1
80
+ beq $sc, $5, invalid_number
81
+ lw $6, $0, tries
82
+ addi $6, $6, 1
83
+ sw $0, tries, $6
96
84
 
97
- label exit
98
- mov sc, 01h
99
- push 0
100
- syscall
85
+ lw $7, $0, number
86
+ lw $8, $0, answer
87
+ beq $7, $8, win
88
+ bgt $7, $8, bigger
89
+ blt $7, $8, smaller
@@ -3,9 +3,11 @@ require 'json'
3
3
  require 'io/console'
4
4
  require 'scanf'
5
5
  require 'digest'
6
+ require 'ostruct'
6
7
 
7
8
  require_relative 'haxor/consts'
8
9
  require_relative 'haxor/header'
10
+ require_relative 'haxor/utils'
9
11
 
10
12
  # vm
11
13
  require_relative 'haxor/vm/core'
@@ -15,24 +17,10 @@ require_relative 'haxor/vm/stack'
15
17
  require_relative 'haxor/vm/os'
16
18
  require_relative 'haxor/vm/registers'
17
19
  require_relative 'haxor/vm/cpu/core'
18
- require_relative 'haxor/vm/cpu/unit/base'
19
- require_relative 'haxor/vm/cpu/unit/logical'
20
- require_relative 'haxor/vm/cpu/unit/arithmetic'
21
- require_relative 'haxor/vm/cpu/unit/jumps'
22
- require_relative 'haxor/vm/cpu/unit/various'
23
- require_relative 'haxor/vm/cpu/unit/transfer'
24
20
 
25
21
  # compiler
26
22
  require_relative 'haxor/compiler/unit'
27
23
  require_relative 'haxor/compiler/core'
28
- require_relative 'haxor/compiler/component/base'
29
- require_relative 'haxor/compiler/component/logical'
30
- require_relative 'haxor/compiler/component/arithmetic'
31
- require_relative 'haxor/compiler/component/jumps'
32
- require_relative 'haxor/compiler/component/various'
33
- require_relative 'haxor/compiler/component/transfer'
34
- require_relative 'haxor/compiler/component/data'
35
- require_relative 'haxor/compiler/component/other'
36
24
 
37
25
  # linker
38
26
  require_relative 'haxor/linker'
@@ -1,25 +1,85 @@
1
1
  module Haxor
2
2
  module Compiler
3
3
  class Core
4
+ REG_ALIASES = {
5
+ '$sp' => Vm::Cpu::Core::REG_STACK,
6
+ '$ret' => Vm::Cpu::Core::REG_RETURN,
7
+ '$sc' => Vm::Cpu::Core::REG_SYSCALL
8
+ }
9
+
4
10
  def initialize
5
11
  @units = []
6
- @cmds = {}
12
+ @cmds = []
7
13
  @autolabel = 0
8
14
  @prev_sections = []
9
15
 
10
- bind_cmd 'section', self, :cmd_section
16
+ init_cmds
11
17
  end
12
18
 
13
- def register_unit(unit)
14
- @units << unit
15
- unit.compiler = self
16
- unit.register
19
+ def init_cmds
20
+ bind_cmd 'section', [:any], :cmd_section
21
+ bind_cmd 'dw', [:wildcard], :cmd_dw
22
+ bind_cmd 'resw', [:any], :cmd_resw
23
+ bind_cmd '#', [:wildcard], :cmd_rem
24
+ bind_cmd 'push', [:reg], :cmd_push
25
+ bind_cmd 'pushi', [:imm], :cmd_pushi
26
+ bind_cmd 'pushm', [:imm], :cmd_pushm
27
+ bind_cmd 'pop', [:reg], :cmd_pop
28
+ bind_cmd 'popm', [:imm], :cmd_popm
29
+ bind_cmd 'move', [:reg, :reg], :cmd_move
30
+ bind_cmd 'clear', [:reg], :cmd_clear
31
+ bind_cmd 'not', [:reg, :reg], :cmd_not
32
+ bind_cmd 'ret', [], :cmd_ret
33
+
34
+ bind_cmd 'b', [:imm], :cmd_b
35
+ bind_cmd 'bal', [:imm], :cmd_bal
36
+ bind_cmd 'bgt', [:reg, :reg, :imm], :cmd_bgt
37
+ bind_cmd 'blt', [:reg, :reg, :imm], :cmd_blt
38
+ bind_cmd 'bge', [:reg, :reg, :imm], :cmd_bge
39
+ bind_cmd 'ble', [:reg, :reg, :imm], :cmd_ble
40
+ bind_cmd 'blez', [:reg, :imm], :cmd_blez
41
+ bind_cmd 'bgtz', [:reg, :imm], :cmd_bgtz
42
+ bind_cmd 'beqz', [:reg, :imm], :cmd_beqz
43
+
44
+ bind_cmd 'nop', [], Vm::Cpu::Core::OP_NOP
45
+ bind_cmd 'add', [:reg, :reg, :reg], Vm::Cpu::Core::OP_ADD
46
+ bind_cmd 'addi', [:reg, :reg, :imm], Vm::Cpu::Core::OP_ADDI
47
+ bind_cmd 'sub', [:reg, :reg, :reg], Vm::Cpu::Core::OP_SUB
48
+ bind_cmd 'mult', [:reg, :reg, :reg], Vm::Cpu::Core::OP_MULT
49
+ bind_cmd 'div', [:reg, :reg, :reg], Vm::Cpu::Core::OP_DIV
50
+ bind_cmd 'mod', [:reg, :reg, :reg], Vm::Cpu::Core::OP_MOD
51
+ bind_cmd 'lw', [:reg, :reg, :imm], Vm::Cpu::Core::OP_LW
52
+ bind_cmd 'sw', [:reg, :imm, :reg], Vm::Cpu::Core::OP_SW
53
+ bind_cmd 'lui', [:reg, :imm], Vm::Cpu::Core::OP_LUI
54
+ bind_cmd 'and', [:reg, :reg, :reg], Vm::Cpu::Core::OP_AND
55
+ bind_cmd 'andi', [:reg, :reg, :imm], Vm::Cpu::Core::OP_ANDI
56
+ bind_cmd 'or', [:reg, :reg, :reg], Vm::Cpu::Core::OP_OR
57
+ bind_cmd 'ori', [:reg, :reg, :imm], Vm::Cpu::Core::OP_ORI
58
+ bind_cmd 'xor', [:reg, :reg, :reg], Vm::Cpu::Core::OP_XOR
59
+ bind_cmd 'nor', [:reg, :reg, :reg], Vm::Cpu::Core::OP_NOR
60
+ bind_cmd 'slt', [:reg, :reg, :reg], Vm::Cpu::Core::OP_SLT
61
+ bind_cmd 'slti', [:reg, :reg, :imm], Vm::Cpu::Core::OP_SLTI
62
+ bind_cmd 'slli', [:reg, :reg, :imm], Vm::Cpu::Core::OP_SLLI
63
+ bind_cmd 'srli', [:reg, :reg, :imm], Vm::Cpu::Core::OP_SRLI
64
+ bind_cmd 'sll', [:reg, :reg, :reg], Vm::Cpu::Core::OP_SLL
65
+ bind_cmd 'srl', [:reg, :reg, :reg], Vm::Cpu::Core::OP_SRL
66
+ bind_cmd 'beq', [:reg, :reg, :imm], Vm::Cpu::Core::OP_BEQ, [:rel_imm, :x8]
67
+ bind_cmd 'beql', [:reg, :reg, :imm], Vm::Cpu::Core::OP_BEQL, [:rel_imm, :x8]
68
+ bind_cmd 'bne', [:reg, :reg, :imm], Vm::Cpu::Core::OP_BNE, [:rel_imm, :x8]
69
+ bind_cmd 'bnel', [:reg, :reg, :imm], Vm::Cpu::Core::OP_BNEL, [:rel_imm, :x8]
70
+ bind_cmd 'j', [:imm], Vm::Cpu::Core::OP_J, [:x8]
71
+ bind_cmd 'jr', [:reg], Vm::Cpu::Core::OP_JR
72
+ bind_cmd 'jal', [:imm], Vm::Cpu::Core::OP_JAL, [:x8]
73
+ bind_cmd 'exiti', [:imm], Vm::Cpu::Core::OP_EXITI
74
+ bind_cmd 'syscall', [], Vm::Cpu::Core::OP_SYSCALL
17
75
  end
18
76
 
19
- def bind_cmd(cmd, object, method)
20
- @cmds[cmd] = {
21
- object: object,
22
- method: method
77
+ def bind_cmd(cmd, args, opcode, opts = [])
78
+ @cmds << {
79
+ cmd: cmd,
80
+ args: args,
81
+ opcode: opcode,
82
+ opts: opts
23
83
  }
24
84
  end
25
85
 
@@ -27,6 +87,122 @@ module Haxor
27
87
  @unit.section = name[1..-1].to_sym
28
88
  end
29
89
 
90
+ def cmd_dw(*args)
91
+ add Token::Label.new(args[0])
92
+
93
+ if args.size == 1
94
+ add Token::Int64.new(0)
95
+ else
96
+ (1...args.size).each do |i|
97
+ begin
98
+ add Token::Int64.new(Integer(args[i]))
99
+ rescue
100
+ args[i][1...-1].each_char do |c|
101
+ add Token::Int64.new(c.ord)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ def cmd_resw(*args)
109
+ (1..args[0].to_i).each do
110
+ add Token::Int64.new(0)
111
+ end
112
+ end
113
+
114
+ def cmd_rem(*)
115
+ end
116
+
117
+ def cmd_push(*args)
118
+ process_cmd 'addi', ['$sp', '$sp', '-' + Consts::WORD_SIZE.to_s]
119
+ process_cmd 'sw', ['$sp', '0', args[0]]
120
+ end
121
+
122
+ def cmd_pushi(*args)
123
+ process_cmd 'addi', ['$1', '$0', args[0]]
124
+ process_cmd 'addi', ['$sp', '$sp', '-' + Consts::WORD_SIZE.to_s]
125
+ process_cmd 'sw', ['$sp', '0', '$1']
126
+ end
127
+
128
+ def cmd_pushm(*args)
129
+ process_cmd 'lw', ['$1', '$0', args[0]]
130
+ process_cmd 'addi', ['$sp', '$sp', '-' + Consts::WORD_SIZE.to_s]
131
+ process_cmd 'sw', ['$sp', '0', '$1']
132
+ end
133
+
134
+ def cmd_pop(*args)
135
+ process_cmd 'lw', [args[0], '$sp', '0']
136
+ process_cmd 'addi', ['$sp', '$sp', Consts::WORD_SIZE.to_s]
137
+ end
138
+
139
+ def cmd_popm(*args)
140
+ process_cmd 'lw', ['$1', '$sp', '0']
141
+ process_cmd 'sw', ['$0', args[0], '$1']
142
+ process_cmd 'addi', ['$sp', '$sp', Consts::WORD_SIZE.to_s]
143
+ end
144
+
145
+ def cmd_move(*args)
146
+ process_cmd 'add', [args[0], args[1], '$0']
147
+ end
148
+
149
+ def cmd_clear(*args)
150
+ process_cmd 'add', [args[0], '$0', '$0']
151
+ end
152
+
153
+ def cmd_not(*args)
154
+ process_cmd 'nor', [args[0], args[1], '$0']
155
+ end
156
+
157
+ def cmd_ret(*_args)
158
+ process_cmd 'jr', ['$' + Vm::Cpu::Core::REG_RETURN.to_s]
159
+ end
160
+
161
+ def cmd_b(*args)
162
+ process_cmd 'beq', ['$0', '$0', args[0]]
163
+ end
164
+
165
+ def cmd_bal(*args)
166
+ process_cmd 'beql', ['$0', '$0', args[0]]
167
+ end
168
+
169
+ # branch is greater than
170
+ def cmd_bgt(*args)
171
+ process_cmd 'slt', ['$1', args[1], args[0]]
172
+ process_cmd 'bne', ['$1', '$0', args[2]]
173
+ end
174
+
175
+ # branch if less than
176
+ def cmd_blt(*args)
177
+ process_cmd 'slt', ['$1', args[0], args[1]]
178
+ process_cmd 'bne', ['$1', '$0', args[2]]
179
+ end
180
+
181
+ # branch is greater or equal
182
+ def cmd_bge(*args)
183
+ process_cmd 'slt', ['$1', args[0], args[1]]
184
+ process_cmd 'beq', ['$1', '$0', args[2]]
185
+ end
186
+
187
+ def cmd_ble(*args)
188
+ process_cmd 'slt', ['$1', args[1], args[0]]
189
+ process_cmd 'beq', ['$1', '$0', args[2]]
190
+ end
191
+
192
+ def cmd_blez(*args)
193
+ process_cmd 'slt', ['$1', '$0', args[0]]
194
+ process_cmd 'beq', ['$1', '$0', args[1]]
195
+ end
196
+
197
+ def cmd_bgtz(*args)
198
+ process_cmd 'slt', ['$1', '$0', args[0]]
199
+ process_cmd 'bne', ['$1', '$0', args[1]]
200
+ end
201
+
202
+ def cmd_beqz(*args)
203
+ process_cmd 'beq', [args[0], '$0', args[1]]
204
+ end
205
+
30
206
  # this is ugly and must be reworked
31
207
  def split_arguments(string)
32
208
  inside_quotes = false
@@ -52,6 +228,23 @@ module Haxor
52
228
  args.map!(&:strip).delete_if { |x| x.length == 0 }
53
229
  end
54
230
 
231
+ def process_cmd(cmd, args)
232
+ @cmds.each do |item|
233
+ next if item[:cmd] != cmd
234
+
235
+ if item[:opcode].is_a? Symbol
236
+ send(item[:opcode], *args)
237
+ return
238
+ end
239
+
240
+ add_cmd item, args
241
+ return
242
+ end
243
+
244
+ puts cmd
245
+ fail
246
+ end
247
+
55
248
  def compile(filename)
56
249
  input = File.read(filename, encoding: 'ASCII-8BIT')
57
250
 
@@ -64,9 +257,11 @@ module Haxor
64
257
  cmd = tmp[0]
65
258
  args = split_arguments(tmp[1] || '')
66
259
 
67
- fail "Unknown command #{cmd} in line #{index}." unless @cmds.key? cmd
68
-
69
- @cmds[cmd][:object].send(@cmds[cmd][:method], *args)
260
+ if cmd[-1] == ':'
261
+ add Token::Label.new(cmd[0...-1])
262
+ else
263
+ process_cmd(cmd, args)
264
+ end
70
265
  end
71
266
 
72
267
  @unit.save(filename + '.u')
@@ -76,11 +271,47 @@ module Haxor
76
271
  @unit.add token
77
272
  end
78
273
 
79
- def add_cmd(opcode, a = nil, b = nil)
80
- opcode |= offset_flags(a, b)
81
- add Token::Cmd.new(opcode)
82
- parse_value a unless a.nil?
83
- parse_value b unless b.nil?
274
+ # def resolve_arg(a, type)
275
+ # case type
276
+ # when :reg
277
+ # return a[1..-1].to_i
278
+ # when :imm
279
+ # return a.to_i
280
+ # else
281
+ # fail
282
+ # end
283
+ # end
284
+
285
+ def add_cmd(info, args = [])
286
+ registers = []
287
+ immediate = 0
288
+ info[:args].each_with_index do |type, index|
289
+ if type == :reg
290
+ if REG_ALIASES.key? args[index]
291
+ registers << REG_ALIASES[args[index]]
292
+ else
293
+ registers << args[index][1..-1].to_i
294
+ end
295
+ elsif type == :imm
296
+ begin
297
+ immediate = parse_number args[index]
298
+ rescue
299
+ immediate = args[index]
300
+ end
301
+ end
302
+ end
303
+
304
+ registers.fill 0, registers.size...3
305
+
306
+ token = Token::Cmd.new
307
+ token.cmd = info[:opcode]
308
+ token.reg1 = registers[0]
309
+ token.reg2 = registers[1]
310
+ token.reg3 = registers[2]
311
+ token.imm = immediate
312
+ token.opts = info[:opts]
313
+
314
+ add token
84
315
  end
85
316
 
86
317
  def parse_number(value)