From 7d8e2dccef8019df61d7724277adaa68ed434484 Mon Sep 17 00:00:00 2001 From: Matthew Berry Date: Sun, 27 Sep 2020 18:12:04 -0700 Subject: [PATCH] set carry flag from barrel shifter ops (arm & thumb) --- src/crab/arm/arm.cr | 12 ++++++------ src/crab/arm/data_processing.cr | 4 ++-- src/crab/arm/single_data_transfer.cr | 2 +- src/crab/cpu.cr | 16 ++++++++++++---- src/crab/thumb/move_shifted_register.cr | 7 +++---- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/crab/arm/arm.cr b/src/crab/arm/arm.cr index 6d32bcf..8e8424f 100644 --- a/src/crab/arm/arm.cr +++ b/src/crab/arm/arm.cr @@ -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 diff --git a/src/crab/arm/data_processing.cr b/src/crab/arm/data_processing.cr index 4880c24..954d159 100644 --- a/src/crab/arm/data_processing.cr +++ b/src/crab/arm/data_processing.cr @@ -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 diff --git a/src/crab/arm/single_data_transfer.cr b/src/crab/arm/single_data_transfer.cr index 2955937..5b787ad 100644 --- a/src/crab/arm/single_data_transfer.cr +++ b/src/crab/arm/single_data_transfer.cr @@ -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 diff --git a/src/crab/cpu.cr b/src/crab/cpu.cr index a019369..1cbc74b 100644 --- a/src/crab/cpu.cr +++ b/src/crab/cpu.cr @@ -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 diff --git a/src/crab/thumb/move_shifted_register.cr b/src/crab/thumb/move_shifted_register.cr index 5fec274..fde88a9 100644 --- a/src/crab/thumb/move_shifted_register.cr +++ b/src/crab/thumb/move_shifted_register.cr @@ -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