abstract register writing (always align and clear pipeline on pc writes)

This commit is contained in:
Matthew Berry 2020-10-24 16:00:12 -07:00
parent 2188e81c5b
commit 5749cd3a24
34 changed files with 116 additions and 123 deletions

View file

@ -14,8 +14,7 @@ module ARM
16.times do |idx| 16.times do |idx|
if bit?(list, idx) if bit?(list, idx)
address &+= add ? 4 : -4 if pre_index address &+= add ? 4 : -4 if pre_index
@r[idx] = @gba.bus.read_word(address) set_reg(idx, @gba.bus.read_word(address))
clear_pipeline if idx == 15
address &+= add ? 4 : -4 unless pre_index address &+= add ? 4 : -4 unless pre_index
end end
end end
@ -29,9 +28,6 @@ module ARM
end end
end end
if write_back set_reg(rn, address) if write_back
@r[rn] = address
clear_pipeline if rn == 15 # do this for all other instrs that write to r15
end
end end
end end

View file

@ -3,8 +3,7 @@ module ARM
link = bit?(instr, 24) link = bit?(instr, 24)
offset = instr & 0xFFFFFF offset = instr & 0xFFFFFF
offset = (offset << 8).to_i32! >> 6 offset = (offset << 8).to_i32! >> 6
@r[14] = @r[15] - 4 if link set_reg(14, @r[15] - 4) if link
@r[15] &+= offset set_reg(15, @r[15] &+ offset)
clear_pipeline
end end
end end

View file

@ -3,10 +3,9 @@ module ARM
rn = bits(instr, 0..3) rn = bits(instr, 0..3)
if bit?(@r[rn], 0) if bit?(@r[rn], 0)
@cpsr.thumb = true @cpsr.thumb = true
@r[15] = @r[rn] & ~1 set_reg(15, @r[rn])
else else
@r[15] = @r[rn] & ~3 set_reg(15, @r[rn])
end end
clear_pipeline
end end
end end

View file

@ -12,28 +12,27 @@ module ARM
end end
# todo handle carry flag on all ops # todo handle carry flag on all ops
case opcode case opcode
when 0x0 then res = @r[rd] = @r[rn] & operand_2 when 0x0 then res = set_reg(rd, @r[rn] & operand_2)
when 0x1 then res = @r[rd] = @r[rn] ^ operand_2 when 0x1 then res = set_reg(rd, @r[rn] ^ operand_2)
when 0x2 then res = @r[rd] = sub(@r[rn], operand_2, set_conditions) when 0x2 then res = set_reg(rd, sub(@r[rn], operand_2, set_conditions))
when 0x3 then res = @r[rd] = sub(operand_2, @r[rn], set_conditions) when 0x3 then res = set_reg(rd, sub(operand_2, @r[rn], set_conditions))
when 0x4 then res = @r[rd] = add(@r[rn], operand_2, set_conditions) when 0x4 then res = set_reg(rd, add(@r[rn], operand_2, set_conditions))
when 0x5 then res = @r[rd] = adc(@r[rn], operand_2, set_conditions) when 0x5 then res = set_reg(rd, adc(@r[rn], operand_2, set_conditions))
when 0x6 then res = @r[rd] = sbc(@r[rn], operand_2, set_conditions) when 0x6 then res = set_reg(rd, sbc(@r[rn], operand_2, set_conditions))
when 0x7 then res = @r[rd] = sbc(operand_2, @r[rn], set_conditions) when 0x7 then res = set_reg(rd, sbc(operand_2, @r[rn], set_conditions))
when 0x8 then res = @r[rn] & operand_2 when 0x8 then res = @r[rn] & operand_2
when 0x9 then res = @r[rn] ^ operand_2 when 0x9 then res = @r[rn] ^ operand_2
when 0xA then res = sub(@r[rn], operand_2, set_conditions) when 0xA then res = sub(@r[rn], operand_2, set_conditions)
when 0xB then res = add(@r[rn], operand_2, set_conditions) when 0xB then res = add(@r[rn], operand_2, set_conditions)
when 0xC then res = @r[rd] = @r[rn] | operand_2 when 0xC then res = set_reg(rd, @r[rn] | operand_2)
when 0xD then res = @r[rd] = operand_2 when 0xD then res = set_reg(rd, operand_2)
when 0xE then res = @r[rd] = @r[rn] & ~operand_2 when 0xE then res = set_reg(rd, @r[rn] & ~operand_2)
when 0xF then res = @r[rd] = ~operand_2 when 0xF then res = set_reg(rd, ~operand_2)
else raise "Unimplemented execution of data processing opcode: #{hex_str opcode}" else raise "Unimplemented execution of data processing opcode: #{hex_str opcode}"
end end
if set_conditions # todo this only works for logical ops, not arithmetic if set_conditions # todo this only works for logical ops, not arithmetic
@cpsr.zero = res == 0 @cpsr.zero = res == 0
@cpsr.negative = bit?(res, 31) @cpsr.negative = bit?(res, 31)
end end
clear_pipeline if rd == 15 # todo only do this when needed (not 0xA or 0xB)
end end
end end

