Update to v086r14 release.

byuu says:

Attempted to fix the bugs pointed out by Cydrak for the shifter carry
and subtraction flags. No way to know if I was successful.
The memory map should exactly match real hardware now.
Also simplified bus reading/writing: we can get fancy when it works,
I suppose.
Reduced some of the code repetition to try and minimize the chances for
bugs.
I hopefully fixed up register-based ror shifting to what the docs were
saying.
And lastly, the disassembler should handle every opcode in every mode
now.
ldr rn,[pc,n] adds (pc,n) [absolute address] after opcode. I didn't want
to actually read from ROM here (in case it ever touches I/O or
something), but I suppose we could try anyway.
At startup, it will write out "disassembly.txt" which is a disassembly
of the entire program ROM.
If anyone wants to look for disassembly errors, I'll go ahead and fix
them. Just note that I won't do common substitutions like mov pc,lr ==
ret.

At this point, we can make two moves and then the game tells us that
we've won.
So ... I'm back to thinking the problem is with bugs in the ARM core,
and that our bidirectional communication is strong enough to play the
game.
Although that's not perfect. The game definitely looks at d4 (and
possibly others later), but my hardware tests can't get anything but
d0/d3 set.
This commit is contained in:
Tim Allen 2012-03-01 23:23:05 +11:00
parent ad71e18e02
commit aa8ac7bbb8
10 changed files with 186 additions and 163 deletions

View File

@ -89,6 +89,6 @@ sync:
rm -r phoenix/test rm -r phoenix/test
archive-all: archive-all:
tar -cjf bsnes.tar.bz2 base data gameboy libco nall nes obj out phoenix ruby snes ui ui-debugger ui-libsnes Makefile cc.bat clean.bat tar -cjf bsnes.tar.bz2 base data gameboy libco nall nes obj out phoenix ruby snes ui ui-debugger ui-libsnes Makefile cc.bat purge.bat
help:; help:;

View File

@ -1,7 +1,7 @@
#ifndef BASE_HPP #ifndef BASE_HPP
#define BASE_HPP #define BASE_HPP
const char Version[] = "086.13"; const char Version[] = "086.14";
#include <nall/platform.hpp> #include <nall/platform.hpp>
#include <nall/algorithm.hpp> #include <nall/algorithm.hpp>

View File

@ -529,19 +529,10 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) {
if(has_st018) markup.append( if(has_st018) markup.append(
" <armdsp firmware='st0018.rom' sha256='6cceff3c6945bb2672040066d218efcd2f31492f3f5c28916c8e53435c2c887e'>\n" " <armdsp firmware='st0018.rom' sha256='6cceff3c6945bb2672040066d218efcd2f31492f3f5c28916c8e53435c2c887e'>\n"
" <map address='00-3f:3800-3805'/>\n"
" <map address='80-bf:3800-3805'/>\n"
" </armdsp>\n"
);
#if 0
if(has_st018) markup.append(
" <setarisc firmware='ST-0018'>\n"
" <map address='00-3f:3800-38ff'/>\n" " <map address='00-3f:3800-38ff'/>\n"
" <map address='80-bf:3800-38ff'/>\n" " <map address='80-bf:3800-38ff'/>\n"
" </setarisc>\n" " </armdsp>\n"
); );
#endif
markup.append("</cartridge>\n"); markup.append("</cartridge>\n");
} }

View File

