bunch of method extraction on instructions

This commit is contained in:
Torsten Ruger 2016-12-14 21:53:26 +02:00
parent 55c108a8d7
commit ec2b0a563e
5 changed files with 63 additions and 59 deletions

View File

@ -48,25 +48,28 @@ module Arm
operand = arg
immediate = 0
elsif (arg.is_a?(Arm::Shift))
# handle_shift
handle_shift
else
raise "invalid operand argument #{arg.inspect} , #{inspect}"
end
instuction_class = 0b00 # OPC_DATA_PROCESSING
val = (operand.is_a?(Symbol) or operand.is_a?(::Register::RegisterValue)) ? reg_code(operand) : operand
val = 0 if val == nil
val = shift(val , 0)
raise inspect unless reg_code(@rd)
val |= shift(reg_code(@rd) , 12)
val |= shift(reg_code(rn) , 12 + 4)
val |= shift(@attributes[:update_status] , 12 + 4 + 4)#20
val |= shift(op_bit_code , 12 + 4 + 4 + 1)
val |= shift(reg_code(@rd) , 12)
val |= shift(reg_code(rn) , 12 + 4)
val |= shift(@attributes[:update_status], 12 + 4 + 4)#20
val |= shift(op_bit_code , 12 + 4 + 4 + 1)
val |= shift(immediate , 12 + 4 + 4 + 1 + 4)
val |= shift(instuction_class , 12 + 4 + 4 + 1 + 4 + 1)
val |= shift(cond_bit_code , 12 + 4 + 4 + 1 + 4 + 1 + 2)
val |= shift(instuction_class , 12 + 4 + 4 + 1 + 4 + 1)
val |= shift(cond_bit_code , 12 + 4 + 4 + 1 + 4 + 1 + 2)
io.write_uint32 val
end
def instuction_class
0b00 # OPC_DATA_PROCESSING
end
# Arms special shift abilities are not modelled in the register level
# So they would have to be used inoptimisations, that are not implemented
# in short unused code
@ -93,6 +96,7 @@ module Arm
# shift_imm = 0
# end
# operand = rm_ref | (shift_op << 4) | (shift_imm << 4 +3)
raise "No implemented"
end
def to_s
"#{opcode} #{@left} , #{@right} #{super}"

View File

@ -32,14 +32,11 @@ module Arm
else
raise "invalid operand argument #{right.inspect} , #{inspect}"
end
result = reg_code(@result)
left_code = reg_code(left)
op = shift_handling
instuction_class = 0b00 # OPC_DATA_PROCESSING
if( opcode == :mul )
operand = reg_code(left) + 0x90
op = reg_code(right) << 8
result = 0
left_code = reg_code(@result)
end
val = shift(operand , 0)
@ -55,6 +52,14 @@ module Arm
assemble_extra
end
def result
opcode == :mul ? 0 : reg_code(@result)
end
def instuction_class
0b00 # OPC_DATA_PROCESSING
end
# Arm can't load any large (over 1024) numbers, or larger with fancy shifting,
# but then the lower bits must be 0's. Especially in constant loading random large numbers
# happen, and so they are split into two instructions. An exection is thrown, that triggers

View File

@ -23,10 +23,7 @@ module Arm
def assemble(io)
# don't overwrite instance variables, to make assembly repeatable
rn = @rn
operand = @operand
add_offset = @add_offset
arg = @left
rn , operand , add_offset , arg = @rn , @operand , @add_offset , @left
arg = arg.symbol if( arg.is_a? ::Register::RegisterValue )
#str / ldr are _serious instructions. With BIG possibilities not half are implemented
is_reg = arg.is_a?(::Register::RegisterValue)
@ -58,11 +55,6 @@ module Arm
#not sure about these 2 constants. They produce the correct output for str r0 , r1
# but i can't help thinking that that is because they are not used in that instruction and
# so it doesn't matter. Will see
add_offset = 1
# TODO to be continued
add_offset = 0 if @attributes[:add_offset]
w = 0 #W flag
byte_access = opcode.to_s[-1] == "b" ? 1 : 0 #B (byte) flag
instuction_class = 0b01 # OPC_MEMORY_ACCESS
if (operand.is_a?(Symbol) or operand.is_a?(::Register::RegisterValue))
val = reg_code(operand)
@ -82,7 +74,7 @@ module Arm
val |= shift(reg_code(@result) , 12 )
val |= shift(reg_code(rn) , 12 + 4) #16
val |= shift(@is_load , 12 + 4 + 4)
val |= shift(w , 12 + 4 + 4 + 1)
val |= shift(0 , 12 + 4 + 4 + 1)
val |= shift(byte_access , 12 + 4 + 4 + 1 + 1)
val |= shift(add_offset , 12 + 4 + 4 + 1 + 1 + 1)
val |= shift(@pre_post_index, 12 + 4 + 4 + 1 + 1 + 1 + 1)#24
@ -92,5 +84,12 @@ module Arm
io.write_uint32 val
end
def add_offset
@attributes[:add_offset] ? 0 : 1
end
def byte_access
opcode.to_s[-1] == "b" ? 1 : 0 #B (byte) flag
end
end
end