View file

@ -25,25 +25,25 @@ module ARM
when 0b00 # swp, no docs on this? when 0b00 # swp, no docs on this?
when 0b01 # ldrh/strh when 0b01 # ldrh/strh
if load if load
@r[rd] = @gba.bus.read_half address set_reg(rd, @gba.bus.read_half address)
else else
@gba.bus[address] = 0xFFFF_u16 & @r[rd] @gba.bus[address] = 0xFFFF_u16 & @r[rd]
end end
when 0b10 # ldrsb when 0b10 # ldrsb
@r[rd] = @gba.bus[address].to_i8!.to_u32 set_reg(rd, @gba.bus[address].to_i8!.to_u32)
when 0b11 # ldrsh when 0b11 # ldrsh
@r[rd] = @gba.bus.read_half(address).to_i16!.to_u32 set_reg(rd, @gba.bus.read_half(address).to_i16!.to_u32)
else raise "Invalid halfword data transfer imm op: #{sh}" else raise "Invalid halfword data transfer imm op: #{sh}"
end end
if !pre_index if !pre_index
if add if add
@r[rn] &+= offset set_reg(rn, @r[rn] &+ offset)
else else
@r[rn] &-= offset set_reg(rn, @r[rn] &- offset)
end end
elsif write_back elsif write_back
@r[rn] = address set_reg(rn, address)
end end
end end
end end

View file

@ -24,25 +24,25 @@ module ARM
when 0b00 # swp, no docs on this? when 0b00 # swp, no docs on this?
when 0b01 # ldrh/strh when 0b01 # ldrh/strh
if load if load
@r[rd] = @gba.bus.read_half address set_reg(rd, @gba.bus.read_half address)
else else
@gba.bus[address] = 0xFFFF_u16 & @r[rd] @gba.bus[address] = 0xFFFF_u16 & @r[rd]
end end
when 0b10 # ldrsb when 0b10 # ldrsb
@r[rd] = @gba.bus[address].to_i8!.to_u32 set_reg(rd, @gba.bus[address].to_i8!.to_u32)
when 0b11 # ldrsh when 0b11 # ldrsh
@r[rd] = @gba.bus.read_half(address).to_i16!.to_u32 set_reg(rd, @gba.bus.read_half(address).to_i16!.to_u32)
else raise "Invalid halfword data transfer imm op: #{sh}" else raise "Invalid halfword data transfer imm op: #{sh}"
end end
if !pre_index if !pre_index
if add if add
@r[rn] &+= offset set_reg(rn, @r[rn] &+ offset)
else else
@r[rn] &-= offset set_reg(rn, @r[rn] &- offset)
end end
elsif write_back elsif write_back
@r[rn] = address set_reg(rn, address)
end end
end end
end end

View file

