set carry flag from barrel shifter ops (arm & thumb)

This commit is contained in:
Matthew Berry 2020-09-27 18:12:04 -07:00
parent 8e6040e4c4
commit 7d8e2dccef
5 changed files with 24 additions and 17 deletions

View file

@ -68,7 +68,7 @@ module ARM
puts "Unused instruction: #{hex_str instr}"
end
def rotate_register(instr : Word, allow_register_shifts = true) : Word
def rotate_register(instr : Word, set_conditions : Bool, allow_register_shifts = true) : Word
reg = bits(instr, 0..3)
shift_type = bits(instr, 5..6)
shift_amount = if allow_register_shifts && bit?(instr, 4)
@ -79,10 +79,10 @@ module ARM
bits(instr, 7..11)
end
case shift_type
when 0b00 then lsl(@r[reg], shift_amount)
when 0b01 then lsr(@r[reg], shift_amount)
when 0b10 then asr(@r[reg], shift_amount)
when 0b11 then ror(@r[reg], shift_amount)
when 0b00 then lsl(@r[reg], shift_amount, set_conditions)
when 0b01 then lsr(@r[reg], shift_amount, set_conditions)
when 0b10 then asr(@r[reg], shift_amount, set_conditions)
when 0b11 then ror(@r[reg], shift_amount, set_conditions)
else raise "Impossible shift type: #{hex_str shift_type}"
end
end
@ -90,6 +90,6 @@ module ARM
def immediate_offset(instr : Word) : Word
rotate = bits(instr, 8..11)
imm = bits(instr, 0..7)
ror(imm, 2 * rotate)
ror(imm, 2 * rotate, false)
end
end

View file

@ -5,12 +5,12 @@ module ARM
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
immediate_offset bits(instr, 0..11)
else # Operand 2 is a register
rotate_register bits(instr, 0..11)
rotate_register bits(instr, 0..11), set_conditions
end
# todo handle carry flag on all ops
case opcode
when 0x0 then res = @r[rd] = @r[rn] & operand_2
when 0x1 then res = @r[rd] = @r[rn] ^ operand_2

View file

@ -10,7 +10,7 @@ module ARM
rn = bits(instr, 16..19)
rd = bits(instr, 12..15)
operand_2 = if imm_flag # Operand 2 is a register (opposite of data procesing for some reason)
rotate_register bits(instr, 0..11), allow_register_shifts: false
rotate_register bits(instr, 0..11), set_conditions: false, allow_register_shifts: false
else # Operand 2 is an immediate offset
immediate_offset bits(instr, 0..11)
end

View file

@ -83,22 +83,30 @@ class CPU
end
# Logical shift left
def lsl(word : Word, bits : Int) : Word
def lsl(word : Word, bits : Int, set_conditions : Bool) : Word
log "lsl - word:#{hex_str word}, bits:#{bits}"
@cpsr.carry = bit?(word, 32 - bits) if set_conditions
word << bits
end
# Logical shift right
def lsr(word : Word, bits : Int) : Word
def lsr(word : Word, bits : Int, set_conditions : Bool) : Word
log "lsr - word:#{hex_str word}, bits:#{bits}"
@cpsr.carry = bit?(word, bits - 1) if set_conditions
word >> bits
end
# Arithmetic shift right
def asr(word : Word, bits : Int) : Word
def asr(word : Word, bits : Int, set_conditions : Bool) : Word
log "asr - word:#{hex_str word}, bits:#{bits}"
@cpsr.carry = bit?(word, bits - 1) if set_conditions
word // (2 ** bits)
end
# Rotate right
def ror(word : Word, bits : Int) : Word
def ror(word : Word, bits : Int, set_conditions : Bool) : Word
log "ror - word:#{hex_str word}, bits:#{bits}"
@cpsr.carry = bit?(word, bits - 1) if set_conditions
word >> bits | word << (32 - bits)
end

View file

@ -1,14 +1,13 @@
module THUMB
def thumb_move_shifted_register(instr : Word) : Nil
# todo carry flags (currently first divergence on armwrestler)
op = bits(instr, 11..12)
offset = bits(instr, 6..10)
rs = bits(instr, 3..5)
rd = bits(instr, 0..2)
@r[rd] = case op
when 0b00 then lsl(@r[rs], offset)
when 0b01 then lsr(@r[rs], offset)
when 0b10 then asr(@r[rs], offset)
when 0b00 then lsl(@r[rs], offset, true)
when 0b01 then lsr(@r[rs], offset, true)
when 0b10 then asr(@r[rs], offset, true)
else raise "Invalid shifted register op: #{op}"
end
@cpsr.zero = @r[rd] == 0