View File

@ -35,10 +35,8 @@ module Arm
# don't overwrite instance variables, to make assembly repeatable
def assemble(io)
rn = @rn
operand = @operand
right = @from
immediate = 1
rn , operand , right , immediate = @rn , @operand , @from , 1
case right
when Numeric
operand = numeric_operand(right)
@ -49,7 +47,6 @@ module Arm
raise "invalid operand argument #{right.class} , #{self.class}"
end
op = shift_handling
instuction_class = 0b00 # OPC_DATA_PROCESSING
val = shift(operand , 0)
val |= shift(op , 0) # any barrel action, is already shifted
val |= shift(reg_code(@to) , 12)
@ -60,10 +57,13 @@ module Arm
val |= shift(instuction_class , 12 + 4 + 4 + 1 + 4 + 1)
val |= shift(cond_bit_code , 12 + 4 + 4 + 1 + 4 + 1 + 2)
io.write_uint32 val
# by now we have the extra add so assemble that
# by now we have the extra add so assemble that
@extra.assemble(io) if(@extra) #puts "Assemble extra at #{val.to_s(16)}"
end
def instuction_class
0b00 # OPC_DATA_PROCESSING
end
def numeric_operand(right)
return right if (right.fits_u8?)
if (op_with_rot = calculate_u8_with_rr(right))

View File

@ -12,45 +12,21 @@ module Arm
@attributes[:update_status] = 0 if @attributes[:update_status] == nil
@attributes[:condition_code] = :al if @attributes[:condition_code] == nil
@attributes[:opcode] = attributes[:opcode]
@operand = 0
# @attributes[:update_status]= 0
@rn = :r0 # register zero = zero bit pattern
# downward growing, decrement before memory access
# official ARM style stack as used by gas
@rn = :sp # sp register
end
# don't overwrite instance variables, to make assembly repeatable
def assemble(io)
# don't overwrite instance variables, to make assembly repeatable
operand = @operand
if (@first.is_a?(Array))
operand = 0
@first.each do |r|
raise "nil register in push, index #{r}- #{inspect}" if r.nil?
operand = operand | (1 << reg_code(r))
end
else
raise "invalid operand argument #{inspect}"
operand = 0
raise "invalid operand argument #{inspect}" unless (@first.is_a?(Array))
@first.each do |r|
raise "nil register in push, index #{r}- #{inspect}" if r.nil?
operand = operand | (1 << reg_code(r))
end
write_base = 1
if (opcode == :push)
pre_post_index = 1
up_down = 0
is_pop = 0
else #pop
pre_post_index = 0
up_down = 1
is_pop = 1
end
instuction_class = 0b10 # OPC_STACK
cond = @attributes[:condition_code].is_a?(Symbol) ? COND_CODES[@attributes[:condition_code]] : @attributes[:condition_code]
@rn = :sp # sp register
#assemble of old
val = operand
val = val | (reg_code(@rn) << 16)
val = val | (is_pop << 16 + 4) #20
val = val | (write_base << 16 + 4 + 1)
val = val | (1 << 16 + 4 + 1)
val = val | (@attributes[:update_status] << 16 + 4 + 1 + 1)
val = val | (up_down << 16 + 4 + 1 + 1 + 1)
val = val | (pre_post_index << 16 + 4 + 1 + 1 + 1 + 1)#24
@ -59,9 +35,29 @@ module Arm
io.write_uint32 val
end
def cond
if @attributes[:condition_code].is_a?(Symbol)
COND_CODES[@attributes[:condition_code]]
else
@attributes[:condition_code]
end
end
def instuction_class
0b10 # OPC_STACK
end
def up_down
(opcode == :push) ? 0 : 1
end
alias :is_pop :up_down
def pre_post_index
(opcode == :push) ? 1 : 0
end
def regs
@first
end
def to_s
"#{opcode} [#{@first.join(',') }] #{super}"
end