@ -7,8 +7,8 @@ module ARM
rs = bits(instr, 8..11) rs = bits(instr, 8..11)
rm = bits(instr, 0..3) rm = bits(instr, 0..3)
@r[rd] = @r[rm] &* @r[rs] set_reg(rd, @r[rm] &* @r[rs])
@r[rd] &+= @r[rn] if accumulate set_reg(rd, @r[rd] &+ @r[rn]) if accumulate
if set_conditions if set_conditions
@cpsr.zero = @r[rd] == 0 @cpsr.zero = @r[rd] == 0
@cpsr.negative = bit?(@r[rd], 31) @cpsr.negative = bit?(@r[rd], 31)

View file

@ -14,8 +14,8 @@ module ARM
@r[rm].to_u64 &* @r[rs] @r[rm].to_u64 &* @r[rs]
end end
res &+= @r[rdhi].to_u64 << 32 | @r[rdlo] if accumulate res &+= @r[rdhi].to_u64 << 32 | @r[rdlo] if accumulate
@r[rdhi] = (res >> 32).to_u32! set_reg(rdhi, (res >> 32).to_u32!)
@r[rdlo] = res.to_u32! set_reg(rdlo, res.to_u32!)
if set_conditions if set_conditions
@cpsr.zero = res == 0 @cpsr.zero = res == 0
@cpsr.negative = bit?(@r[rdhi], 31) @cpsr.negative = bit?(@r[rdhi], 31)

View file

@ -27,9 +27,9 @@ module ARM
else else
rd = bits(instr, 12..15) rd = bits(instr, 12..15)
if spsr if spsr
@r[rd] = @spsr.value set_reg(rd, @spsr.value)
else else
@r[rd] = @cpsr.value set_reg(rd, @cpsr.value)
end end
end end
end end

View file

@ -7,11 +7,11 @@ module ARM
if byte_quantity if byte_quantity
tmp = @gba.bus[@r[rn]] tmp = @gba.bus[@r[rn]]
@gba.bus[@r[rn]] = @r[rm].to_u8! @gba.bus[@r[rn]] = @r[rm].to_u8!
@r[rd] = tmp.to_u32 set_reg(rd, tmp.to_u32)
else else
tmp = @gba.bus.read_word @r[rn] tmp = @gba.bus.read_word @r[rn]
@gba.bus[@r[rn]] = @r[rm] @gba.bus[@r[rn]] = @r[rm]
@r[rd] = tmp set_reg(rd, tmp)
end end
end end
end end

View file

@ -27,9 +27,9 @@ module ARM
if load if load
if byte_quantity if byte_quantity
@r[rd] = 0xFF_u32 & @gba.bus[address] set_reg(rd, 0xFF_u32 & @gba.bus[address])
else else
@r[rd] = @gba.bus.read_word address set_reg(rd, @gba.bus.read_word address)
end end
else else
if byte_quantity if byte_quantity
@ -41,12 +41,12 @@ module ARM
if !pre_indexing if !pre_indexing
if add_offset if add_offset
@r[rn] &+= offset set_reg(rn, @r[rn] &+ offset)
else else
@r[rn] &-= offset set_reg(rn, @r[rn] &- offset)
end end
elsif write_back elsif write_back
@r[rn] = address set_reg(rn, address)
end end
end end
end end

View file

@ -2,9 +2,8 @@ module ARM
def arm_software_interrupt(instr : Word) : Nil def arm_software_interrupt(instr : Word) : Nil
lr = @r[15] - 4 lr = @r[15] - 4
switch_mode CPU::Mode::SVC switch_mode CPU::Mode::SVC
@r[14] = lr set_reg(14, lr)
@cpsr.irq_disable = true @cpsr.irq_disable = true
@r[15] = 0x08 set_reg(15, 0x08)
clear_pipeline
end end
end end

View file

@ -134,6 +134,21 @@ class CPU
end end
end end
@[AlwaysInline]
def set_reg(reg : Int, value : UInt32) : UInt32
case reg
when 15
if @cpsr.thumb
@r[reg] = value & ~1
else
@r[reg] = value & ~3
end
clear_pipeline
else @r[reg] = value
end
value
end
# Logical shift left # Logical shift left
def lsl(word : Word, bits : Int, set_conditions : Bool) : Word def lsl(word : Word, bits : Int, set_conditions : Bool) : Word
log "lsl - word:#{hex_str word}, bits:#{bits}" log "lsl - word:#{hex_str word}, bits:#{bits}"

