started naming instruction arguments properly, starting with compare
This commit is contained in:
parent
f65ad813af
commit
6abd10f278
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -2,3 +2,4 @@ require_relative "test_arm"
|
||||
require_relative "test_logic"
|
||||
require_relative "test_move"
|
||||
require_relative "test_memory"
|
||||
require_relative "test_compare"
|
||||
|
@ -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
22
test/arm/test_compare.rb
Normal 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
|
Loading…
Reference in New Issue
Block a user