mirror of https://github.com/bsnes-emu/bsnes.git
Update to v087r11 release.
byuu says: Added all of the above fixes and changes. [A lot of individual fixes for the ARM core from Cydrak - Ed.] Also new is pipeline_decode() to fetch data, and IME/IE/IF support, and an ARM::processor.irqline flag that triggers IRQs at 0x18. Only Vblank is hooked up, which is what SWI 4 was waiting on previously. I'm sure my interrupt support is horribly broken and wrong. I was never able to really figure out IE/IF on the Game Boy, so there's no question this is even worse. It's now going crazy and writing 0 to IE forever now after the Vblank IRQ triggers.
This commit is contained in:
parent
5a1dcf5079
commit
c66cc73374
|
@ -1,7 +1,7 @@
|
|||
#ifndef BASE_HPP
|
||||
#define BASE_HPP
|
||||
|
||||
static const char Version[] = "087.10";
|
||||
static const char Version[] = "087.11";
|
||||
|
||||
#include <nall/platform.hpp>
|
||||
#include <nall/algorithm.hpp>
|
||||
|
|
|
@ -2,20 +2,23 @@
|
|||
|
||||
namespace GBA {
|
||||
|
||||
#include "registers.cpp"
|
||||
CPU cpu;
|
||||
|
||||
void CPU::Enter() { cpu.enter(); }
|
||||
|
||||
void CPU::enter() {
|
||||
while(true) {
|
||||
if(exception) {
|
||||
if(crash) {
|
||||
print(cpsr().t ? disassemble_thumb_instruction(pipeline.execute.address)
|
||||
: disassemble_arm_instruction(pipeline.execute.address), "\n");
|
||||
print(disassemble_registers(), "\n");
|
||||
print("Executed: ", instructions, "\n");
|
||||
while(true) step(frequency);
|
||||
}
|
||||
cpsr().t ? thumb_step() : arm_step();
|
||||
|
||||
processor.irqline = regs.ime && regs.irq_flag;
|
||||
exec();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,17 +47,57 @@ void CPU::power() {
|
|||
for(unsigned n = 0; n < iwram.size; n++) iwram.data[n] = 0;
|
||||
for(unsigned n = 0; n < ewram.size; n++) ewram.data[n] = 0;
|
||||
|
||||
bus.mmio[0x0300] = this;
|
||||
bus.mmio[0x0301] = this;
|
||||
bus.mmio[0x0302] = this;
|
||||
bus.mmio[0x0303] = this;
|
||||
regs.ime = 0;
|
||||
regs.irq_enable = 0;
|
||||
regs.irq_flag = 0;
|
||||
|
||||
bus.mmio[0x130] = this;
|
||||
bus.mmio[0x200] = this;
|
||||
bus.mmio[0x202] = this;
|
||||
bus.mmio[0x208] = this;
|
||||
}
|
||||
|
||||
uint32 CPU::read(uint32 addr, uint32 size) {
|
||||
uint32 result = 0;
|
||||
|
||||
switch(addr & 0x0ffffffc) {
|
||||
|
||||
case 0x04000130: //KEYINPUT
|
||||
for(unsigned n = 0; n < 10; n++) result |= (interface->inputPoll(n) == false) << n;
|
||||
if((result & 0xc0) == 0xc0) result &= ~0xc0; //up+down cannot be pressed simultaneously
|
||||
if((result & 0x30) == 0x30) result &= ~0x30; //left+right cannot be pressed simultaneously
|
||||
return result;
|
||||
|
||||
case 0x04000200: //IE
|
||||
return regs.irq_enable;
|
||||
|
||||
case 0x04000202: //IF
|
||||
return regs.irq_flag;
|
||||
|
||||
case 0x04000208: //IME
|
||||
return regs.ime;
|
||||
|
||||
}
|
||||
|
||||
return 0u;
|
||||
}
|
||||
|
||||
void CPU::write(uint32 addr, uint32 size, uint32 word) {
|
||||
switch(addr & 0x0ffffffc) {
|
||||
|
||||
case 0x04000200: //IE
|
||||
regs.irq_enable = word;
|
||||
return;
|
||||
|
||||
case 0x04000202: //IF
|
||||
regs.irq_flag = regs.irq_flag & ~word;
|
||||
return;
|
||||
|
||||
case 0x04000208: //IME
|
||||
regs.ime = word & 1;
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
CPU::CPU() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
struct CPU : Processor::ARM, Thread, Memory {
|
||||
StaticMemory iwram;
|
||||
StaticMemory ewram;
|
||||
#include "registers.hpp"
|
||||
|
||||
static void Enter();
|
||||
void enter();
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
CPU::Registers::Interrupt::operator uint16() const {
|
||||
return (
|
||||
(vblank << 0)
|
||||
|| (hblank << 1)
|
||||
|| (vcoincidence << 2)
|
||||
|| (timer0 << 3)
|
||||
|| (timer1 << 4)
|
||||
|| (timer2 << 5)
|
||||
|| (timer3 << 6)
|
||||
|| (serial << 7)
|
||||
|| (dma0 << 8)
|
||||
|| (dma1 << 9)
|
||||
|| (dma2 << 10)
|
||||
|| (dma3 << 11)
|
||||
|| (keypad << 12)
|
||||
|| (cartridge << 13)
|
||||
);
|
||||
}
|
||||
|
||||
CPU::Registers::Interrupt& CPU::Registers::Interrupt::operator=(uint16 source) {
|
||||
vblank = source & (1 << 0);
|
||||
hblank = source & (1 << 1);
|
||||
vcoincidence = source & (1 << 2);
|
||||
timer0 = source & (1 << 3);
|
||||
timer1 = source & (1 << 4);
|
||||
timer2 = source & (1 << 5);
|
||||
timer3 = source & (1 << 6);
|
||||
serial = source & (1 << 7);
|
||||
dma0 = source & (1 << 8);
|
||||
dma1 = source & (1 << 9);
|
||||
dma2 = source & (1 << 10);
|
||||
dma3 = source & (1 << 11);
|
||||
keypad = source & (1 << 12);
|
||||
cartridge = source & (1 << 13);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
struct Registers {
|
||||
bool ime;
|
||||
|
||||
struct Interrupt {
|
||||
bool vblank;
|
||||
bool hblank;
|
||||
bool vcoincidence;
|
||||
bool timer0;
|
||||
bool timer1;
|
||||
bool timer2;
|
||||
bool timer3;
|
||||
bool serial;
|
||||
bool dma0;
|
||||
bool dma1;
|
||||
bool dma2;
|
||||
bool dma3;
|
||||
bool keypad;
|
||||
bool cartridge;
|
||||
|
||||
operator uint16() const;
|
||||
Interrupt& operator=(uint16 source);
|
||||
} irq_enable, irq_flag;
|
||||
} regs;
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
//vdraw: 160 scanlines (197120 cycles)
|
||||
//vblank: 68 scanlines ( 83776 cycles)
|
||||
//frame: 208 scanlines (280896 cycles)
|
||||
//frame: 228 scanlines (280896 cycles)
|
||||
|
||||
namespace GBA {
|
||||
|
||||
|
@ -18,8 +18,8 @@ void PPU::Enter() { ppu.enter(); }
|
|||
|
||||
void PPU::enter() {
|
||||
while(true) {
|
||||
frame();
|
||||
step(280896);
|
||||
step(1232);
|
||||
scanline();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,27 @@ void PPU::power() {
|
|||
for(unsigned n = 0; n < vram.size; n++) vram.data[n] = 0;
|
||||
for(unsigned n = 0; n < oam.size; n++) oam.data[n] = 0;
|
||||
for(unsigned n = 0; n < pram.size; n++) pram.data[n] = 0;
|
||||
|
||||
regs.scanline = 0;
|
||||
|
||||
bus.mmio[0x006] = this;
|
||||
}
|
||||
|
||||
void PPU::scanline() {
|
||||
regs.scanline++;
|
||||
|
||||
if(regs.scanline == 160) {
|
||||
if(cpu.regs.ime && cpu.regs.irq_enable.vblank) {
|
||||
cpu.regs.irq_flag.vblank = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(regs.scanline == 228) {
|
||||
regs.scanline = 0;
|
||||
frame();
|
||||
}
|
||||
|
||||
if(regs.scanline >= 160) return;
|
||||
}
|
||||
|
||||
void PPU::frame() {
|
||||
|
@ -57,6 +78,11 @@ void PPU::frame() {
|
|||
}
|
||||
|
||||
uint32 PPU::read(uint32 addr, uint32 size) {
|
||||
if(addr == 0x04000006) {
|
||||
//VCOUNT
|
||||
return regs.scanline;
|
||||
}
|
||||
|
||||
return 0u;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,16 @@ struct PPU : Thread, Memory {
|
|||
StaticMemory oam;
|
||||
StaticMemory pram;
|
||||
|
||||
struct Registers {
|
||||
unsigned scanline;
|
||||
} regs;
|
||||
|
||||
static void Enter();
|
||||
void enter();
|
||||
void step(unsigned clocks);
|
||||
|
||||
void power();
|
||||
void scanline();
|
||||
void frame();
|
||||
|
||||
uint32 read(uint32 addr, uint32 size);
|
||||
|
|
|
@ -18,3 +18,121 @@ bool ARM::condition(uint4 condition) {
|
|||
case 15: return false; //NV (never)
|
||||
}
|
||||
}
|
||||
|
||||
uint32 ARM::bit(uint32 result) {
|
||||
if(cpsr().t || instruction() & (1 << 20)) {
|
||||
cpsr().n = result >> 31;
|
||||
cpsr().z = result == 0;
|
||||
cpsr().c = carryout();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32 ARM::add(uint32 source, uint32 modify, bool carry) {
|
||||
uint32 result = source + modify + carry;
|
||||
if(cpsr().t || instruction() & (1 << 20)) {
|
||||
uint32 overflow = ~(source ^ modify) & (source ^ result);
|
||||
cpsr().n = result >> 31;
|
||||
cpsr().z = result == 0;
|
||||
cpsr().c = (1u << 31) & (overflow ^ source ^ modify ^ result);
|
||||
cpsr().v = (1u << 31) & (overflow);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32 ARM::sub(uint32 source, uint32 modify, bool carry) {
|
||||
return add(source, ~modify, carry);
|
||||
}
|
||||
|
||||
uint32 ARM::mul(uint32 product, uint32 multiplicand, uint32 multiplier) {
|
||||
//Modified Booth Encoding
|
||||
bool carry = 0;
|
||||
unsigned place = 0;
|
||||
|
||||
do {
|
||||
step(1);
|
||||
signed factor = (int2)multiplier + carry;
|
||||
|
||||
if(factor == -2) product -= multiplicand << (place + 1);
|
||||
if(factor == -1) product -= multiplicand << (place + 0);
|
||||
if(factor == +1) product += multiplicand << (place + 0);
|
||||
if(factor == +2) product += multiplicand << (place + 1);
|
||||
|
||||
carry = multiplier & 2;
|
||||
place += 2;
|
||||
multiplier >>= 2;
|
||||
} while(multiplier + carry && place < 32);
|
||||
|
||||
if(cpsr().t || instruction() & (1 << 20)) {
|
||||
cpsr().n = product >> 31;
|
||||
cpsr().z = product == 0;
|
||||
cpsr().c = carry;
|
||||
}
|
||||
|
||||
return product;
|
||||
}
|
||||
|
||||
uint32 ARM::lsl(uint32 source, uint32 shift) {
|
||||
while(shift--) {
|
||||
carryout() = source >> 31;
|
||||
source <<= 1;
|
||||
}
|
||||
|
||||
if(cpsr().t) {
|
||||
cpsr().n = source >> 31;
|
||||
cpsr().z = source == 0;
|
||||
cpsr().c = carryout();
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
uint32 ARM::lsr(uint32 source, uint32 shift) {
|
||||
while(shift--) {
|
||||
carryout() = source & 1;
|
||||
source >>= 1;
|
||||
}
|
||||
|
||||
if(cpsr().t) {
|
||||
cpsr().n = source >> 31;
|
||||
cpsr().z = source == 0;
|
||||
cpsr().c = carryout();
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
uint32 ARM::asr(uint32 source, uint32 shift) {
|
||||
while(shift--) {
|
||||
carryout() = source & 1;
|
||||
source = (int32)source >> 1;
|
||||
}
|
||||
|
||||
if(cpsr().t) {
|
||||
cpsr().n = source >> 31;
|
||||
cpsr().z = source == 0;
|
||||
cpsr().c = carryout();
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
uint32 ARM::ror(uint32 source, uint32 shift) {
|
||||
while(shift--) {
|
||||
carryout() = source & 1;
|
||||
source = (source << 31) | (source >> 1);
|
||||
}
|
||||
|
||||
if(cpsr().t) {
|
||||
cpsr().n = source >> 31;
|
||||
cpsr().z = source == 0;
|
||||
cpsr().c = carryout();
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
uint32 ARM::rrx(uint32 source) {
|
||||
carryout() = source & 1;
|
||||
source = (cpsr().c << 31) | (source >> 1);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ void ARM::power() {
|
|||
processor.power();
|
||||
vector(0x00000000, Processor::Mode::SVC);
|
||||
pipeline.reload = true;
|
||||
exception = false;
|
||||
crash = false;
|
||||
r(15).modify = [&] {
|
||||
pipeline.reload = true;
|
||||
r(15).data &= cpsr().t ? ~1 : ~3;
|
||||
|
@ -23,6 +23,15 @@ void ARM::power() {
|
|||
instructions = 0;
|
||||
}
|
||||
|
||||
void ARM::exec() {
|
||||
if(processor.irqline && cpsr().i == 0) {
|
||||
vector(0x00000018, Processor::Mode::IRQ);
|
||||
r(14) += 4;
|
||||
}
|
||||
|
||||
cpsr().t ? thumb_step() : arm_step();
|
||||
}
|
||||
|
||||
void ARM::vector(uint32 addr, Processor::Mode mode) {
|
||||
auto psr = cpsr();
|
||||
processor.setMode(mode);
|
||||
|
|
|
@ -16,8 +16,19 @@ struct ARM {
|
|||
virtual void bus_write(uint32 addr, uint32 size, uint32 word) = 0;
|
||||
|
||||
void power();
|
||||
void exec();
|
||||
void vector(uint32 addr, Processor::Mode mode);
|
||||
|
||||
bool condition(uint4 condition);
|
||||
uint32 bit(uint32 result);
|
||||
uint32 add(uint32 source, uint32 modify, bool carry);
|
||||
uint32 sub(uint32 source, uint32 modify, bool carry);
|
||||
uint32 mul(uint32 product, uint32 multiplicand, uint32 multiplier);
|
||||
uint32 lsl(uint32 source, uint32 shift);
|
||||
uint32 lsr(uint32 source, uint32 shift);
|
||||
uint32 asr(uint32 source, uint32 shift);
|
||||
uint32 ror(uint32 source, uint32 shift);
|
||||
uint32 rrx(uint32 source);
|
||||
|
||||
void serialize(serializer&);
|
||||
|
||||
|
|
|
@ -746,12 +746,14 @@ string ARM::disassemble_registers() {
|
|||
string output;
|
||||
output.append( "r0:", hex<8>(r( 0)), " r1:", hex<8>(r( 1)), " r2:", hex<8>(r( 2)), " r3:", hex<8>(r( 3)), " ");
|
||||
output.append( "r4:", hex<8>(r( 4)), " r5:", hex<8>(r( 5)), " r6:", hex<8>(r( 6)), " r7:", hex<8>(r( 7)), " ");
|
||||
output.append("cpsr:", cpsr().n ? "N" : "n", cpsr().z ? "Z" : "z", cpsr().c ? "C" : "c", cpsr().v ? "V" : "v", "\n");
|
||||
output.append("cpsr:", cpsr().n ? "N" : "n", cpsr().z ? "Z" : "z", cpsr().c ? "C" : "c", cpsr().v ? "V" : "v");
|
||||
output.append("/", hex<2>(cpsr().m), "\n");
|
||||
output.append( "r8:", hex<8>(r( 8)), " r9:", hex<8>(r( 9)), " r10:", hex<8>(r(10)), " r11:", hex<8>(r(11)), " ");
|
||||
output.append("r12:", hex<8>(r(12)), " sp:", hex<8>(r(13)), " lr:", hex<8>(r(14)), " pc:", hex<8>(r(15)), " ");
|
||||
output.append("spsr:");
|
||||
if(mode() == Processor::Mode::USR || mode() == Processor::Mode::SYS) { output.append("----"); return output; }
|
||||
if(mode() == Processor::Mode::USR || mode() == Processor::Mode::SYS) { output.append("----/--"); return output; }
|
||||
output.append( spsr().n ? "N" : "n", spsr().z ? "Z" : "z", spsr().c ? "C" : "c", spsr().v ? "V" : "v");
|
||||
output.append("/", hex<2>(spsr().m));
|
||||
return output;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,18 +7,11 @@ void ARM::arm_step() {
|
|||
pipeline.fetch.address = r(15);
|
||||
pipeline.fetch.instruction = bus_read(r(15), Word);
|
||||
|
||||
r(15).data += 4;
|
||||
pipeline.decode = pipeline.fetch;
|
||||
pipeline.fetch.address = r(15);
|
||||
pipeline.fetch.instruction = bus_read(r(15), Word);
|
||||
pipeline_step();
|
||||
step(2);
|
||||
}
|
||||
|
||||
r(15).data += 4;
|
||||
pipeline.execute = pipeline.decode;
|
||||
pipeline.decode = pipeline.fetch;
|
||||
pipeline.fetch.address = r(15);
|
||||
pipeline.fetch.instruction = bus_read(r(15), Word);
|
||||
pipeline_step();
|
||||
step(2);
|
||||
|
||||
instructions++;
|
||||
|
@ -34,21 +27,19 @@ void ARM::arm_step() {
|
|||
== std::integral_constant<uint32, bit::test(pattern)>::value \
|
||||
) return arm_op_ ## execute()
|
||||
|
||||
decode("???? 0001 0010 ++++ ++++ ++++ 0001 ????", branch_exchange_register);
|
||||
decode("???? 0000 00?? ???? ???? ???? 1001 ????", multiply);
|
||||
decode("???? 0001 0?00 ++++ ???? ---- 0000 ----", move_to_register_from_status);
|
||||
decode("???? 0001 0?00 ???? ???? ---- 1001 ????", memory_swap);
|
||||
decode("???? 000? ?0?? ???? ???? ---- 1011 ????", move_half_register);
|
||||
decode("???? 000? ?1?? ???? ???? ???? 1011 ????", move_half_immediate);
|
||||
decode("???? 0001 0?10 ???? ++++ ---- 0000 ????", move_to_status_from_register);
|
||||
decode("???? 0011 0?10 ???? ++++ ???? ???? ????", move_to_status_from_immediate);
|
||||
decode("???? 000? ?0?1 ???? ???? ---- 11?1 ????", load_register);
|
||||
decode("???? 000? ?1?1 ???? ???? ???? 11?1 ????", load_immediate);
|
||||
|
||||
decode("???? 0001 0?00 ++++ ???? ---- 0000 ----", move_to_register_from_status);
|
||||
decode("???? 0001 0?10 ???? ++++ ---- 0000 ????", move_to_status_from_register);
|
||||
decode("???? 0001 0010 ++++ ++++ ++++ 0001 ????", branch_exchange_register);
|
||||
|
||||
decode("???? 000? ?0?? ???? ???? ---- 1011 ????", move_half_register);
|
||||
decode("???? 000? ?1?? ???? ???? ???? 1011 ????", move_half_immediate);
|
||||
decode("???? 000? ???? ???? ???? ???? ???0 ????", data_immediate_shift);
|
||||
decode("???? 000? ???? ???? ???? ???? 0??1 ????", data_register_shift);
|
||||
decode("???? 001? ???? ???? ???? ???? ???? ????", data_immediate);
|
||||
decode("???? 0011 0?10 ???? ++++ ???? ???? ????", move_to_status_from_immediate);
|
||||
decode("???? 010? ???? ???? ???? ???? ???? ????", move_immediate_offset);
|
||||
decode("???? 011? ???? ???? ???? ???? ???0 ????", move_register_offset);
|
||||
decode("???? 100? ???? ???? ???? ???? ???? ????", move_multiple);
|
||||
|
@ -57,7 +48,7 @@ void ARM::arm_step() {
|
|||
|
||||
#undef decode
|
||||
|
||||
exception = true;
|
||||
crash = true;
|
||||
}
|
||||
|
||||
void ARM::arm_opcode(uint32 rm) {
|
||||
|
@ -68,44 +59,28 @@ void ARM::arm_opcode(uint32 rm) {
|
|||
|
||||
uint32 rn = r(n);
|
||||
|
||||
auto test = [&](uint32 result) {
|
||||
if(save) {
|
||||
cpsr().n = result >> 31;
|
||||
cpsr().z = result == 0;
|
||||
cpsr().c = carryout();
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
auto math = [&](uint32 source, uint32 modify, bool carry) {
|
||||
uint32 result = source + modify + carry;
|
||||
if(save) {
|
||||
uint32 overflow = ~(source ^ modify) & (source ^ result);
|
||||
cpsr().n = result >> 31;
|
||||
cpsr().z = result == 0;
|
||||
cpsr().c = (1u << 31) & (overflow ^ source ^ modify ^ result);
|
||||
cpsr().v = (1u << 31) & (overflow);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
switch(opcode) {
|
||||
case 0: r(d) = test(rn & rm); break; //AND
|
||||
case 1: r(d) = test(rn ^ rm); break; //EOR
|
||||
case 2: r(d) = math(rn, ~rm, 1); break; //SUB
|
||||
case 3: r(d) = math(rm, ~rn, 1); break; //RSB
|
||||
case 4: r(d) = math(rn, rm, 0); break; //ADD
|
||||
case 5: r(d) = math(rn, rm, cpsr().c); break; //ADC
|
||||
case 6: r(d) = math(rn, ~rm, cpsr().c); break; //SBC
|
||||
case 7: r(d) = math(rm, ~rn, cpsr().c); break; //RSC
|
||||
case 8: test(rn & rm); break; //TST
|
||||
case 9: test(rn ^ rm); break; //TEQ
|
||||
case 10: math(rn, ~rm, 1); break; //CMP
|
||||
case 11: math(rn, rm, 0); break; //CMN
|
||||
case 12: r(d) = test(rn | rm); break; //ORR
|
||||
case 13: r(d) = test(rm); break; //MOV
|
||||
case 14: r(d) = test(rn &~rm); break; //BIC
|
||||
case 15: r(d) = test(~rm); break; //MVN
|
||||
case 0: r(d) = bit(rn & rm); break; //AND
|
||||
case 1: r(d) = bit(rn ^ rm); break; //EOR
|
||||
case 2: r(d) = sub(rn, rm, 1); break; //SUB
|
||||
case 3: r(d) = sub(rm, rn, 1); break; //RSB
|
||||
case 4: r(d) = add(rn, rm, 0); break; //ADD
|
||||
case 5: r(d) = add(rn, rm, cpsr().c); break; //ADC
|
||||
case 6: r(d) = sub(rn, rm, cpsr().c); break; //SBC
|
||||
case 7: r(d) = sub(rm, rn, cpsr().c); break; //RSC
|
||||
case 8: bit(rn & rm); break; //TST
|
||||
case 9: bit(rn ^ rm); break; //TEQ
|
||||
case 10: sub(rn, rm, 1); break; //CMP
|
||||
case 11: add(rn, rm, 0); break; //CMN
|
||||
case 12: r(d) = bit(rn | rm); break; //ORR
|
||||
case 13: r(d) = bit(rm); break; //MOV
|
||||
case 14: r(d) = bit(rn & ~rm); break; //BIC
|
||||
case 15: r(d) = bit(~rm); break; //MVN
|
||||
}
|
||||
|
||||
if(exceptionmode() && d == 15 && save) {
|
||||
cpsr() = spsr();
|
||||
processor.setMode((Processor::Mode)cpsr().m);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +96,7 @@ void ARM::arm_move_to_status(uint32 rm) {
|
|||
PSR &psr = source ? spsr() : cpsr();
|
||||
|
||||
if(field & 1) {
|
||||
if(source == 1 || (Processor::Mode)cpsr().m != Processor::Mode::USR) {
|
||||
if(source == 1 || privilegedmode()) {
|
||||
psr.i = rm & 0x00000080;
|
||||
psr.f = rm & 0x00000040;
|
||||
psr.t = rm & 0x00000020;
|
||||
|
@ -138,45 +113,6 @@ void ARM::arm_move_to_status(uint32 rm) {
|
|||
}
|
||||
}
|
||||
|
||||
//logical shift left
|
||||
void ARM::lsl(bool &c, uint32 &rm, uint32 rs) {
|
||||
while(rs--) {
|
||||
c = rm >> 31;
|
||||
rm <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//logical shift right
|
||||
void ARM::lsr(bool &c, uint32 &rm, uint32 rs) {
|
||||
while(rs--) {
|
||||
c = rm & 1;
|
||||
rm >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
//arithmetic shift right
|
||||
void ARM::asr(bool &c, uint32 &rm, uint32 rs) {
|
||||
while(rs--) {
|
||||
c = rm & 1;
|
||||
rm = (int32)rm >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
//rotate right
|
||||
void ARM::ror(bool &c, uint32 &rm, uint32 rs) {
|
||||
while(rs--) {
|
||||
c = rm & 1;
|
||||
rm = (rm << 31) | (rm >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
//rotate right with extend
|
||||
void ARM::rrx(bool &c, uint32 &rm) {
|
||||
bool carry = c;
|
||||
c = rm & 1;
|
||||
rm = (carry << 31) | (rm >> 1);
|
||||
}
|
||||
|
||||
//mul{condition}{s} rd,rm,rs
|
||||
//mla{condition}{s} rd,rm,rs,rn
|
||||
//cccc 0000 00as dddd nnnn ssss 1001 mmmm
|
||||
|
@ -189,42 +125,14 @@ void ARM::rrx(bool &c, uint32 &rm) {
|
|||
//n = rm
|
||||
void ARM::arm_op_multiply() {
|
||||
uint1 accumulate = instruction() >> 21;
|
||||
uint1 save = instruction() >> 20;
|
||||
uint4 d = instruction() >> 16;
|
||||
uint4 n = instruction() >> 12;
|
||||
uint4 s = instruction() >> 8;
|
||||
uint4 m = instruction() >> 0;
|
||||
|
||||
auto &rd = r(d);
|
||||
uint32 rs = r(s);
|
||||
auto &rm = r(m);
|
||||
|
||||
rd = accumulate ? r(n) : 0u;
|
||||
r(d) = accumulate ? r(n) : 0u;
|
||||
step(1);
|
||||
|
||||
//Modified Booth Encoding
|
||||
bool carry = 0;
|
||||
unsigned place = 0;
|
||||
|
||||
do {
|
||||
step(1);
|
||||
signed factor = (int2)rs + carry;
|
||||
|
||||
if(factor == -2) rd -= rm << (place + 1);
|
||||
if(factor == -1) rd -= rm << (place + 0);
|
||||
if(factor == +1) rd += rm << (place + 0);
|
||||
if(factor == +2) rd += rm << (place + 1);
|
||||
|
||||
carry = rs & 2;
|
||||
place += 2;
|
||||
rs >>= 2;
|
||||
} while(rs + carry && place < 32);
|
||||
|
||||
if(save) {
|
||||
cpsr().n = r(d) >> 31;
|
||||
cpsr().z = r(d) == 0;
|
||||
cpsr().c = carry;
|
||||
}
|
||||
r(d) = mul(r(d), r(m), r(s));
|
||||
}
|
||||
|
||||
//swp{condition}{b} rd,rm,[rn]
|
||||
|
@ -269,8 +177,8 @@ void ARM::arm_op_move_half_register() {
|
|||
uint32 rm = r(m);
|
||||
|
||||
if(pre == 1) rn = up ? rn + rm : rn - rm;
|
||||
if(load == 1) r(d) = bus_read(rn, Word);
|
||||
if(load == 0) bus_write(rn, Word, r(d));
|
||||
if(load == 1) r(d) = bus_read(rn, Half);
|
||||
if(load == 0) bus_write(rn, Half, r(d));
|
||||
if(pre == 0) rn = up ? rn + rm : rn - rm;
|
||||
|
||||
if(pre == 0 || writeback == 1) r(n) = rn;
|
||||
|
@ -302,8 +210,8 @@ void ARM::arm_op_move_half_immediate() {
|
|||
uint8 immediate = (ih << 4) + (il << 0);
|
||||
|
||||
if(pre == 1) rn = up ? rn + immediate : rn - immediate;
|
||||
if(load == 1) r(d) = bus_read(rn, Word);
|
||||
if(load == 0) bus_write(rn, Word, r(d));
|
||||
if(load == 1) r(d) = bus_read(rn, Half);
|
||||
if(load == 0) bus_write(rn, Half, r(d));
|
||||
if(pre == 0) rn = up ? rn + immediate : rn - immediate;
|
||||
|
||||
if(pre == 0 || writeback == 1) r(n) = rn;
|
||||
|
@ -335,7 +243,7 @@ void ARM::arm_op_load_register() {
|
|||
if(pre == 1) rn = up ? rn + rm : rn - rm;
|
||||
uint32 word = bus_read(rn, half ? Half : Byte);
|
||||
r(d) = half ? (int16)word : (int8)word;
|
||||
if(pre == 0) rm = up ? rn + rm : rn - rm;
|
||||
if(pre == 0) rn = up ? rn + rm : rn - rm;
|
||||
|
||||
if(pre == 0 || writeback == 1) r(n) = rn;
|
||||
}
|
||||
|
@ -425,8 +333,7 @@ void ARM::arm_op_move_to_status_from_immediate() {
|
|||
uint8 immediate = instruction();
|
||||
|
||||
uint32 rm = immediate;
|
||||
bool c = cpsr().c;
|
||||
if(rotate) ror(c, rm, 2 * rotate);
|
||||
if(rotate) rm = ror(rm, 2 * rotate);
|
||||
|
||||
arm_move_to_status(rm);
|
||||
}
|
||||
|
@ -451,14 +358,12 @@ void ARM::arm_op_data_immediate_shift() {
|
|||
|
||||
uint32 rs = shift;
|
||||
uint32 rm = r(m);
|
||||
bool c = cpsr().c;
|
||||
|
||||
if(mode == 0) lsl(c, rm, rs);
|
||||
if(mode == 1) lsr(c, rm, rs ? rs : 32);
|
||||
if(mode == 2) asr(c, rm, rs ? rs : 32);
|
||||
if(mode == 3) rs ? ror(c, rm, rs) : rrx(c, rm);
|
||||
if(mode == 0) rm = lsl(rm, rs);
|
||||
if(mode == 1) rm = lsr(rm, rs ? rs : 32);
|
||||
if(mode == 2) rm = asr(rm, rs ? rs : 32);
|
||||
if(mode == 3) rm = rs ? ror(rm, rs) : rrx(rm);
|
||||
|
||||
carryout() = c;
|
||||
arm_opcode(rm);
|
||||
}
|
||||
|
||||
|
@ -482,14 +387,12 @@ void ARM::arm_op_data_register_shift() {
|
|||
|
||||
uint8 rs = r(s);
|
||||
uint32 rm = r(m);
|
||||
bool c = cpsr().c;
|
||||
|
||||
if(mode == 0) lsl(c, rm, rs < 33 ? rs : 33);
|
||||
if(mode == 1) lsr(c, rm, rs < 33 ? rs : 33);
|
||||
if(mode == 2) asr(c, rm, rs < 32 ? rs : 32);
|
||||
if(mode == 3 && rs) ror(c, rm, rs & 31 == 0 ? 32 : rs & 31);
|
||||
if(mode == 0 ) rm = lsl(rm, rs < 33 ? rs : 33);
|
||||
if(mode == 1 ) rm = lsr(rm, rs < 33 ? rs : 33);
|
||||
if(mode == 2 ) rm = asr(rm, rs < 32 ? rs : 32);
|
||||
if(mode == 3 && rs) rm = ror(rm, rs & 31 == 0 ? 32 : rs & 31);
|
||||
|
||||
carryout() = c;
|
||||
arm_opcode(rm);
|
||||
}
|
||||
|
||||
|
@ -584,10 +487,10 @@ void ARM::arm_op_move_register_offset() {
|
|||
uint32 rm = r(m);
|
||||
bool c = cpsr().c;
|
||||
|
||||
if(mode == 0) lsl(c, rm, rs);
|
||||
if(mode == 1) lsr(c, rm, rs ? rs : 32);
|
||||
if(mode == 2) asr(c, rm, rs ? rs : 32);
|
||||
if(mode == 3) rs ? ror(c, rm, rs) : rrx(c, rm);
|
||||
if(mode == 0) rm = lsl(rm, rs);
|
||||
if(mode == 1) rm = lsr(rm, rs ? rs : 32);
|
||||
if(mode == 2) rm = asr(rm, rs ? rs : 32);
|
||||
if(mode == 3) rm = rs ? ror(rm, rs) : rrx(rm);
|
||||
|
||||
if(pre == 1) rn = up ? rn + rm : rn - rm;
|
||||
if(load) {
|
||||
|
|
|
@ -1,15 +1,8 @@
|
|||
void arm_step();
|
||||
|
||||
bool arm_condition();
|
||||
void arm_opcode(uint32 rm);
|
||||
void arm_move_to_status(uint32 rm);
|
||||
|
||||
void lsl(bool &c, uint32 &rm, uint32 rs);
|
||||
void lsr(bool &c, uint32 &rm, uint32 rs);
|
||||
void asr(bool &c, uint32 &rm, uint32 rs);
|
||||
void ror(bool &c, uint32 &rm, uint32 rs);
|
||||
void rrx(bool &c, uint32 &rm);
|
||||
|
||||
void arm_op_multiply();
|
||||
void arm_op_memory_swap();
|
||||
void arm_op_move_half_register();
|
||||
|
|
|
@ -7,18 +7,11 @@ void ARM::thumb_step() {
|
|||
pipeline.fetch.address = r(15);
|
||||
pipeline.fetch.instruction = bus_read(r(15), Half);
|
||||
|
||||
r(15).data += 2;
|
||||
pipeline.decode = pipeline.fetch;
|
||||
pipeline.fetch.address = r(15);
|
||||
pipeline.fetch.instruction = bus_read(r(15), Half);
|
||||
pipeline_step();
|
||||
step(1);
|
||||
}
|
||||
|
||||
r(15).data += 2;
|
||||
pipeline.execute = pipeline.decode;
|
||||
pipeline.decode = pipeline.fetch;
|
||||
pipeline.fetch.address = r(15);
|
||||
pipeline.fetch.instruction = bus_read(r(15), Half);
|
||||
pipeline_step();
|
||||
step(1);
|
||||
|
||||
instructions++;
|
||||
|
@ -57,98 +50,30 @@ void ARM::thumb_step() {
|
|||
|
||||
#undef decode
|
||||
|
||||
exception = true;
|
||||
crash = true;
|
||||
}
|
||||
|
||||
void ARM::thumb_opcode(uint4 opcode, uint4 d, uint4 m) {
|
||||
switch(opcode) {
|
||||
case 0: r(d) = thumb_tst(r(d) & r(m)); break; //AND
|
||||
case 1: r(d) = thumb_tst(r(d) ^ r(m)); break; //EOR
|
||||
case 2: r(d) = thumb_lsl(r(d), r(m) & 0xff); break; //LSL
|
||||
case 3: r(d) = thumb_lsr(r(d), r(m) & 0xff); break; //LSR
|
||||
case 4: r(d) = thumb_asr(r(d), r(m) & 0xff); break; //ASR
|
||||
case 5: r(d) = thumb_add(r(d), r(m), cpsr().c); break; //ADC
|
||||
case 6: r(d) = thumb_sub(r(d), r(m), cpsr().c); break; //SBC
|
||||
case 7: r(d) = thumb_ror(r(d), r(m) & 0xff); break; //ROR
|
||||
case 8: thumb_tst(r(d) & r(m)); break; //TST
|
||||
case 9: r(d) = thumb_sub(0, r(m)); break; //NEG
|
||||
case 10: thumb_sub(r(d), r(m)); break; //CMP
|
||||
case 11: thumb_add(r(d), r(m)); break; //CMN
|
||||
case 12: r(d) = thumb_tst(r(d) | r(m)); break; //ORR
|
||||
case 13: r(d) = thumb_mul(r(d), r(m)); break; //MUL
|
||||
case 14: r(d) = thumb_tst(r(d) & ~r(m)); break; //BIC
|
||||
case 15: r(d) = thumb_tst(~r(m)); break; //MVN
|
||||
case 0: r(d) = bit(r(d) & r(m)); break; //AND
|
||||
case 1: r(d) = bit(r(d) ^ r(m)); break; //EOR
|
||||
case 2: r(d) = lsl(r(d), r(m) & 0xff); break; //LSL
|
||||
case 3: r(d) = lsr(r(d), r(m) & 0xff); break; //LSR
|
||||
case 4: r(d) = asr(r(d), r(m) & 0xff); break; //ASR
|
||||
case 5: r(d) = add(r(d), r(m), cpsr().c); break; //ADC
|
||||
case 6: r(d) = sub(r(d), r(m), cpsr().c); break; //SBC
|
||||
case 7: r(d) = ror(r(d), r(m) & 0xff); break; //ROR
|
||||
case 8: bit(r(d) & r(m)); break; //TST
|
||||
case 9: r(d) = sub(0, r(m), 1); break; //NEG
|
||||
case 10: sub(r(d), r(m), 1); break; //CMP
|
||||
case 11: add(r(d), r(m), 0); break; //CMN
|
||||
case 12: r(d) = bit(r(d) | r(m)); break; //ORR
|
||||
case 13: r(d) = mul(0, r(d), r(m)); break; //MUL
|
||||
case 14: r(d) = bit(r(d) & ~r(m)); break; //BIC
|
||||
case 15: r(d) = bit(~r(m)); break; //MVN
|
||||
}
|
||||
}
|
||||
|
||||
uint32 ARM::thumb_tst(uint32 modify) {
|
||||
cpsr().n = modify >> 31;
|
||||
cpsr().z = modify == 0;
|
||||
return modify;
|
||||
}
|
||||
|
||||
uint32 ARM::thumb_add(uint32 source, uint32 modify, bool carry) {
|
||||
uint32 result = source + modify + carry;
|
||||
uint32 overflow = ~(source ^ modify) & (source ^ result);
|
||||
cpsr().n = result >> 31;
|
||||
cpsr().z = result == 0;
|
||||
cpsr().c = (1u << 31) & (overflow ^ source ^ modify ^ result);
|
||||
cpsr().v = (1u << 31) & (overflow);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32 ARM::thumb_sub(uint32 source, uint32 modify, bool carry) {
|
||||
thumb_add(source, ~modify, carry);
|
||||
}
|
||||
|
||||
uint32 ARM::thumb_lsl(uint32 source, uint32 modify) {
|
||||
while(modify--) {
|
||||
cpsr().c = source >> 31;
|
||||
source <<= 1;
|
||||
}
|
||||
cpsr().n = source >> 31;
|
||||
cpsr().z = source == 0;
|
||||
return source;
|
||||
}
|
||||
|
||||
uint32 ARM::thumb_lsr(uint32 source, uint32 modify) {
|
||||
while(modify--) {
|
||||
cpsr().c = source & 1;
|
||||
source >>= 1;
|
||||
}
|
||||
cpsr().n = source >> 31;
|
||||
cpsr().z = source == 0;
|
||||
return source;
|
||||
}
|
||||
|
||||
uint32 ARM::thumb_asr(uint32 source, uint32 modify) {
|
||||
while(modify--) {
|
||||
cpsr().c = source & 1;
|
||||
source = (int32)source >> 1;
|
||||
}
|
||||
cpsr().n = source >> 31;
|
||||
cpsr().z = source == 0;
|
||||
return source;
|
||||
}
|
||||
|
||||
uint32 ARM::thumb_ror(uint32 source, uint32 modify) {
|
||||
while(modify--) {
|
||||
cpsr().c = source & 1;
|
||||
source = (source << 31) | (source >> 1);
|
||||
}
|
||||
cpsr().n = source >> 31;
|
||||
cpsr().z = source == 0;
|
||||
return source;
|
||||
}
|
||||
|
||||
uint32 ARM::thumb_mul(uint32 source, uint32 modify) {
|
||||
source = source * modify;
|
||||
cpsr().n = source >> 31;
|
||||
cpsr().z = source == 0;
|
||||
cpsr().c = 0;
|
||||
return source;
|
||||
}
|
||||
|
||||
//(add,sub) rd,rn,rm
|
||||
//0001 10om mmnn nddd
|
||||
//o = opcode
|
||||
|
@ -162,8 +87,8 @@ void ARM::thumb_op_adjust_register() {
|
|||
uint3 d = instruction() >> 0;
|
||||
|
||||
switch(opcode) {
|
||||
case 0: r(d) = thumb_add(r(n), r(m)); break;
|
||||
case 1: r(d) = thumb_sub(r(n), r(m)); break;
|
||||
case 0: r(d) = add(r(n), r(m), 0); break;
|
||||
case 1: r(d) = sub(r(n), r(m), 1); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,8 +105,8 @@ void ARM::thumb_op_adjust_immediate() {
|
|||
uint3 d = instruction() >> 0;
|
||||
|
||||
switch(opcode) {
|
||||
case 0: r(d) = thumb_add(r(n), immediate); break;
|
||||
case 1: r(d) = thumb_sub(r(n), immediate); break;
|
||||
case 0: r(d) = add(r(n), immediate, 0); break;
|
||||
case 1: r(d) = sub(r(n), immediate, 1); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,9 +123,9 @@ void ARM::thumb_op_shift_immediate() {
|
|||
uint3 d = instruction() >> 0;
|
||||
|
||||
switch(opcode) {
|
||||
case 0: r(d) = thumb_lsl(r(m), immediate); break;
|
||||
case 1: r(d) = thumb_lsr(r(m), immediate); break;
|
||||
case 2: r(d) = thumb_asr(r(m), immediate); break;
|
||||
case 0: r(d) = lsl(r(m), immediate); break;
|
||||
case 1: r(d) = lsr(r(m), immediate); break;
|
||||
case 2: r(d) = asr(r(m), immediate); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,10 +140,10 @@ void ARM::thumb_op_immediate() {
|
|||
uint8 immediate = instruction();
|
||||
|
||||
switch(opcode) {
|
||||
case 0: r(d) = thumb_tst( immediate); break;
|
||||
case 1: thumb_sub(r(d), immediate); break;
|
||||
case 2: r(d) = thumb_add(r(d), immediate); break;
|
||||
case 3: r(d) = thumb_sub(r(d), immediate); break;
|
||||
case 0: r(d) = bit( immediate ); break;
|
||||
case 1: sub(r(d), immediate, 1); break;
|
||||
case 2: r(d) = add(r(d), immediate, 0); break;
|
||||
case 3: r(d) = sub(r(d), immediate, 1); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,9 +183,9 @@ void ARM::thumb_op_alu_hi() {
|
|||
|
||||
uint4 d = (dh << 3) + (dl << 0);
|
||||
switch(opcode) {
|
||||
case 0: r(d) = thumb_add(r(d), r(m)); break; //ADD
|
||||
case 1: thumb_sub(r(d), r(m)); break; //SUB
|
||||
case 2: r(d) = thumb_tst( r(m)); break; //MOV
|
||||
case 0: r(d) = r(d) + r(m); break; //ADD (does not modify flags)
|
||||
case 1: sub(r(d), r(m), 1); break; //SUB
|
||||
case 2: r(d) = r(m); break; //MOV (does not modify flags)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,7 +238,7 @@ void ARM::thumb_op_move_word_immediate() {
|
|||
uint3 d = instruction() >> 0;
|
||||
|
||||
if(load == 1) r(d) = bus_read(r(n) + offset * 4, Word);
|
||||
if(load == 0) bus_write(r(d) + offset * 4, Word, r(n));
|
||||
if(load == 0) bus_write(r(n) + offset * 4, Word, r(d));
|
||||
}
|
||||
|
||||
//(ldr,str)b rd,[rn,#offset]
|
||||
|
@ -326,10 +251,10 @@ void ARM::thumb_op_move_byte_immediate() {
|
|||
uint1 load = instruction() >> 11;
|
||||
uint5 offset = instruction() >> 6;
|
||||
uint3 n = instruction() >> 3;
|
||||
uint4 d = instruction() >> 0;
|
||||
uint3 d = instruction() >> 0;
|
||||
|
||||
if(load == 1) r(d) = bus_read(r(n) + offset, Byte);
|
||||
if(load == 0) bus_write(r(d) + offset, Byte, r(n));
|
||||
if(load == 0) bus_write(r(n) + offset, Byte, r(d));
|
||||
}
|
||||
|
||||
//(ldr,str)h rd,[rn,#offset]
|
||||
|
@ -345,21 +270,21 @@ void ARM::thumb_op_move_half_immediate() {
|
|||
uint3 d = instruction() >> 0;
|
||||
|
||||
if(load == 1) r(d) = bus_read(r(n) + offset * 2, Half);
|
||||
if(load == 0) bus_write(r(d) + offset * 2, Half, r(n));
|
||||
if(load == 0) bus_write(r(n) + offset * 2, Half, r(d));
|
||||
}
|
||||
|
||||
//(ldr,str) rd,[sp,#relative]
|
||||
//1001 oddd rrrr rrrr
|
||||
//(ldr,str) rd,[sp,#immediate]
|
||||
//1001 oddd iiii iiii
|
||||
//o = opcode
|
||||
//d = rd
|
||||
//r = relative
|
||||
//i = immediate
|
||||
void ARM::thumb_op_move_stack() {
|
||||
uint1 opcode = instruction() >> 11;
|
||||
uint3 d = instruction() >> 8;
|
||||
int8 relative = instruction();
|
||||
uint8 immediate = instruction();
|
||||
|
||||
if(opcode == 0) bus_write(r(13) + relative * 4, Word, r(d));
|
||||
if(opcode == 1) r(d) = bus_read(r(13) + relative * 4, Word);
|
||||
if(opcode == 0) bus_write(r(13) + immediate * 4, Word, r(d));
|
||||
if(opcode == 1) r(d) = bus_read(r(13) + immediate * 4, Word);
|
||||
}
|
||||
|
||||
//add rd,{pc,sp},#immediate
|
||||
|
|
|
@ -1,17 +1,7 @@
|
|||
void thumb_step();
|
||||
|
||||
bool thumb_condition(uint4 condition);
|
||||
void thumb_opcode(uint4 opcode, uint4 d, uint4 s);
|
||||
|
||||
uint32 thumb_tst(uint32 modify);
|
||||
uint32 thumb_add(uint32 source, uint32 modify, bool carry = 0);
|
||||
uint32 thumb_sub(uint32 source, uint32 modify, bool carry = 1);
|
||||
uint32 thumb_lsl(uint32 source, uint32 modify);
|
||||
uint32 thumb_lsr(uint32 source, uint32 modify);
|
||||
uint32 thumb_asr(uint32 source, uint32 modify);
|
||||
uint32 thumb_ror(uint32 source, uint32 modify);
|
||||
uint32 thumb_mul(uint32 source, uint32 modify);
|
||||
|
||||
void thumb_op_adjust_register();
|
||||
void thumb_op_adjust_immediate();
|
||||
void thumb_op_shift_immediate();
|
||||
|
|
|
@ -10,6 +10,9 @@ void ARM::Processor::power() {
|
|||
und.sp = und.lr = 0;
|
||||
pc = 0;
|
||||
|
||||
carryout = false;
|
||||
irqline = false;
|
||||
|
||||
cpsr = 0;
|
||||
spsr = nullptr;
|
||||
fiq.spsr = 0;
|
||||
|
@ -31,7 +34,7 @@ void ARM::Processor::power() {
|
|||
}
|
||||
|
||||
void ARM::Processor::setMode(Mode mode) {
|
||||
cpsr.m = (unsigned)mode;
|
||||
cpsr.m = 0x10 | (unsigned)mode;
|
||||
|
||||
if(mode == Mode::FIQ) {
|
||||
r[ 8] = &fiq.r8;
|
||||
|
@ -57,4 +60,19 @@ void ARM::Processor::setMode(Mode mode) {
|
|||
}
|
||||
}
|
||||
|
||||
void ARM::pipeline_step() {
|
||||
pipeline.execute = pipeline.decode;
|
||||
pipeline.decode = pipeline.fetch;
|
||||
|
||||
if(cpsr().t == 0) {
|
||||
r(15).data += 4;
|
||||
pipeline.fetch.address = r(15);
|
||||
pipeline.fetch.instruction = bus_read(r(15), Word);
|
||||
} else {
|
||||
r(15).data += 2;
|
||||
pipeline.fetch.address = r(15);
|
||||
pipeline.fetch.instruction = bus_read(r(15), Half);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -104,6 +104,7 @@ struct Processor {
|
|||
GPR pc;
|
||||
PSR cpsr;
|
||||
bool carryout;
|
||||
bool irqline;
|
||||
|
||||
GPR *r[16];
|
||||
PSR *spsr;
|
||||
|
@ -114,7 +115,9 @@ struct Processor {
|
|||
|
||||
Processor processor;
|
||||
Pipeline pipeline;
|
||||
bool exception;
|
||||
bool crash;
|
||||
|
||||
void pipeline_step();
|
||||
|
||||
alwaysinline GPR& r(unsigned n) { return *processor.r[n]; }
|
||||
alwaysinline PSR& cpsr() { return processor.cpsr; }
|
||||
|
@ -122,3 +125,5 @@ alwaysinline PSR& spsr() { return *processor.spsr; }
|
|||
alwaysinline bool& carryout() { return processor.carryout; }
|
||||
alwaysinline uint32 instruction() { return pipeline.execute.instruction; }
|
||||
alwaysinline Processor::Mode mode() { return (Processor::Mode)processor.cpsr.m; }
|
||||
alwaysinline bool privilegedmode() const { return (Processor::Mode)processor.cpsr.m != Processor::Mode::USR; }
|
||||
alwaysinline bool exceptionmode() const { return privilegedmode() && (Processor::Mode)processor.cpsr.m != Processor::Mode::SYS; }
|
||||
|
|
|
@ -27,7 +27,7 @@ void ArmDSP::enter() {
|
|||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
||||
if(exception) {
|
||||
if(crash) {
|
||||
print(disassemble_arm_instruction(pipeline.execute.address), "\n");
|
||||
print(disassemble_registers(), "\n");
|
||||
print("Executed: ", instructions, "\n");
|
||||
|
|
Loading…
Reference in New Issue