data processing logical flags, minor rotate_register patch, abstract immediate_offset

This commit is contained in:
Matthew Berry 2020-09-26 21:47:00 -07:00
parent 64c8b26fb8
commit df79b7b48b
2 changed files with 30 additions and 22 deletions

View file

@ -108,12 +108,12 @@ module ARM
end
def rotate_register(instr : Word) : Word
shift = bits(instr, 4..11)
reg = bits(instr, 0..3)
shift_type = bits(instr, 5..6)
shift_amount = if bit?(instr, 4)
shift_register = bits(instr, 8..11)
@r[shift_register] & 0xF
# todo weird logic if bottom byte of reg > 31
@r[shift_register] & 0xFF
else
bits(instr, 7..11)
end
@ -125,4 +125,10 @@ module ARM
else raise "Impossible shift type: #{hex_str shift_type}"
end
end
def immediate_offset(instr : Word) : Word
rotate = bits(instr, 8..11)
imm = bits(instr, 0..7)
ror(imm, 2 * rotate)
end
end

View file

@ -1,36 +1,38 @@
module ARM
def arm_data_processing(instr : Word) : Nil
# todo all resulting flags
imm_flag = bit?(instr, 25)
opcode = bits(instr, 21..24)
set_conditions = bit?(instr, 20)
rn = bits(instr, 16..19)
rd = bits(instr, 12..15)
# todo set carry flag from barrel shifter
operand_2 = if imm_flag # Operand 2 is an immediate
rotate = bits(instr, 8..11)
imm = bits(instr, 0..7)
ror(imm, 2 * rotate)
immediate_offset bits(instr, 0..11)
else # Operand 2 is a register
rotate_register bits(instr, 0..11)
end
case opcode
when 0x0 then @r[rd] = rn & operand_2
when 0x1 then @r[rd] = rn ^ operand_2
when 0x2 then @r[rd] = rn &- operand_2
when 0x3 then @r[rd] = operand_2 &- rn
when 0x4 then @r[rd] = rn &+ operand_2
when 0x5 then @r[rd] = rn &+ operand_2 &+ @cpsr.carry.to_unsafe
when 0x6 then @r[rd] = rn &- operand_2 &+ @cpsr.carry.to_unsafe &- 1
when 0x7 then @r[rd] = operand_2 &- rn &+ @cpsr.carry.to_unsafe &- 1
when 0x8
when 0x9
when 0xA
when 0xB
when 0xC then @r[rd] = rn | operand_2
when 0xD then @r[rd] = operand_2
when 0xE then @r[rd] = rn & ~operand_2
when 0xF then @r[rd] = ~operand_2
when 0x0 then res = @r[rd] = rn & operand_2
when 0x1 then res = @r[rd] = rn ^ operand_2
when 0x2 then res = @r[rd] = rn &- operand_2
when 0x3 then res = @r[rd] = operand_2 &- rn
when 0x4 then res = @r[rd] = rn &+ operand_2
when 0x5 then res = @r[rd] = rn &+ operand_2 &+ @cpsr.carry.to_unsafe
when 0x6 then res = @r[rd] = rn &- operand_2 &+ @cpsr.carry.to_unsafe &- 1
when 0x7 then res = @r[rd] = operand_2 &- rn &+ @cpsr.carry.to_unsafe &- 1
when 0x8 then res = rn & operand_2
when 0x9 then res = rn ^ operand_2
when 0xA then res = rn &- operand_2
when 0xB then res = rn &+ operand_2
when 0xC then res = @r[rd] = rn | operand_2
when 0xD then res = @r[rd] = operand_2
when 0xE then res = @r[rd] = rn & ~operand_2
when 0xF then res = @r[rd] = ~operand_2
else raise "Unimplemented execution of data processing opcode: #{hex_str opcode}"
end
if set_conditions # todo this only works for logical ops, not arithmetic
@cpsr.zero = res == 0
@cpsr.negative = bit?(res, 31)
end
end
end