diff --git a/lib/arm/arm_machine.rb b/lib/arm/arm_machine.rb index ce5f4172..565f2a23 100644 --- a/lib/arm/arm_machine.rb +++ b/lib/arm/arm_machine.rb @@ -16,15 +16,15 @@ module Arm def define_instruction inst , clazz super return - # need to use create_method and move to options hash + # need to use create_method and move to attributes hash define_method("#{inst}s") do |*args| instruction clazz , inst , :al , 1 , *args end ArmMachine::COND_CODES.keys.each do |suffix| - define_method("#{inst}#{suffix}") do |options| + define_method("#{inst}#{suffix}") do |attributes| instruction clazz , inst , suffix , 0 , *args end - define_method("#{inst}s#{suffix}") do |options| + define_method("#{inst}s#{suffix}") do |attributes| instruction clazz , inst , suffix , 1 , *args end end diff --git a/lib/arm/call_instruction.rb b/lib/arm/call_instruction.rb index e2fdab47..003eb084 100644 --- a/lib/arm/call_instruction.rb +++ b/lib/arm/call_instruction.rb @@ -22,12 +22,12 @@ module Arm 4 end - def initialize(options) - super(options) + def initialize(attributes) + super(attributes) @update_status_flag = 0 @condition_code = :al - @opcode = options[:opcode] - @args = [options[:left] , options[:right] , options[:extra]] + @opcode = attributes[:opcode] + @args = [attributes[:left] , attributes[:right] , attributes[:extra]] @operand = 0 end diff --git a/lib/arm/logic_instruction.rb b/lib/arm/logic_instruction.rb index fe75da44..ea929445 100644 --- a/lib/arm/logic_instruction.rb +++ b/lib/arm/logic_instruction.rb @@ -82,12 +82,12 @@ module Arm include Arm::Constants include LogicHelper - def initialize(options) - super(options) + def initialize(attributes) + super(attributes) @update_status_flag = 0 @condition_code = :al - @opcode = options[:opcode] - @args = [options[:left] , options[:right] , options[:extra]] + @opcode = attributes[:opcode] + @args = [attributes[:left] , attributes[:right] , attributes[:extra]] @operand = 0 @rn = nil @@ -103,11 +103,14 @@ module Arm end class CompareInstruction < Vm::CompareInstruction - def initialize(options) - super(options) + include Arm::Constants + include LogicHelper + + def initialize(attributes) + super(attributes) @condition_code = :al - @opcode = options[:opcode] - @args = [options[:left] , options[:right] , options[:extra]] + @opcode = attributes[:opcode] + @args = [attributes[:left] , attributes[:right] , attributes[:extra]] @operand = 0 @i = 0 @update_status_flag = 1 @@ -115,19 +118,19 @@ module Arm @rd = :r0 end def build - do_build args[1] + do_build @args[1] end end class MoveInstruction < Vm::MoveInstruction include Arm::Constants include LogicHelper - def initialize(options) - super(options) + def initialize(attributes) + super(attributes) @update_status_flag = 0 @condition_code = :al - @opcode = options[:opcode] - @args = [options[:left] , options[:right] , options[:extra]] + @opcode = attributes[:opcode] + @args = [attributes[:left] , attributes[:right] , attributes[:extra]] @operand = 0 @i = 0 diff --git a/lib/arm/memory_instruction.rb b/lib/arm/memory_instruction.rb index f12ea24d..0ddae894 100644 --- a/lib/arm/memory_instruction.rb +++ b/lib/arm/memory_instruction.rb @@ -7,12 +7,12 @@ module Arm class MemoryInstruction < Vm::MemoryInstruction include Arm::Constants - def initialize(options) - super(options) + def initialize(attributes) + super(attributes) @update_status_flag = 0 @condition_code = :al - @opcode = options[:opcode] - @args = [options[:left] , options[:right] ] + @opcode = attributes[:opcode] + @args = [attributes[:left] , attributes[:right] ] @operand = 0 @i = 0 #I flag (third bit) @@ -44,8 +44,8 @@ module Arm #str / ldr are _serious instructions. With BIG possibilities not half are implemented if (arg.is_a?(Symbol)) #symbol is register @rn = arg - if options[:offset] - @operand = options[:offset] + if @attributes[:offset] + @operand = @attributes[:offset] if (@operand < 0) @add_offset = 0 #TODO test/check/understand diff --git a/lib/arm/stack_instruction.rb b/lib/arm/stack_instruction.rb index e2730c01..5fb01981 100644 --- a/lib/arm/stack_instruction.rb +++ b/lib/arm/stack_instruction.rb @@ -10,12 +10,12 @@ module Arm 4 end - def initialize(options) - super(options) + def initialize(attributes) + super(attributes) @update_status_flag = 0 @condition_code = :al - @opcode = options[:opcode] - @args = [options[:left] , options[:right] , options[:extra]] + @opcode = attributes[:opcode] + @args = [attributes[:left] , attributes[:right] , attributes[:extra]] @operand = 0 @update_status_flag= 0 diff --git a/test/test_asm.rb b/test/test_arm.rb similarity index 67% rename from test/test_asm.rb rename to test/test_arm.rb index 75d6e2f4..283ae3d3 100644 --- a/test/test_asm.rb +++ b/test/test_arm.rb @@ -8,18 +8,17 @@ require_relative 'helper' class TestArmAsm < MiniTest::Test # need Assembler and a block (see those classes) def setup - @program = Asm::Assembler.new - #no ruby block given, ie need to add this block later by hand - @block = @program.block + @machine = Arm::ArmMachine.new end # code is what the generator spits out, at least one instruction worth (.first) # the op code is wat was witten as assembler in the first place and the binary result # is reversed and in 4 bytes as ruby can only do 31 bits and so we can't test with just one int (?) def assert_code code , op , should - @program.add_block @block #assume not added before assert_equal op , code.opcode - binary = @program.assemble_to_string + io = StringIO.new + code.assemble(io) + binary = io.string assert_equal 4 , binary.length index = 0 binary.each_byte do |byte | @@ -28,111 +27,110 @@ class TestArmAsm < MiniTest::Test end end def test_adc - code = @block.instance_eval { adc r1, r3, r5}.first + code = @machine.adc :left => :r1, :right => :r3, :extra => :r5 assert_code code , :adc , [0x05,0x10,0xa3,0xe0] #e0 a3 10 05 end def test_add - code = @block.instance_eval { add r1 , r1, r3}.first + code = @machine.add :left => :r1 , :right => :r1, :extra => :r3 assert_code code , :add , [0x03,0x10,0x81,0xe0] #e0 81 10 03 end def test_and # inst eval doesn't really work with and - code = @block.and( @block.r1 , @block.r2 , @block.r3).first + code = @machine.and( :left => :r1 , :right => :r2 , :extra => :r3) assert_code code , :and , [0x03,0x10,0x02,0xe0] #e0 01 10 03 end def test_b # the address is what an assembler calculates (a signed number for the amount of instructions), # ie the relative (to pc) address -8 (pipeline) /4 so save space # so the cpu adds the value*4 and starts loading that (load, decode, execute) - code = @block.instance_eval { b -1 }.first #this jumps to the next instruction + code = @machine.b :left => -4 #this jumps to the next instruction assert_code code , :b , [0xff,0xff,0xff,0xea] #ea ff ff fe end def test_bl #see comment above. bx not implemented (as it means into thumb, and no thumb here) - code = @block.instance_eval { bl -1 }.first #this jumps to the next instruction + code = @machine.bl :left => -4 #this jumps to the next instruction assert_code code , :bl , [0xff,0xff,0xff,0xeb] #ea ff ff fe end def test_bic - code = @block.instance_eval { bic r2 , r2 , r3 }.first + code = @machine.bic :left => :r2 , :right => :r2 , :extra => :r3 assert_code code , :bic , [0x03,0x20,0xc2,0xe1] #e3 c2 20 44 end def test_cmn - code = @block.instance_eval { cmn r1 , r2 }.first + code = @machine.cmn :left => :r1 , :right => :r2 assert_code code , :cmn , [0x02,0x00,0x71,0xe1] #e1 71 00 02 end def test_cmp - code = @block.instance_eval { cmp r1 , r2 }.first + code = @machine.cmp :left => :r1 , :right => :r2 assert_code code , :cmp , [0x02,0x00,0x51,0xe1] #e1 51 00 02 end def test_eor - code = @block.instance_eval { eor r2 , r2 , r3 }.first + code = @machine.eor :left => :r2 , :right => :r2 , :extra => :r3 assert_code code , :eor , [0x03,0x20,0x22,0xe0] #e0 22 20 03 end def test_ldr - code = @block.instance_eval { ldr r0, r0 }.first + code = @machine.ldr :left => :r0, :right => :r0 assert_code code, :ldr , [0x00,0x00,0x90,0xe5] #e5 90 00 00 end def test_ldr2 - code = @block.instance_eval { ldr r0, r0 + 4 }.first + code = @machine.ldr :left => :r0, :right => :r0 , :offset => 4 assert_code code, :ldr , [0x04,0x00,0x90,0xe5] #e5 90 00 04 end def test_ldrb - code = @block.instance_eval { ldrb r0, r0 }.first + code = @machine.ldrb :left => :r0, :right => :r0 assert_code code, :ldrb , [0x00,0x00,0xd0,0xe5] #e5 d0 00 00 end def test_orr - code = @block.instance_eval { orr r2 , r2 , r3 }.first + code = @machine.orr :left => :r2 , :right => :r2 , :extra => :r3 assert_code code , :orr , [0x03,0x20,0x82,0xe1] #e1 82 20 03 end def test_push - code = @block.instance_eval { push lr }.first + code = @machine.push :left => :lr assert_code code , :push , [0x00,0x40,0x2d,0xe9] #e9 2d 40 00 end def test_pop - code = @block.instance_eval { pop pc }.first + code = @machine.pop :left => :pc assert_code code , :pop , [0x00,0x80,0xbd,0xe8] #e8 bd 80 00 end - def test_rsb - code = @block.instance_eval { rsb r1 , r2 , r3 }.first + code = @machine.rsb :left => :r1 , :right => :r2 , :extra => :r3 assert_code code , :rsb , [0x03,0x10,0x62,0xe0]#e0 62 10 03 end def test_rsc - code = @block.instance_eval { rsc r2 , r3 , r4 }.first + code = @machine.rsc :left => :r2 , :right => :r3 , :extra => :r4 assert_code code , :rsc , [0x04,0x20,0xe3,0xe0]#e0 e3 20 04 end def test_sbc - code = @block.instance_eval { sbc r3, r4 , r5 }.first + code = @machine.sbc :left => :r3, :right => :r4 , :extra => :r5 assert_code code , :sbc , [0x05,0x30,0xc4,0xe0]#e0 c4 30 05 end def test_str - code = @block.instance_eval { str r0, r0 }.first + code = @machine.str :left => :r0, :right => :r0 assert_code code, :str , [0x00,0x00,0x80,0xe5] #e5 81 00 00 end def test_strb - code = @block.instance_eval { strb r0, r0 }.first + code = @machine.strb :left => :r0, :right => :r0 assert_code code, :strb , [0x00,0x00,0xc0,0xe5] #e5 c0 00 00 end def test_sub - code = @block.instance_eval { sub r2, r0, 1 }.first + code = @machine.sub :left => :r2, :right => :r0, :extra => 1 assert_code code, :sub , [0x01,0x20,0x40,0xe2] #e2 40 20 01 end def test_swi - code = @block.instance_eval { swi 0x05 }.first + code = @machine.swi :left => 0x05 assert_code code , :swi , [0x05,0x00,0x00,0xef]#ef 00 00 05 end def test_teq - code = @block.instance_eval{ teq r1 , r2}.first + code = @machine.teq :left => :r1 , :right => :r2 assert_code code , :teq , [0x02,0x00,0x31,0xe1] #e1 31 00 02 end def test_tst - code = @block.instance_eval{ tst r1 , r2}.first + code = @machine.tst :left => :r1 , :right => :r2 assert_code code , :tst , [0x02,0x00,0x11,0xe1] #e1 11 00 02 end def test_mov - code = @block.instance_eval { mov r0, 5 }.first + code = @machine.mov :left => :r0, :right => 5 assert_code code , :mov , [0x05,0x00,0xa0,0xe3] #e3 a0 10 05 end def test_mvn - code = @block.instance_eval { mvn r1, 5 }.first + code = @machine.mvn :left => :r1, :right => 5 assert_code code , :mvn , [0x05,0x10,0xe0,0xe3] #e3 e0 10 05 end end