View file

@ -20,6 +20,7 @@ class Display
@fps = 30 @fps = 30
@seconds : Int32 = Time.utc.second @seconds : Int32 = Time.utc.second
def draw(framebuffer : Bytes) : Nil def draw(framebuffer : Bytes) : Nil
LibSDL.update_texture @texture, nil, framebuffer, WIDTH * 2 LibSDL.update_texture @texture, nil, framebuffer, WIDTH * 2
@renderer.clear @renderer.clear

View file

@ -3,9 +3,9 @@ module THUMB
sign = bit?(instr, 7) sign = bit?(instr, 7)
offset = bits(instr, 0..6) offset = bits(instr, 0..6)
if sign # negative if sign # negative
@r[13] &-= (offset << 2) set_reg(13, @r[13] &- (offset << 2))
else # positive else # positive
@r[13] &+= (offset << 2) set_reg(13, @r[13] &+ (offset << 2))
end end
end end
end end

View file

@ -11,9 +11,9 @@ module THUMB
@r[imm] @r[imm]
end end
if sub if sub
@r[rd] = sub(@r[rs], operand, true) set_reg(rd, sub(@r[rs], operand, true))
else else
@r[rd] = add(@r[rs], operand, true) set_reg(rd, add(@r[rs], operand, true))
end end
# todo handle carry flag on all ops # todo handle carry flag on all ops
@cpsr.zero = @r[rd] == 0 @cpsr.zero = @r[rd] == 0

View file

@ -5,22 +5,22 @@ module THUMB
rd = bits(instr, 0..2) rd = bits(instr, 0..2)
# todo handle flags for all ops # todo handle flags for all ops
case op case op
when 0b0000 then res = @r[rd] = @r[rd] & @r[rs] when 0b0000 then res = set_reg(rd, @r[rd] & @r[rs])
when 0b0001 then res = @r[rd] = @r[rd] ^ @r[rs] when 0b0001 then res = set_reg(rd, @r[rd] ^ @r[rs])
when 0b0010 then res = @r[rd] = lsl(@r[rd], @r[rs], true) when 0b0010 then res = set_reg(rd, lsl(@r[rd], @r[rs], true))
when 0b0011 then res = @r[rd] = lsr(@r[rd], @r[rs], true) when 0b0011 then res = set_reg(rd, lsr(@r[rd], @r[rs], true))
when 0b0100 then res = @r[rd] = asr(@r[rd], @r[rs], true) when 0b0100 then res = set_reg(rd, asr(@r[rd], @r[rs], true))
when 0b0101 then res = @r[rd] = adc(@r[rd], @r[rs], true) when 0b0101 then res = set_reg(rd, adc(@r[rd], @r[rs], true))
when 0b0110 then res = @r[rd] = sbc(@r[rd], @r[rs], true) when 0b0110 then res = set_reg(rd, sbc(@r[rd], @r[rs], true))
when 0b0111 then res = @r[rd] = ror(@r[rd], @r[rs], true) when 0b0111 then res = set_reg(rd, ror(@r[rd], @r[rs], true))
when 0b1000 then res = @r[rd] & @r[rs] when 0b1000 then res = @r[rd] & @r[rs]
when 0b1001 then res = @r[rd] = (-@r[rs].to_i32!).to_u32! when 0b1001 then res = set_reg(rd, (-@r[rs].to_i32!).to_u32!)
when 0b1010 then res = sub(@r[rd], @r[rs], true) when 0b1010 then res = sub(@r[rd], @r[rs], true)
when 0b1011 then res = add(@r[rd], @r[rs], true) when 0b1011 then res = add(@r[rd], @r[rs], true)
when 0b1100 then res = @r[rd] = @r[rd] | @r[rs] when 0b1100 then res = set_reg(rd, @r[rd] | @r[rs])
when 0b1101 then res = @r[rd] = @r[rs] &* @r[rd] when 0b1101 then res = set_reg(rd, @r[rs] &* @r[rd])
when 0b1110 then res = @r[rd] = @r[rd] & ~@r[rs] when 0b1110 then res = set_reg(rd, @r[rd] & ~@r[rs])
when 0b1111 then res = @r[rd] = ~@r[rs] when 0b1111 then res = set_reg(rd, ~@r[rs])
else raise "Invalid alu op: #{op}" else raise "Invalid alu op: #{op}"
end end
@cpsr.zero = res == 0 @cpsr.zero = res == 0