@ -35,13 +35,13 @@ void ArmDSP::enter() {
if(pipeline.reload) { if(pipeline.reload) {
pipeline.reload = false; pipeline.reload = false;
pipeline.prefetch.address = r[15]; pipeline.prefetch.address = r[15];
pipeline.prefetch.opcode = bus_read<4>(r[15]); pipeline.prefetch.opcode = bus_readword(r[15]);
r[15].step(); r[15].step();
} }
pipeline.instruction = pipeline.prefetch; pipeline.instruction = pipeline.prefetch;
pipeline.prefetch.address = r[15]; pipeline.prefetch.address = r[15];
pipeline.prefetch.opcode = bus_read<4>(r[15]); pipeline.prefetch.opcode = bus_readword(r[15]);
r[15].step(); r[15].step();
//if(pipeline.instruction.address == 0x0000ef5c) trace = 1; //if(pipeline.instruction.address == 0x0000ef5c) trace = 1;
@ -68,11 +68,15 @@ void ArmDSP::enter() {
} }
} }
//MMIO: $00-3f|80-bf:3800-38ff
//3800-3807 mirrored throughout
//a0 ignored
uint8 ArmDSP::mmio_read(unsigned addr) { uint8 ArmDSP::mmio_read(unsigned addr) {
cpu.synchronize_coprocessors(); cpu.synchronize_coprocessors();
uint8 data = 0x00; uint8 data = 0x00;
addr &= 0xffff; addr &= 0xff06;
if(addr == 0x3800) { if(addr == 0x3800) {
if(bridge.armtocpu.ready) { if(bridge.armtocpu.ready) {
@ -104,7 +108,7 @@ void ArmDSP::mmio_write(unsigned addr, uint8 data) {
usleep(200000); usleep(200000);
} }
addr &= 0xffff; addr &= 0xff06;
if(addr == 0x3802) { if(addr == 0x3802) {
bridge.cputoarm.ready = true; bridge.cputoarm.ready = true;
@ -131,12 +135,21 @@ void ArmDSP::power() {
fp.read(dataROM, 32 * 1024); fp.read(dataROM, 32 * 1024);
fp.close(); fp.close();
} }
filename = { dir(filename), "disassembly.txt" };
fp.open(filename, file::mode::write);
for(unsigned n = 0; n < 128 * 1024; n += 4) {
fp.print(disassemble_opcode(n), "\n");
}
fp.close();
} }
void ArmDSP::reset() { void ArmDSP::reset() {
create(ArmDSP::Enter, 21477272); create(ArmDSP::Enter, 21477272);
for(auto &rd : r) rd = 0; for(auto &rd : r) rd = 0;
shiftercarry = 0;
exception = false; exception = false;
pipeline.reload = true; pipeline.reload = true;

View File

@ -42,8 +42,12 @@ struct ArmDSP : public Coprocessor {
//memory.cpp //memory.cpp
uint8 bus_iread(uint32 addr); uint8 bus_iread(uint32 addr);
void bus_iwrite(uint32 addr, uint8 data); void bus_iwrite(uint32 addr, uint8 data);
template<unsigned size> uint32 bus_read(uint32 addr);
template<unsigned size> void bus_write(uint32 addr, uint32 data); uint32 bus_readbyte(uint32 addr);
uint32 bus_readword(uint32 addr);
void bus_writebyte(uint32 addr, uint32 data);
void bus_writeword(uint32 addr, uint32 data);
//disassembler.cpp //disassembler.cpp
string disassemble_opcode(uint32 pc); string disassemble_opcode(uint32 pc);

View File

@ -12,10 +12,11 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
string output{hex<8>(pc), " "}; string output{hex<8>(pc), " "};
uint32 instruction = bus_read<4>(pc); uint32 instruction = bus_readword(pc);
output.append(hex<8>(instruction), " "); output.append(hex<8>(instruction), " ");
//multiply //multiply
//(mul,mla){condition}{s} rd,rm,rs,rn
if((instruction & 0x0fc000f0) == 0x00000090) { if((instruction & 0x0fc000f0) == 0x00000090) {
uint4 condition = instruction >> 28; uint4 condition = instruction >> 28;
uint1 accumulate = instruction >> 21; uint1 accumulate = instruction >> 21;
@ -33,6 +34,7 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
} }
//move to register from status register //move to register from status register
//mrs{condition} rd,(c,s)psr
if((instruction & 0x0fb000f0) == 0x01000000) { if((instruction & 0x0fb000f0) == 0x01000000) {
uint4 condition = instruction >> 28; uint4 condition = instruction >> 28;
uint1 psr = instruction >> 22; uint1 psr = instruction >> 22;
@ -45,6 +47,7 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
} }
//move to status register from register //move to status register from register
//msr{condition} (c,s)psr:{fields},rm
if((instruction & 0x0fb000f0) == 0x01200000) { if((instruction & 0x0fb000f0) == 0x01200000) {
uint4 condition = instruction >> 28; uint4 condition = instruction >> 28;
uint1 psr = instruction >> 22; uint1 psr = instruction >> 22;
@ -89,6 +92,34 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
return output; return output;
} }
//data register shift
//{opcode}{condition}{s} rd,rm {shift} rs
//{opcode}{condition} rn,rm {shift} rs
//{opcode}{condition}{s} rd,rn,rm {shift} rs
if((instruction & 0x0e000090) == 0x00000010) {
uint4 condition = instruction >> 28;
uint4 opcode = instruction >> 21;
uint1 save = instruction >> 20;
uint4 rn = instruction >> 16;
uint4 rd = instruction >> 12;
uint4 rs = instruction >> 8;
uint2 mode = instruction >> 5;
uint4 rm = instruction;
output.append(opcodes[opcode], conditions[condition]);
if(is_move(opcode)) output.append(save ? "s " : " ", registers[rd], ",");
if(is_comp(opcode)) output.append(registers[rn], ",");
if(is_math(opcode)) output.append(save ? "s " : " ", registers[rd], ",", registers[rn], ",");
output.append(registers[rm]);
if(mode == 0) output.append(" lsl ");
if(mode == 1) output.append(" lsr ");
if(mode == 2) output.append(" asr ");
if(mode == 3) output.append(" ror ");
output.append(registers[rs]);
return output;
}
//data immediate //data immediate
//{opcode}{condition}{s} rd,#immediate //{opcode}{condition}{s} rd,#immediate
//{opcode}{condition} rn,#immediate //{opcode}{condition} rn,#immediate
@ -113,21 +144,58 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
} }
//move immediate offset //move immediate offset
//(ldr,str){condition}{b} rd,[rn{+offset}] //(ldr,str){condition}{b} rd,[rn{,+/-offset}]{!}
//todo: support W flag //(ldr,str){condition}{b} rd,[rn]{,+/-offset}
if((instruction & 0x0e000000) == 0x04000000) { if((instruction & 0x0e000000) == 0x04000000) {
uint4 condition = instruction >> 28; uint4 condition = instruction >> 28;
uint1 p = instruction >> 24;
uint1 u = instruction >> 23; uint1 u = instruction >> 23;
uint1 b = instruction >> 22;
uint1 w = instruction >> 21;
uint1 load = instruction >> 20; uint1 load = instruction >> 20;
uint4 rn = instruction >> 16; uint4 rn = instruction >> 16;
uint4 rd = instruction >> 12; uint4 rd = instruction >> 12;
uint12 immediate = instruction; uint12 immediate = instruction;
output.append(load ? "ldr" : "str", conditions[condition]); output.append(load ? "ldr" : "str", conditions[condition], b ? "b " : " ");
if(instruction & 0x00400000) output.append("b"); output.append(registers[rd], ",[", registers[rn]);
output.append(" ", registers[rd], ",[", registers[rn]); if(p == 0) output.append("]");
if(immediate) output.append(u ? "+" : "-", "0x", hex<3>((uint12)instruction)); if(immediate) output.append(",", u ? "+" : "-", "0x", hex<3>(immediate));
output.append("]"); if(p == 1) output.append("]");
if(p == 1 && w == 1) output.append("!");
if(rn == 15) output.append(" (0x", hex<8>(pc + 8 + (u ? +immediate : -immediate)), ")");
return output;
}
//move register offset
//(ldr)(str){condition}{b} rd,[rn,rm {mode} #immediate]{!}
//(ldr)(str){condition}{b} rd,[rn],rm {mode} #immediate
if((instruction & 0x0e000010) == 0x06000000) {
uint4 condition = instruction >> 28;
uint1 p = instruction >> 24;
uint1 u = instruction >> 23;
uint1 b = instruction >> 22;
uint1 w = instruction >> 21;
uint1 load = instruction >> 20;
uint4 rn = instruction >> 16;
uint4 rd = instruction >> 12;
uint5 shift = instruction >> 7;
uint2 mode = instruction >> 5;
uint4 rm = instruction;
output.append(load ? "ldr" : "str", conditions[condition], b ? "b " : " ");
output.append(registers[rd], ",[", registers[rn]);
if(p == 0) output.append("]");
output.append(",", u ? "+" : "-", registers[rm]);
if(mode == 0 && shift != 0) output.append(" lsl #", shift);
if(mode == 1) output.append(" lsr #", shift == 0 ? 32u : (unsigned)shift);
if(mode == 2) output.append(" asr #", shift == 0 ? 32u : (unsigned)shift);
if(mode == 3 && shift != 0) output.append(" ror #", shift);
if(mode == 3 && shift == 0) output.append(" rrx");
if(p == 1) output.append("]");
if(p == 1 && w == 1) output.append("!");
return output; return output;
} }
@ -166,10 +234,12 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
string ArmDSP::disassemble_registers() { string ArmDSP::disassemble_registers() {
return { return {
"r0:", hex<8>(r[ 0]), " r1:", hex<8>(r[ 1]), " r2:", hex<8>(r[ 2]), " r3:", hex<8>(r[ 3]), "r0:", hex<8>(r[ 0]), " r1:", hex<8>(r[ 1]), " r2:", hex<8>(r[ 2]), " r3:", hex<8>(r[ 3]),
" r4:", hex<8>(r[ 4]), " r5:", hex<8>(r[ 5]), " r6:", hex<8>(r[ 6]), " r7:", hex<8>(r[ 7]), "\n", " r4:", hex<8>(r[ 4]), " r5:", hex<8>(r[ 5]), " r6:", hex<8>(r[ 6]), " r7:", hex<8>(r[ 7]), " ",
"cpsr:", cpsr.n ? "N" : "n", cpsr.z ? "Z" : "z", cpsr.c ? "C" : "c", cpsr.v ? "V" : "v", "\n",
"r8:", hex<8>(r[ 8]), " r9:", hex<8>(r[ 9]), " r10:", hex<8>(r[10]), " r11:", hex<8>(r[11]), "r8:", hex<8>(r[ 8]), " r9:", hex<8>(r[ 9]), " r10:", hex<8>(r[10]), " r11:", hex<8>(r[11]),
" r12:", hex<8>(r[12]), " r13:", hex<8>(r[13]), " r14:", hex<8>(r[14]), " r15:", hex<8>(r[15]), "\n", " r12:", hex<8>(r[12]), " r13:", hex<8>(r[13]), " r14:", hex<8>(r[14]), " r15:", hex<8>(r[15]), " ",
"cpsr:", cpsr.n ? "N" : "n", cpsr.z ? "Z" : "z", cpsr.c ? "C" : "c", cpsr.v ? "V" : "v" "spsr:", spsr.n ? "N" : "n", spsr.z ? "Z" : "z", spsr.c ? "C" : "c", spsr.v ? "V" : "v"
}; };
} }

View File

@ -58,61 +58,30 @@ void ArmDSP::bus_iwrite(uint32 addr, uint8 data) {
if((addr & 3) == 0) print("* ARM w", hex<8>(addr), " = ", hex<2>(data), "\n"); if((addr & 3) == 0) print("* ARM w", hex<8>(addr), " = ", hex<2>(data), "\n");
} }
template<unsigned size> uint32 ArmDSP::bus_readbyte(uint32 addr) {
uint32 ArmDSP::bus_read(uint32 addr) { return bus_iread(addr);
uint32 data = 0;
if(size == 1) {
uint32 mask = 255u << ((addr & ~3) << 3);
data |= bus_iread(addr) & mask;
} }
if(size == 4) { uint32 ArmDSP::bus_readword(uint32 addr) {
addr &= ~3; addr &= ~3;
data |= bus_iread(addr + 0) << 0; return (
data |= bus_iread(addr + 1) << 8; (bus_iread(addr + 0) << 0)
data |= bus_iread(addr + 2) << 16; | (bus_iread(addr + 1) << 8)
data |= bus_iread(addr + 3) << 24; | (bus_iread(addr + 2) << 16)
| (bus_iread(addr + 3) << 24)
);
} }
if(0&&addr >= 0x40000000 && addr <= 0x400000ff) { void ArmDSP::bus_writebyte(uint32 addr, uint32 data) {
if(addr != 0x40000020 || data != 0x80) return bus_iwrite(addr, data);
if(data) {
if(size == 1) print("* ARM r", hex<8>(addr), " = ", hex<2>(data), "\n");
if(size == 2) print("* ARM r", hex<8>(addr), " = ", hex<4>(data), "\n");
if(size == 4) print("* ARM r", hex<8>(addr), " = ", hex<8>(data), "\n");
usleep(20000);
}
} }
if(size == 1) return data & 0xff; void ArmDSP::bus_writeword(uint32 addr, uint32 data) {
if(size == 2) return data & 0xffff;
return data;
}
template<unsigned size>
void ArmDSP::bus_write(uint32 addr, uint32 data) {
if(0&&addr >= 0x40000000 && addr <= 0x400000ff) {
if(data) {
if(size == 1) print("* ARM w", hex<8>(addr), " = ", hex<2>(data), "\n");
if(size == 2) print("* ARM w", hex<8>(addr), " = ", hex<4>(data), "\n");
if(size == 4) print("* ARM w", hex<8>(addr), " = ", hex<8>(data), "\n");
usleep(20000);
}
}
if(size == 1) {
uint32 mask = 255u << ((addr & ~3) << 3);
bus_iwrite(addr, data);
}
if(size == 4) {
addr &= ~3; addr &= ~3;
bus_iwrite(addr + 0, data >> 0); bus_iwrite(addr + 0, data >> 0);
bus_iwrite(addr + 1, data >> 8); bus_iwrite(addr + 1, data >> 8);
bus_iwrite(addr + 2, data >> 16); bus_iwrite(addr + 2, data >> 16);
bus_iwrite(addr + 3, data >> 24); bus_iwrite(addr + 3, data >> 24);
} }
}
#endif #endif

View File

@ -29,56 +29,53 @@ bool ArmDSP::condition() {
//ro = modified target //ro = modified target
void ArmDSP::opcode(uint32 rm) { void ArmDSP::opcode(uint32 rm) {
uint4 opcode = instruction >> 21; uint4 opcode = instruction >> 21;
uint1 s = instruction >> 20; uint1 save = instruction >> 20;
uint4 n = instruction >> 16; uint4 n = instruction >> 16;
uint4 d = instruction >> 12; uint4 d = instruction >> 12;
uint32 rn = r[n]; uint32 rn = r[n];
auto &rd = r[d];
uint32 ri = rd, ro;
//comparison opcodes always update flags //comparison opcodes always update flags (debug test)
if(opcode >= 8 && opcode <= 11) assert(s == 1); //this can be removed later: s=0 opcode=8-11 is invalid
if(opcode >= 8 && opcode <= 11) assert(save == 1);
auto bit = [&](uint32 ro) { auto test = [&](uint32 result) {
if(!s) return; if(save) {
cpsr.n = ro >> 31; cpsr.n = result >> 31;
cpsr.z = ro == 0; cpsr.z = result == 0;
cpsr.c = shiftercarry;
}
return result;
}; };
auto add = [&](uint32 ro) { auto math = [&](uint32 source, uint32 modify, bool carry) {
if(!s) return; uint32 result = source + modify + carry;
cpsr.n = ro >> 31; if(save) {
cpsr.z = ro == 0; cpsr.n = result >> 31;
cpsr.c = ro < ri; cpsr.z = result == 0;
cpsr.v = ~(ri ^ rm) & (ri ^ ro) & (1u << 31); cpsr.c = result < source;
}; cpsr.v = ~(source ^ modify) & (source ^ result) & (1u << 31);
}
auto sub = [&](uint32 ro) { return result;
if(!s) return;
cpsr.n = ro >> 31;
cpsr.z = ro == 0;
cpsr.c = ro > ri;
cpsr.v = (ri ^ rm) & (ri ^ ro) & (1u << 31);
}; };
switch(opcode) { switch(opcode) {
case 0: rd = rn & rm; bit(rd); break; //AND (logical and) case 0: r[d] = test(rn & rm); break; //AND
case 1: rd = rn ^ rm; bit(rd); break; //EOR (logical exclusive or) case 1: r[d] = test(rn ^ rm); break; //EOR
case 2: rd = rn - rm; sub(rd); break; //SUB (subtract) case 2: r[d] = math(rn, ~rm, 1); break; //SUB
case 3: rd = rm - rn; sub(rd); break; //RSB (reverse subtract) case 3: r[d] = math(rm, ~rn, 1); break; //RSB
case 4: rd = rn + rm; add(rd); break; //ADD (add) case 4: r[d] = math(rn, rm, 0); break; //ADD
case 5: rd = rn + rm + cpsr.c; add(rd); break; //ADC (add with carry) case 5: r[d] = math(rn, rm, cpsr.c); break; //ADC
case 6: rd = rn - rm -!cpsr.c; sub(rd); break; //SBC (subtract with carry) case 6: r[d] = math(rn, ~rm, cpsr.c); break; //SBC
case 7: rd = rm - rn -!cpsr.c; sub(rd); break; //RSC (reverse subtract with carry) case 7: r[d] = math(rm, ~rn, cpsr.c); break; //RSC
case 8: ro = rn & rm; bit(ro); break; //TST (test) case 8: test(rn & rm); break; //TST
case 9: ro = rn ^ rm; bit(ro); break; //TEQ (test equivalence) case 9: test(rn ^ rm); break; //TEQ
case 10: ro = rn - rm; sub(ro); break; //CMP (compare) case 10: math(rn, ~rm, 1); break; //CMP
case 11: ro = rn + rm; add(ro); break; //CMN (compare negated) case 11: math(rn, rm, 0); break; //CMN
case 12: rd = rn | rm; bit(rd); break; //ORR (logical inclusive or) case 12: r[d] = test(rn | rm); break; //ORR
case 13: rd = rm; bit(rd); break; //MOV (move) case 13: r[d] = test(rm); break; //MOV
case 14: rd = rn &~rm; bit(rd); break; //BIC (bit clear) case 14: r[d] = test(rn &~rm); break; //BIC
case 15: rd =~rm; bit(rd); break; //MVN (move not) case 15: r[d] = test(~rm); break; //MVN
} }
} }
@ -203,7 +200,7 @@ void ArmDSP::op_data_immediate_shift() {
if(mode == 2) asr(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 == 3) rs ? ror(c, rm, rs) : rrx(c, rm);
if(save) cpsr.c = c; shiftercarry = c;
opcode(rm); opcode(rm);
} }
@ -232,9 +229,9 @@ void ArmDSP::op_data_register_shift() {
if(mode == 0) lsl(c, rm, rs < 33 ? rs : 33); if(mode == 0) lsl(c, rm, rs < 33 ? rs : 33);
if(mode == 1) lsr(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 == 2) asr(c, rm, rs < 32 ? rs : 32);
if(mode == 3) ror(c, rm, rs < 32 ? rs : 32); if(mode == 3 && rs) ror(c, rm, rs & 31 == 0 ? 32 : rs & 31);
if(save) cpsr.c = c; shiftercarry = c;
opcode(rm); opcode(rm);
} }
@ -254,17 +251,15 @@ void ArmDSP::op_data_immediate() {
uint4 shift = instruction >> 8; uint4 shift = instruction >> 8;
uint8 immediate = instruction; uint8 immediate = instruction;
bool c = cpsr.c;
uint32 rs = shift << 1; uint32 rs = shift << 1;
uint32 rm = (immediate >> rs) | (immediate << (32 - rs)); uint32 rm = (immediate >> rs) | (immediate << (32 - rs));
if(rs) c = immediate >> 31; if(rs) shiftercarry = immediate >> 31;
if(save) cpsr.c = c;
opcode(rm); opcode(rm);
} }
//(ldr,str){condition}{b} rd,[rn{+offset}] //(ldr,str){condition}{b} rd,[rn{,+/-offset}]{!}
//(ldr,str){condition}{b} rd,[rn]{,+/-offset}
//cccc 010p ubwl nnnn dddd iiii iiii iiii //cccc 010p ubwl nnnn dddd iiii iiii iiii
//c = condition //c = condition
//p = pre (0 = post-indexed addressing) //p = pre (0 = post-indexed addressing)
@ -288,22 +283,16 @@ void ArmDSP::op_move_immediate_offset() {
uint32 rn = r[n]; uint32 rn = r[n];
auto &rd = r[d]; auto &rd = r[d];
if(l) {
if(p == 1) rn = u ? rn + rm : rn - rm; if(p == 1) rn = u ? rn + rm : rn - rm;
if(b) rd = bus_read<1>(rn); if(l) rd = b ? bus_readbyte(rn) : bus_readword(rn);
else rd = bus_read<4>(rn); else b ? bus_writebyte(rn, rd) : bus_writeword(rn, rd);
if(p == 0) rn = u ? rn + rm : rn - rm; if(p == 0) rn = u ? rn + rm : rn - rm;
} else {
if(p == 1) rn = u ? rn + rm : rn - rm;
if(b) bus_write<1>(rn, rd);
else bus_write<4>(rn, rd);
if(p == 0) rn = u ? rn + rm : rn - rm;
}
if(p == 0 || w == 1) r[n] = rn; if(p == 0 || w == 1) r[n] = rn;
} }
//(ldr)(str){condition}{b} rd,rn,rm {mode} #immediate //(ldr)(str){condition}{b} rd,[rn,rm {mode} #immediate]{!}
//(ldr)(str){condition}{b} rd,[rn],rm {mode} #immediate
//cccc 011p ubwl nnnn dddd llll lss0 mmmm //cccc 011p ubwl nnnn dddd llll lss0 mmmm
//c = condition //c = condition
//p = pre (0 = post-indexed addressing) //p = pre (0 = post-indexed addressing)
@ -339,17 +328,10 @@ void ArmDSP::op_move_register_offset() {
if(mode == 2) asr(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 == 3) rs ? ror(c, rm, rs) : rrx(c, rm);
if(l) {
if(p == 1) rn = u ? rn + rm : rn - rm; if(p == 1) rn = u ? rn + rm : rn - rm;
if(b) rd = bus_read<1>(rn); if(l) rd = b ? bus_readbyte(rn) : bus_readword(rn);
else rd = bus_read<4>(rn); else b ? bus_writebyte(rn, rd) : bus_writeword(rn, rd);
if(p == 0) rn = u ? rn + rm : rn - rm; if(p == 0) rn = u ? rn + rm : rn - rm;
} else {
if(p == 1) rn = u ? rn + rm : rn - rm;
if(b) bus_write<1>(rn, rd);
else bus_write<4>(rn, rd);
if(p == 0) rn = u ? rn + rm : rn - rm;
}
if(p == 0 || w == 1) r[n] = rn; if(p == 0 || w == 1) r[n] = rn;
} }
@ -379,21 +361,13 @@ void ArmDSP::op_move_multiple() {
if(p == 1 && u == 0) rn = rn - bit::count(list) * 4 + 0; //DB if(p == 1 && u == 0) rn = rn - bit::count(list) * 4 + 0; //DB
if(p == 0 && u == 0) rn = rn - bit::count(list) * 4 + 4; //DA if(p == 0 && u == 0) rn = rn - bit::count(list) * 4 + 4; //DA
if(l) {
for(unsigned n = 0; n < 16; n++) { for(unsigned n = 0; n < 16; n++) {
if(list & (1 << n)) { if(list & (1 << n)) {
r[n] = bus_read<4>(rn); if(l) r[n] = bus_readword(rn);
else bus_writeword(rn, r[n]);
rn += 4; rn += 4;
} }
} }
} else {
for(unsigned n = 0; n < 16; n++) {
if(list & (1 << n)) {
bus_write<4>(rn, r[n]);
rn += 4;
}
}
}
if(w) { if(w) {
if(u == 1) r[n] = r[n] + bit::count(list) * 4; //IA, IB if(u == 1) r[n] = r[n] + bit::count(list) * 4; //IA, IB

View File

@ -101,6 +101,8 @@ struct Register {
} }
} r[16]; } r[16];
bool shiftercarry;
struct Pipeline { struct Pipeline {
bool reload; bool reload;
struct Instruction { struct Instruction {