diff --git a/lib/arm/arm_machine.rb b/lib/arm/arm_machine.rb index 2b340024..39f62f82 100644 --- a/lib/arm/arm_machine.rb +++ b/lib/arm/arm_machine.rb @@ -11,27 +11,27 @@ module Arm class ArmMachine < Vm::CMachine def integer_less_or_equal block , first , right - block << cmp( first , right: right ) + block << cmp( first , right ) Vm::Bool.new end def integer_plus block , result , first , right - block << add( result , left: first , :extra => right ) + block << add( result , first , right ) result end def integer_minus block , result , first , right - block << sub( result , left: first , :extra => right ) + block << sub( result , first , right ) result end def integer_load block , first , right - block << mov( first , right: right ) + block << mov( first , right ) first end def integer_move block , first , right - block << mov( first , right: right ) + block << mov( first , right ) first end @@ -82,17 +82,17 @@ module Arm # And coding it is a bit of a mind leap: it's all about finding a a result that gets the # remainder smaller than an int. i'll post some links sometime. This is from the arm manual block.instance_eval do - sub( remainder , left: number , right: 10 ) - sub( number , left: number , right: number , shift_lsr: 2) - add( number , left: number , right: number , shift_lsr: 4) - add( number , left: number , right: number , shift_lsr: 8) - add( number , left: number , right: number , shift_lsr: 16) - mov( number , right: number , shift_lsr: 3) + sub( remainder , number , 10 ) + sub( number , number , number , shift_lsr: 2) + add( number , number , number , shift_lsr: 4) + add( number , number , number , shift_lsr: 8) + add( number , number , number , shift_lsr: 16) + mov( number , number , shift_lsr: 3) tmp = Vm::Integer.new( remainder.register + 1) - add( tmp , left: number , right: number , shift_lsl: 2) - sub( remainder , left: remainder , right: tmp , shift_lsl: 1 , update_status: 1) - add( number , left: number, right: 1 , condition_code: :pl ) - add( remainder , left: remainder , right: 10 , condition_code: :mi ) + add( tmp , number , number , shift_lsl: 2) + sub( remainder , remainder , tmp , shift_lsl: 1 , update_status: 1) + add( number , number, 1 , condition_code: :pl ) + add( remainder , remainder , 10 , condition_code: :mi ) end end diff --git a/lib/arm/logic_instruction.rb b/lib/arm/logic_instruction.rb index 0abbb453..165bca4f 100644 --- a/lib/arm/logic_instruction.rb +++ b/lib/arm/logic_instruction.rb @@ -3,13 +3,12 @@ module Arm class LogicInstruction < Vm::LogicInstruction include Arm::Constants - def initialize(first , attributes) - super(first , attributes) + def initialize(result , left , right , attributes) + super(result ,left , right , attributes) @attributes[:update_status] = 0 if @attributes[:update_status] == nil @attributes[:condition_code] = :al if @attributes[:condition_code] == nil @operand = 0 - @left = @attributes[:left] raise "Left arg must be given #{inspect}" unless @left @immediate = 0 end @@ -21,7 +20,7 @@ module Arm # Build representation for source value def build - right = @attributes[:right] + right = @right if @left.is_a?(Vm::StringConstant) # do pc relative addressing with the difference to the instuction # 8 is for the funny pipeline adjustment (ie pointing to fetch and not execute) @@ -57,7 +56,7 @@ module Arm build instuction_class = 0b00 # OPC_DATA_PROCESSING val = shift(@operand , 0) - val |= shift(reg_code(@first) , 12) + val |= shift(reg_code(@result) , 12) val |= shift(reg_code(@left) , 12+4) val |= shift(@attributes[:update_status] , 12+4+4)#20 val |= shift(op_bit_code , 12+4+4 +1) diff --git a/lib/core/kernel.rb b/lib/core/kernel.rb index 816ec624..bacb6871 100644 --- a/lib/core/kernel.rb +++ b/lib/core/kernel.rb @@ -43,8 +43,8 @@ module Core itos_fun = context.program.get_or_create_function(:utoa) block.instance_eval do mov( reg1 , right: str_addr ) #move arg up - add( str_addr , left: buffer ) # string to write to - add( str_addr , left: str_addr , right: (buffer.length-3)) + add( str_addr , buffer ,nil ) # string to write to + add( str_addr , str_addr , (buffer.length-3)) call( itos_fun , {}) # And now we "just" have to print it, using the write_stdout add( str_addr , left: buffer ) # string to write to @@ -67,10 +67,10 @@ module Core Vm::CMachine.instance.div10( block , number , remainder ) # make char out of digit (by using ascii encoding) 48 == "0" block.instance_eval do - add( remainder , left: remainder , right: 48 ) + add( remainder , remainder , 48 ) strb( remainder, right: str_addr ) - sub( str_addr, left: str_addr , right: 1 ) - cmp( number , right: 0 ) + sub( str_addr, str_addr , 1 ) + cmp( number , 0 ) callne( function , {} ) end return function diff --git a/lib/vm/block.rb b/lib/vm/block.rb index bf3289f8..d59024e6 100644 --- a/lib/vm/block.rb +++ b/lib/vm/block.rb @@ -67,11 +67,7 @@ module Vm # sugar to create instructions easily. Any method with one arg is sent to the machine and the result # (hopefully an instruction) added as code def method_missing(meth, *args, &block) - if args.length == 2 - add_code CMachine.instance.send(meth , *args) - else - super - end + add_code CMachine.instance.send(meth , *args) end end diff --git a/lib/vm/c_machine.rb b/lib/vm/c_machine.rb index 5871d695..165f8f7d 100644 --- a/lib/vm/c_machine.rb +++ b/lib/vm/c_machine.rb @@ -48,7 +48,7 @@ module Vm define_instruction_one(inst , StackInstruction) end [:adc, :add, :and, :bic, :eor, :orr, :rsb, :rsc, :sbc, :sub].each do |inst| - define_instruction_one(inst , LogicInstruction) + define_instruction_three(inst , LogicInstruction) end [:mov, :mvn].each do |inst| define_instruction_one(inst , MoveInstruction) @@ -104,11 +104,22 @@ module Vm # same for two args (left right, from to etc) def define_instruction_two(inst , clazz , defaults = {} ) clazz = class_for(clazz) - create_method(inst) do |first ,second , options = nil| + create_method(inst) do |left ,right , options = nil| options = {} if options == nil options.merge defaults options[:opcode] = inst - clazz.new(first , second ,options) + clazz.new(left , right ,options) + end + end + + # same for three args (result = left right,) + def define_instruction_three(inst , clazz , defaults = {} ) + clazz = class_for(clazz) + create_method(inst) do |result , left ,right , options = nil| + options = {} if options == nil + options.merge defaults + options[:opcode] = inst + clazz.new(result, left , right ,options) end end diff --git a/lib/vm/instruction.rb b/lib/vm/instruction.rb index 98338f69..3187efe3 100644 --- a/lib/vm/instruction.rb +++ b/lib/vm/instruction.rb @@ -43,8 +43,10 @@ module Vm end end class LogicInstruction < Instruction - def initialize first , options - @first = first + def initialize result , left , right , options + @result = result + @left = left + @right = right super(options) end end diff --git a/test/arm/test_arm.rb b/test/arm/test_arm.rb index b1aeb09c..9bdd18f6 100644 --- a/test/arm/test_arm.rb +++ b/test/arm/test_arm.rb @@ -14,10 +14,6 @@ class TestArmAsm < MiniTest::Test code = @machine.call -4 ,{} #this jumps to the next instruction assert_code code , :call, [0xff,0xff,0xff,0xeb] #ea ff ff fe end - def test_bic - code = @machine.bic :r2 , left: :r2 , right: :r3 - assert_code code , :bic , [0x03,0x20,0xc2,0xe1] #e3 c2 20 44 - end def test_push code = @machine.push [:lr] , {} assert_code code , :push , [0x00,0x40,0x2d,0xe9] #e9 2d 40 00 @@ -26,18 +22,6 @@ class TestArmAsm < MiniTest::Test code = @machine.pop [:pc] , {} assert_code code , :pop , [0x00,0x80,0xbd,0xe8] #e8 bd 80 00 end - def test_rsb - code = @machine.rsb :r1 , left: :r2 , right: :r3 - assert_code code , :rsb , [0x03,0x10,0x62,0xe0]#e0 62 10 03 - end - def test_rsc - code = @machine.rsc :r2 , left: :r3 , right: :r4 - assert_code code , :rsc , [0x04,0x20,0xe3,0xe0]#e0 e3 20 04 - end - def test_sbc - code = @machine.sbc :r3, left: :r4 , right: :r5 - assert_code code , :sbc , [0x05,0x30,0xc4,0xe0]#e0 c4 30 05 - end def test_swi code = @machine.swi 0x05 assert_code code , :swi , [0x05,0x00,0x00,0xef]#ef 00 00 05 diff --git a/test/arm/test_logic.rb b/test/arm/test_logic.rb index b15c37b4..c2a8d9ad 100644 --- a/test/arm/test_logic.rb +++ b/test/arm/test_logic.rb @@ -4,35 +4,51 @@ class TestLogic < MiniTest::Test include ArmHelper def test_adc - code = @machine.adc :r1, left: :r3, right: :r5 + code = @machine.adc :r1, :r3, :r5 assert_code code , :adc , [0x05,0x10,0xa3,0xe0] #e0 a3 10 05 end def test_add - code = @machine.add :r1 , left: :r1, right: :r3 + code = @machine.add :r1 , :r1, :r3 assert_code code , :add , [0x03,0x10,0x81,0xe0] #e0 81 10 03 end def test_add_lst - code = @machine.add( :r1 , left: :r2 , right: :r3 , shift_lsr: 8) + code = @machine.add( :r1 , :r2 , :r3 , shift_lsr: 8) assert_code code , :add , [0x23,0x14,0x82,0xe0] #e0 82 14 23 end def test_and # inst eval doesn't really work with and - code = @machine.and( :r1 , left: :r2 , right: :r3) + code = @machine.and( :r1 , :r2 , :r3) assert_code code , :and , [0x03,0x10,0x02,0xe0] #e0 01 10 03 end + def test_bic + code = @machine.bic :r2 , :r2 , :r3 + assert_code code , :bic , [0x03,0x20,0xc2,0xe1] #e3 c2 20 44 + end def test_eor - code = @machine.eor :r2 , left: :r2 , right: :r3 + code = @machine.eor :r2 , :r2 , :r3 assert_code code , :eor , [0x03,0x20,0x22,0xe0] #e0 22 20 03 end + def test_rsb + code = @machine.rsb :r1 , :r2 , :r3 + assert_code code , :rsb , [0x03,0x10,0x62,0xe0]#e0 62 10 03 + end + def test_rsc + code = @machine.rsc :r2 , :r3 , :r4 + assert_code code , :rsc , [0x04,0x20,0xe3,0xe0]#e0 e3 20 04 + end + def test_sbc + code = @machine.sbc :r3, :r4 , :r5 + assert_code code , :sbc , [0x05,0x30,0xc4,0xe0]#e0 c4 30 05 + end def test_sub - code = @machine.sub :r2, left: :r0, right: 1 + code = @machine.sub :r2, :r0, 1 assert_code code, :sub , [0x01,0x20,0x40,0xe2] #e2 40 20 01 end def test_subs - code = @machine.sub :r2, left: :r2, right: 1 , update_status: 1 + code = @machine.sub :r2, :r2, 1 , update_status: 1 assert_code code, :sub , [0x01,0x20,0x52,0xe2] #e2 52 20 01 end def test_orr - code = @machine.orr :r2 , left: :r2 , right: :r3 + code = @machine.orr :r2 , :r2 , :r3 assert_code code , :orr , [0x03,0x20,0x82,0xe1] #e1 82 20 03 end end diff --git a/test/test_small_program.rb b/test/test_small_program.rb index c78a921d..80b592ec 100644 --- a/test/test_small_program.rb +++ b/test/test_small_program.rb @@ -18,7 +18,7 @@ class TestSmallProg < MiniTest::Test start = Vm::Block.new("start") add_code start start.instance_eval do - sub :r0, left: :r0, right: 1 , :update_status => 1 #2 + sub :r0, :r0, 1 , :update_status => 1 #2 bne start ,{} #3 end end @@ -31,7 +31,7 @@ class TestSmallProg < MiniTest::Test @program.main.instance_eval do mov :r7, right: 4 # 4 == write mov :r0 , right: 1 # stdout - add :r1 , left: hello # address of "hello Raisa" + add :r1 , hello , nil # address of "hello Raisa" mov :r2 , right: hello.length swi 0 , {} #software interupt, ie kernel syscall end