bunch of method extraction on instructions
This commit is contained in:
parent
55c108a8d7
commit
ec2b0a563e
@ -48,25 +48,28 @@ module Arm
|
|||||||
operand = arg
|
operand = arg
|
||||||
immediate = 0
|
immediate = 0
|
||||||
elsif (arg.is_a?(Arm::Shift))
|
elsif (arg.is_a?(Arm::Shift))
|
||||||
# handle_shift
|
handle_shift
|
||||||
else
|
else
|
||||||
raise "invalid operand argument #{arg.inspect} , #{inspect}"
|
raise "invalid operand argument #{arg.inspect} , #{inspect}"
|
||||||
end
|
end
|
||||||
instuction_class = 0b00 # OPC_DATA_PROCESSING
|
|
||||||
val = (operand.is_a?(Symbol) or operand.is_a?(::Register::RegisterValue)) ? reg_code(operand) : operand
|
val = (operand.is_a?(Symbol) or operand.is_a?(::Register::RegisterValue)) ? reg_code(operand) : operand
|
||||||
val = 0 if val == nil
|
val = 0 if val == nil
|
||||||
val = shift(val , 0)
|
val = shift(val , 0)
|
||||||
raise inspect unless reg_code(@rd)
|
raise inspect unless reg_code(@rd)
|
||||||
val |= shift(reg_code(@rd) , 12)
|
val |= shift(reg_code(@rd) , 12)
|
||||||
val |= shift(reg_code(rn) , 12 + 4)
|
val |= shift(reg_code(rn) , 12 + 4)
|
||||||
val |= shift(@attributes[:update_status] , 12 + 4 + 4)#20
|
val |= shift(@attributes[:update_status], 12 + 4 + 4)#20
|
||||||
val |= shift(op_bit_code , 12 + 4 + 4 + 1)
|
val |= shift(op_bit_code , 12 + 4 + 4 + 1)
|
||||||
val |= shift(immediate , 12 + 4 + 4 + 1 + 4)
|
val |= shift(immediate , 12 + 4 + 4 + 1 + 4)
|
||||||
val |= shift(instuction_class , 12 + 4 + 4 + 1 + 4 + 1)
|
val |= shift(instuction_class , 12 + 4 + 4 + 1 + 4 + 1)
|
||||||
val |= shift(cond_bit_code , 12 + 4 + 4 + 1 + 4 + 1 + 2)
|
val |= shift(cond_bit_code , 12 + 4 + 4 + 1 + 4 + 1 + 2)
|
||||||
io.write_uint32 val
|
io.write_uint32 val
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def instuction_class
|
||||||
|
0b00 # OPC_DATA_PROCESSING
|
||||||
|
end
|
||||||
|
|
||||||
# Arms special shift abilities are not modelled in the register level
|
# Arms special shift abilities are not modelled in the register level
|
||||||
# So they would have to be used inoptimisations, that are not implemented
|
# So they would have to be used inoptimisations, that are not implemented
|
||||||
# in short unused code
|
# in short unused code
|
||||||
@ -93,6 +96,7 @@ module Arm
|
|||||||
# shift_imm = 0
|
# shift_imm = 0
|
||||||
# end
|
# end
|
||||||
# operand = rm_ref | (shift_op << 4) | (shift_imm << 4 +3)
|
# operand = rm_ref | (shift_op << 4) | (shift_imm << 4 +3)
|
||||||
|
raise "No implemented"
|
||||||
end
|
end
|
||||||
def to_s
|
def to_s
|
||||||
"#{opcode} #{@left} , #{@right} #{super}"
|
"#{opcode} #{@left} , #{@right} #{super}"
|
||||||
|
@ -32,14 +32,11 @@ module Arm
|
|||||||
else
|
else
|
||||||
raise "invalid operand argument #{right.inspect} , #{inspect}"
|
raise "invalid operand argument #{right.inspect} , #{inspect}"
|
||||||
end
|
end
|
||||||
result = reg_code(@result)
|
|
||||||
left_code = reg_code(left)
|
left_code = reg_code(left)
|
||||||
op = shift_handling
|
op = shift_handling
|
||||||
instuction_class = 0b00 # OPC_DATA_PROCESSING
|
|
||||||
if( opcode == :mul )
|
if( opcode == :mul )
|
||||||
operand = reg_code(left) + 0x90
|
operand = reg_code(left) + 0x90
|
||||||
op = reg_code(right) << 8
|
op = reg_code(right) << 8
|
||||||
result = 0
|
|
||||||
left_code = reg_code(@result)
|
left_code = reg_code(@result)
|
||||||
end
|
end
|
||||||
val = shift(operand , 0)
|
val = shift(operand , 0)
|
||||||
@ -55,6 +52,14 @@ module Arm
|
|||||||
assemble_extra
|
assemble_extra
|
||||||
end
|
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,
|
# 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
|
# 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
|
# happen, and so they are split into two instructions. An exection is thrown, that triggers
|
||||||
|
@ -23,10 +23,7 @@ module Arm
|
|||||||
|
|
||||||
def assemble(io)
|
def assemble(io)
|
||||||
# don't overwrite instance variables, to make assembly repeatable
|
# don't overwrite instance variables, to make assembly repeatable
|
||||||
rn = @rn
|
rn , operand , add_offset , arg = @rn , @operand , @add_offset , @left
|
||||||
operand = @operand
|
|
||||||
add_offset = @add_offset
|
|
||||||
arg = @left
|
|
||||||
arg = arg.symbol if( arg.is_a? ::Register::RegisterValue )
|
arg = arg.symbol if( arg.is_a? ::Register::RegisterValue )
|
||||||
#str / ldr are _serious instructions. With BIG possibilities not half are implemented
|
#str / ldr are _serious instructions. With BIG possibilities not half are implemented
|
||||||
is_reg = arg.is_a?(::Register::RegisterValue)
|
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
|
#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
|
# 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
|
# 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
|
instuction_class = 0b01 # OPC_MEMORY_ACCESS
|
||||||
if (operand.is_a?(Symbol) or operand.is_a?(::Register::RegisterValue))
|
if (operand.is_a?(Symbol) or operand.is_a?(::Register::RegisterValue))
|
||||||
val = reg_code(operand)
|
val = reg_code(operand)
|
||||||
@ -82,7 +74,7 @@ module Arm
|
|||||||
val |= shift(reg_code(@result) , 12 )
|
val |= shift(reg_code(@result) , 12 )
|
||||||
val |= shift(reg_code(rn) , 12 + 4) #16
|
val |= shift(reg_code(rn) , 12 + 4) #16
|
||||||
val |= shift(@is_load , 12 + 4 + 4)
|
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(byte_access , 12 + 4 + 4 + 1 + 1)
|
||||||
val |= shift(add_offset , 12 + 4 + 4 + 1 + 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
|
val |= shift(@pre_post_index, 12 + 4 + 4 + 1 + 1 + 1 + 1)#24
|
||||||
@ -92,5 +84,12 @@ module Arm
|
|||||||
io.write_uint32 val
|
io.write_uint32 val
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
@ -35,10 +35,8 @@ module Arm
|
|||||||
|
|
||||||
# don't overwrite instance variables, to make assembly repeatable
|
# don't overwrite instance variables, to make assembly repeatable
|
||||||
def assemble(io)
|
def assemble(io)
|
||||||
rn = @rn
|
rn , operand , right , immediate = @rn , @operand , @from , 1
|
||||||
operand = @operand
|
|
||||||
right = @from
|
|
||||||
immediate = 1
|
|
||||||
case right
|
case right
|
||||||
when Numeric
|
when Numeric
|
||||||
operand = numeric_operand(right)
|
operand = numeric_operand(right)
|
||||||
@ -49,7 +47,6 @@ module Arm
|
|||||||
raise "invalid operand argument #{right.class} , #{self.class}"
|
raise "invalid operand argument #{right.class} , #{self.class}"
|
||||||
end
|
end
|
||||||
op = shift_handling
|
op = shift_handling
|
||||||
instuction_class = 0b00 # OPC_DATA_PROCESSING
|
|
||||||
val = shift(operand , 0)
|
val = shift(operand , 0)
|
||||||
val |= shift(op , 0) # any barrel action, is already shifted
|
val |= shift(op , 0) # any barrel action, is already shifted
|
||||||
val |= shift(reg_code(@to) , 12)
|
val |= shift(reg_code(@to) , 12)
|
||||||
@ -60,10 +57,13 @@ module Arm
|
|||||||
val |= shift(instuction_class , 12 + 4 + 4 + 1 + 4 + 1)
|
val |= shift(instuction_class , 12 + 4 + 4 + 1 + 4 + 1)
|
||||||
val |= shift(cond_bit_code , 12 + 4 + 4 + 1 + 4 + 1 + 2)
|
val |= shift(cond_bit_code , 12 + 4 + 4 + 1 + 4 + 1 + 2)
|
||||||
io.write_uint32 val
|
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)}"
|
@extra.assemble(io) if(@extra) #puts "Assemble extra at #{val.to_s(16)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def instuction_class
|
||||||
|
0b00 # OPC_DATA_PROCESSING
|
||||||
|
end
|
||||||
def numeric_operand(right)
|
def numeric_operand(right)
|
||||||
return right if (right.fits_u8?)
|
return right if (right.fits_u8?)
|
||||||
if (op_with_rot = calculate_u8_with_rr(right))
|
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[:update_status] = 0 if @attributes[:update_status] == nil
|
||||||
@attributes[:condition_code] = :al if @attributes[:condition_code] == nil
|
@attributes[:condition_code] = :al if @attributes[:condition_code] == nil
|
||||||
@attributes[:opcode] = attributes[:opcode]
|
@attributes[:opcode] = attributes[:opcode]
|
||||||
@operand = 0
|
@rn = :sp # sp register
|
||||||
|
|
||||||
# @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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# don't overwrite instance variables, to make assembly repeatable
|
||||||
def assemble(io)
|
def assemble(io)
|
||||||
# don't overwrite instance variables, to make assembly repeatable
|
operand = 0
|
||||||
operand = @operand
|
raise "invalid operand argument #{inspect}" unless (@first.is_a?(Array))
|
||||||
|
@first.each do |r|
|
||||||
if (@first.is_a?(Array))
|
raise "nil register in push, index #{r}- #{inspect}" if r.nil?
|
||||||
operand = 0
|
operand = operand | (1 << reg_code(r))
|
||||||
@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}"
|
|
||||||
end
|
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 = operand
|
||||||
val = val | (reg_code(@rn) << 16)
|
val = val | (reg_code(@rn) << 16)
|
||||||
val = val | (is_pop << 16 + 4) #20
|
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 | (@attributes[:update_status] << 16 + 4 + 1 + 1)
|
||||||
val = val | (up_down << 16 + 4 + 1 + 1 + 1)
|
val = val | (up_down << 16 + 4 + 1 + 1 + 1)
|
||||||
val = val | (pre_post_index << 16 + 4 + 1 + 1 + 1 + 1)#24
|
val = val | (pre_post_index << 16 + 4 + 1 + 1 + 1 + 1)#24
|
||||||
@ -59,9 +35,29 @@ module Arm
|
|||||||
io.write_uint32 val
|
io.write_uint32 val
|
||||||
end
|
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
|
def regs
|
||||||
@first
|
@first
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
"#{opcode} [#{@first.join(',') }] #{super}"
|
"#{opcode} [#{@first.join(',') }] #{super}"
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user