View file

@ -3,8 +3,7 @@ module THUMB
cond = bits(instr, 8..11) cond = bits(instr, 8..11)
offset = bits(instr, 0..7).to_i8!.to_i32 offset = bits(instr, 0..7).to_i8!.to_i32
if check_cond cond if check_cond cond
@r[15] &+= (offset * 2) set_reg(15, @r[15] &+ (offset * 2))
clear_pipeline
end end
end end
end end

View file

@ -10,18 +10,16 @@ module THUMB
rs += 8 if h2 rs += 8 if h2
case op case op
when 0b00 then @r[rd] = add(@r[rd], @r[rs], true) when 0b00 then set_reg(rd, add(@r[rd], @r[rs], true))
when 0b01 then sub(@r[rd], @r[rs], true) when 0b01 then sub(@r[rd], @r[rs], true)
when 0b10 then @r[rd] = @r[rs] when 0b10 then set_reg(rd, @r[rs])
when 0b11 when 0b11
if bit?(@r[rs], 0) if bit?(@r[rs], 0)
@r[15] = @r[rs] & ~1 set_reg(15, @r[rs])
else else
@cpsr.thumb = false @cpsr.thumb = false
@r[15] = @r[rs] & ~3 set_reg(15, @r[rs])
end end
clear_pipeline
end end
clear_pipeline if rd == 15
end end
end end

View file

@ -4,6 +4,6 @@ module THUMB
rd = bits(instr, 8..10) rd = bits(instr, 8..10)
word = bits(instr, 0..8) word = bits(instr, 0..8)
imm = word << 2 imm = word << 2
@r[rd] = (source ? @r[13] : @r[15]) &+ imm set_reg(rd, (source ? @r[13] : @r[15]) &+ imm)
end end
end end

View file

@ -6,7 +6,7 @@ module THUMB
rd = bits(instr, 0..2) rd = bits(instr, 0..2)
address = @r[rb] + (offset << 1) address = @r[rb] + (offset << 1)
if load if load
@r[rd] = @gba.bus.read_half(address) set_reg(rd, @gba.bus.read_half(address))
else else
@gba.bus[address] = @r[rd].to_u16! @gba.bus[address] = @r[rd].to_u16!
end end

View file

@ -8,13 +8,9 @@ module THUMB
address = @r[rb] &+ (offset << 2) address = @r[rb] &+ (offset << 2)
case byte_quantity_and_load case byte_quantity_and_load
when 0b00 then @gba.bus[address] = @r[rd] when 0b00 then @gba.bus[address] = @r[rd]
when 0b01 when 0b01 then set_reg(rd, @gba.bus.read_word(address))
@r[rd] = @gba.bus.read_word(address)
clear_pipeline if rd == 15
when 0b10 then @gba.bus[address] = 0xFF_u8 & @r[rd] when 0b10 then @gba.bus[address] = 0xFF_u8 & @r[rd]
when 0b11 when 0b11 then set_reg(rd, 0xFFFFFFFF_u32 & @gba.bus[address])
@r[rd] = 0xFFFFFFFF_u32 & @gba.bus[address]
clear_pipeline if rd == 15
end end
end end
end end

View file

