bunch of method extraction on instructions
This commit is contained in:
parent
55c108a8d7
commit
ec2b0a563e
@ -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}"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user