started naming instruction arguments properly, starting with compare

This commit is contained in:
Torsten Ruger 2014-05-18 11:11:26 +03:00
parent f65ad813af
commit 6abd10f278
6 changed files with 63 additions and 48 deletions

View File

@ -2,22 +2,22 @@ module Arm
class CompareInstruction < Vm::CompareInstruction
include Arm::Constants
def initialize(first , attributes)
super(first , attributes)
def initialize(left , right , attributes)
super(left , right, attributes)
@attributes[:condition_code] = :al if @attributes[:condition_code] == nil
@operand = 0
@i = 0
@attributes[:update_status] = 1
@rn = first
@rn = left
@rd = :r0
end
# arm intrucioons are pretty sensible, and always 4 bytes (thumb not supported)
# arm instructions are pretty sensible, and always 4 bytes (thumb not supported)
def length
4
end
def build
arg = @attributes[:right]
arg = @right
if arg.is_a?(Vm::StringConstant)
# do pc relative addressing with the difference to the instuction

View File

@ -45,28 +45,28 @@ module Vm
# Derived machines may use own instructions and define functions for them if so desired
def initialize
[:push, :pop].each do |inst|
define_instruction_for(inst , StackInstruction)
define_instruction_one(inst , StackInstruction)
end
[:adc, :add, :and, :bic, :eor, :orr, :rsb, :rsc, :sbc, :sub].each do |inst|
define_instruction_for(inst , LogicInstruction)
define_instruction_one(inst , LogicInstruction)
end
[:mov, :mvn].each do |inst|
define_instruction_for(inst , MoveInstruction)
define_instruction_one(inst , MoveInstruction)
end
[:cmn, :cmp, :teq, :tst].each do |inst|
define_instruction_for(inst , CompareInstruction)
define_instruction_two(inst , CompareInstruction)
end
[:strb, :str , :ldrb, :ldr].each do |inst|
define_instruction_for(inst , MemoryInstruction)
define_instruction_one(inst , MemoryInstruction)
end
[:b, :call , :swi].each do |inst|
define_instruction_for(inst , CallInstruction)
define_instruction_one(inst , CallInstruction)
end
# create all possible brach instructions, but the CallInstruction demangles the
# code, and has opcode set to :b and :condition_code set to the condition
CONDITIONS.each do |suffix|
define_instruction_for("b#{suffix}".to_sym , CallInstruction)
define_instruction_for("call#{suffix}".to_sym , CallInstruction)
define_instruction_one("b#{suffix}".to_sym , CallInstruction)
define_instruction_one("call#{suffix}".to_sym , CallInstruction)
end
end
@ -74,20 +74,6 @@ module Vm
self.class.send(:define_method, name , &block)
end
# define the instruction inst (given as a symbol) on this class as a methods
# As we define a standard set of instructions (or memnonics) , this turns this class into a kind of
# Assembler, in that you can write .mov() or .pop() and those functions mean the same as if they
# were in an assembler file (also options are the same)
# defaults gets merged into the instructions options hash, ie passed on to the (machine specific)
# Instruction constructor and as such can be used to influence that classes behaviour
def define_instruction(inst , clazz , defaults = {} )
create_method(inst) do |first , options|
options = {} if options == nil
options.merge defaults
options[:opcode] = inst
clazz.new(first , options)
end
end
def self.instance
@@instance
@ -105,7 +91,28 @@ module Vm
# be used to define the mov on an arm machine.
# This methods picks up that derived class and calls a define_instruction methods that can
# be overriden in subclasses
def define_instruction_for(inst , clazz )
def define_instruction_one(inst , clazz , defaults = {} )
clazz = class_for(clazz)
create_method(inst) do |first , options = nil|
options = {} if options == nil
options.merge defaults
options[:opcode] = inst
clazz.new(first , options)
end
end
# 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|
options = {} if options == nil
options.merge defaults
options[:opcode] = inst
clazz.new(first , second ,options)
end
end
def class_for clazz
c_name = clazz.name
my_module = self.class.name.split("::").first
clazz_name = clazz.name.split("::").last
@ -113,7 +120,7 @@ module Vm
module_class = eval("#{my_module}::#{clazz_name}") rescue nil
clazz = module_class if module_class
end
define_instruction(inst , clazz )
clazz
end
end
end

View File

@ -55,8 +55,9 @@ module Vm
end
end
class CompareInstruction < Instruction
def initialize first , options
@first = first
def initialize left , right , options
@left = left
@right = right
super(options)
end
end

View File

@ -2,3 +2,4 @@ require_relative "test_arm"
require_relative "test_logic"
require_relative "test_move"
require_relative "test_memory"
require_relative "test_compare"

View File

@ -18,14 +18,6 @@ class TestArmAsm < MiniTest::Test
code = @machine.bic :r2 , left: :r2 , right: :r3
assert_code code , :bic , [0x03,0x20,0xc2,0xe1] #e3 c2 20 44
end
def test_cmn
code = @machine.cmn :r1 , right: :r2
assert_code code , :cmn , [0x02,0x00,0x71,0xe1] #e1 71 00 02
end
def test_cmp
code = @machine.cmp :r1 , right: :r2
assert_code code , :cmp , [0x02,0x00,0x51,0xe1] #e1 51 00 02
end
def test_push
code = @machine.push [:lr] , {}
assert_code code , :push , [0x00,0x40,0x2d,0xe9] #e9 2d 40 00
@ -47,15 +39,7 @@ class TestArmAsm < MiniTest::Test
assert_code code , :sbc , [0x05,0x30,0xc4,0xe0]#e0 c4 30 05
end
def test_swi
code = @machine.swi 0x05 , {}
code = @machine.swi 0x05
assert_code code , :swi , [0x05,0x00,0x00,0xef]#ef 00 00 05
end
def test_teq
code = @machine.teq :r1 , right: :r2
assert_code code , :teq , [0x02,0x00,0x31,0xe1] #e1 31 00 02
end
def test_tst
code = @machine.tst :r1 , right: :r2
assert_code code , :tst , [0x02,0x00,0x11,0xe1] #e1 11 00 02
end
end

22
test/arm/test_compare.rb Normal file
View File

@ -0,0 +1,22 @@
require_relative 'helper'
class TestArmAsm < MiniTest::Test
include ArmHelper
def test_cmn
code = @machine.cmn :r1 , :r2
assert_code code , :cmn , [0x02,0x00,0x71,0xe1] #e1 71 00 02
end
def test_cmp
code = @machine.cmp :r1 , :r2
assert_code code , :cmp , [0x02,0x00,0x51,0xe1] #e1 51 00 02
end
def test_teq
code = @machine.teq :r1 , :r2
assert_code code , :teq , [0x02,0x00,0x31,0xe1] #e1 31 00 02
end
def test_tst
code = @machine.tst :r1 , :r2
assert_code code , :tst , [0x02,0x00,0x11,0xe1] #e1 11 00 02
end
end