@ -8,12 +8,8 @@ module THUMB
case load_and_byte_quantity case load_and_byte_quantity
when 0b00 then @gba.bus[address] = @r[rd] when 0b00 then @gba.bus[address] = @r[rd]
when 0b01 then @gba.bus[address] = 0xFF_u8 & @r[rd] when 0b01 then @gba.bus[address] = 0xFF_u8 & @r[rd]
when 0b10 when 0b10 then set_reg(rd, @gba.bus.read_word address)
@r[rd] = @gba.bus.read_word address when 0b11 then set_reg(rd, 0xFFFFFFFF_u32 & @gba.bus[address])
clear_pipeline if rd == 15
when 0b11
@r[rd] = 0xFFFFFFFF_u32 & @gba.bus[address]
clear_pipeline if rd == 15
end end
end end
end end

View file

@ -7,9 +7,9 @@ module THUMB
address = @r[rb] &+ @r[ro] address = @r[rb] &+ @r[ro]
case hs case hs
when 0b00 then @gba.bus[address] = @r[rd].to_u16! # strh when 0b00 then @gba.bus[address] = @r[rd].to_u16! # strh
when 0b01 then @r[rd] = @gba.bus[address].to_i8!.to_u32 # ldsb when 0b01 then set_reg(rd, @gba.bus[address].to_i8!.to_u32) # ldsb
when 0b10 then @r[rd] = @gba.bus.read_half(address) # ldrh when 0b10 then set_reg(rd, @gba.bus.read_half(address)) # ldrh
when 0b11 then @r[rd] = @gba.bus.read_half(address).to_i16!.to_u32 # ldsh when 0b11 then set_reg(rd, @gba.bus.read_half(address).to_i16!.to_u32) # ldsh
else raise "Invalid load/store signed extended: #{hs}" else raise "Invalid load/store signed extended: #{hs}"
end end
end end

View file

@ -4,12 +4,11 @@ module THUMB
offset = bits(instr, 0..10) offset = bits(instr, 0..10)
if second_instr if second_instr
temp = @r[15] &- 2 temp = @r[15] &- 2
@r[15] = @r[14] &+ (offset << 1) set_reg(15, @r[14] &+ (offset << 1))
@r[14] = temp | 1 set_reg(14, temp | 1)
clear_pipeline
else else
offset = (offset << 5).to_i16! >> 5 offset = (offset << 5).to_i16! >> 5
@r[14] = @r[15] &+ (offset.to_u32 << 12) set_reg(14, @r[15] &+ (offset.to_u32 << 12))
end end
end end
end end

View file

@ -5,10 +5,10 @@ module THUMB
offset = bits(instr, 0..7) offset = bits(instr, 0..7)
# todo handle carry flag on all ops # todo handle carry flag on all ops
case op case op
when 0b00 then res = @r[rd] = offset when 0b00 then res = set_reg(rd, offset)
when 0b01 then res = sub(@r[rd], offset, true) when 0b01 then res = sub(@r[rd], offset, true)
when 0b10 then res = @r[rd] = add(@r[rd], offset, true) when 0b10 then res = set_reg(rd, add(@r[rd], offset, true))
when 0b11 then res = @r[rd] = sub(@r[rd], offset, true) when 0b11 then res = set_reg(rd, sub(@r[rd], offset, true))
else raise "Invalid move/compare/add/subtract op: #{op}" else raise "Invalid move/compare/add/subtract op: #{op}"
end end
@cpsr.zero = res == 0 @cpsr.zero = res == 0

View file

@ -4,10 +4,10 @@ module THUMB
offset = bits(instr, 6..10) offset = bits(instr, 6..10)
rs = bits(instr, 3..5) rs = bits(instr, 3..5)
rd = bits(instr, 0..2) rd = bits(instr, 0..2)
@r[rd] = case op case op
when 0b00 then lsl(@r[rs], offset, true) when 0b00 then set_reg(rd, lsl(@r[rs], offset, true))
when 0b01 then lsr(@r[rs], offset, true) when 0b01 then set_reg(rd, lsr(@r[rs], offset, true))
when 0b10 then asr(@r[rs], offset, true) when 0b10 then set_reg(rd, asr(@r[rs], offset, true))
else raise "Invalid shifted register op: #{op}" else raise "Invalid shifted register op: #{op}"
end end
@cpsr.zero = @r[rd] == 0 @cpsr.zero = @r[rd] == 0

View file

@ -7,7 +7,7 @@ module THUMB
if load # ldmia if load # ldmia
8.times do |idx| 8.times do |idx|
if bit?(list, idx) if bit?(list, idx)
@r[idx] = @gba.bus.read_word(address) set_reg(idx, @gba.bus.read_word(address))
address &+= 4 address &+= 4
end end
end end
@ -19,6 +19,6 @@ module THUMB
end end
end end
end end
@r[rb] = address set_reg(rb, address)
end end
end end

View file

@ -2,6 +2,6 @@ module THUMB
def thumb_pc_relative_load(instr : Word) : Nil def thumb_pc_relative_load(instr : Word) : Nil
imm = bits(instr, 0..7) imm = bits(instr, 0..7)
rd = bits(instr, 8..10) rd = bits(instr, 8..10)
@r[rd] = @gba.bus.read_word((@r[15] & ~2) &+ (imm << 2)) set_reg(rd, @gba.bus.read_word((@r[15] & ~2) &+ (imm << 2)))
end end
end end

View file

@ -7,14 +7,13 @@ module THUMB
if pop if pop
8.times do |idx| 8.times do |idx|
if bit?(list, idx) if bit?(list, idx)
@r[idx] = @gba.bus.read_word(address) set_reg(idx, @gba.bus.read_word(address))
address &+= 4 address &+= 4
end end
end end
if pclr if pclr
@r[15] = @gba.bus.read_word(address) set_reg(15, @gba.bus.read_word(address))
address &+= 4 address &+= 4
clear_pipeline
end end
else else
if pclr if pclr
@ -28,6 +27,6 @@ module THUMB
end end
end end
end end
@r[13] = address set_reg(13, address)
end end
end end

View file

@ -2,10 +2,9 @@ module THUMB
def thumb_software_interrupt(instr : Word) : Nil def thumb_software_interrupt(instr : Word) : Nil
lr = @r[15] - 4 lr = @r[15] - 4
switch_mode CPU::Mode::SVC switch_mode CPU::Mode::SVC
@r[14] = lr set_reg(14, lr)
@cpsr.irq_disable = true @cpsr.irq_disable = true
@cpsr.thumb = false @cpsr.thumb = false
@r[15] = 0x08 set_reg(15, 0x08)
clear_pipeline
end end
end end

View file

@ -5,7 +5,7 @@ module THUMB
word = bits(instr, 0..7) word = bits(instr, 0..7)
address = @r[13] &+ (word << 2) address = @r[13] &+ (word << 2)
if load if load
@r[rd] = @gba.bus.read_word(address) set_reg(rd, @gba.bus.read_word(address))
else else
@gba.bus[address] = @r[rd] @gba.bus[address] = @r[rd]
end end

View file

@ -25,7 +25,7 @@ module THUMB
elsif idx & 0b11110000 == 0b10010000 elsif idx & 0b11110000 == 0b10010000
lut[idx] = ->thumb_sp_relative_load_store(Word) lut[idx] = ->thumb_sp_relative_load_store(Word)
elsif idx & 0b11110000 == 0b10000000 elsif idx & 0b11110000 == 0b10000000
lut[idx] = -> thumb_load_store_halfword(Word) lut[idx] = ->thumb_load_store_halfword(Word)
elsif idx & 0b11100000 == 0b01100000 elsif idx & 0b11100000 == 0b01100000
lut[idx] = ->thumb_load_store_immediate_offset(Word) lut[idx] = ->thumb_load_store_immediate_offset(Word)
elsif idx & 0b11110010 == 0b01010010 elsif idx & 0b11110010 == 0b01010010

View file

@ -2,7 +2,6 @@ module THUMB
def thumb_unconditional_branch(instr : Word) : Nil def thumb_unconditional_branch(instr : Word) : Nil
offset = bits(instr, 0..10) offset = bits(instr, 0..10)
offset = (offset << 5).to_i16! >> 4 offset = (offset << 5).to_i16! >> 4
@r[15] &+= offset set_reg(15, @r[15] &+ offset)
clear_pipeline
end end
end end