mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
ad71e18e02
commit
aa8ac7bbb8
|
@ -89,6 +89,6 @@ sync:
|
|||
rm -r phoenix/test
|
||||
|
||||
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:;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef BASE_HPP
|
||||
#define BASE_HPP
|
||||
|
||||
const char Version[] = "086.13";
|
||||
const char Version[] = "086.14";
|
||||
|
||||
#include <nall/platform.hpp>
|
||||
#include <nall/algorithm.hpp>
|
||||
|
|
|
@ -529,19 +529,10 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) {
|
|||
|
||||
if(has_st018) markup.append(
|
||||
" <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='80-bf:3800-38ff'/>\n"
|
||||
" </setarisc>\n"
|
||||
" </armdsp>\n"
|
||||
);
|
||||
#endif
|
||||
|
||||
markup.append("</cartridge>\n");
|
||||
}
|
||||
|
|
|
@ -35,13 +35,13 @@ void ArmDSP::enter() {
|
|||
if(pipeline.reload) {
|
||||
pipeline.reload = false;
|
||||
pipeline.prefetch.address = r[15];
|
||||
pipeline.prefetch.opcode = bus_read<4>(r[15]);
|
||||
pipeline.prefetch.opcode = bus_readword(r[15]);
|
||||
r[15].step();
|
||||
}
|
||||
|
||||
pipeline.instruction = pipeline.prefetch;
|
||||
pipeline.prefetch.address = r[15];
|
||||
pipeline.prefetch.opcode = bus_read<4>(r[15]);
|
||||
pipeline.prefetch.opcode = bus_readword(r[15]);
|
||||
r[15].step();
|
||||
|
||||
//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) {
|
||||
cpu.synchronize_coprocessors();
|
||||
|
||||
uint8 data = 0x00;
|
||||
addr &= 0xffff;
|
||||
addr &= 0xff06;
|
||||
|
||||
if(addr == 0x3800) {
|
||||
if(bridge.armtocpu.ready) {
|
||||
|
@ -104,7 +108,7 @@ void ArmDSP::mmio_write(unsigned addr, uint8 data) {
|
|||
usleep(200000);
|
||||
}
|
||||
|
||||
addr &= 0xffff;
|
||||
addr &= 0xff06;
|
||||
|
||||
if(addr == 0x3802) {
|
||||
bridge.cputoarm.ready = true;
|
||||
|
@ -131,12 +135,21 @@ void ArmDSP::power() {
|
|||
fp.read(dataROM, 32 * 1024);
|
||||
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() {
|
||||
create(ArmDSP::Enter, 21477272);
|
||||
|
||||
for(auto &rd : r) rd = 0;
|
||||
shiftercarry = 0;
|
||||
|
||||
exception = false;
|
||||
|
||||
pipeline.reload = true;
|
||||
|
|
|
@ -42,8 +42,12 @@ struct ArmDSP : public Coprocessor {
|
|||
//memory.cpp
|
||||
uint8 bus_iread(uint32 addr);
|
||||
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
|
||||
string disassemble_opcode(uint32 pc);
|
||||
|
|
|
@ -12,10 +12,11 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
|
|||
|
||||
string output{hex<8>(pc), " "};
|
||||
|
||||
uint32 instruction = bus_read<4>(pc);
|
||||
uint32 instruction = bus_readword(pc);
|
||||
output.append(hex<8>(instruction), " ");
|
||||
|
||||
//multiply
|
||||
//(mul,mla){condition}{s} rd,rm,rs,rn
|
||||
if((instruction & 0x0fc000f0) == 0x00000090) {
|
||||
uint4 condition = instruction >> 28;
|
||||
uint1 accumulate = instruction >> 21;
|
||||
|
@ -33,6 +34,7 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
|
|||
}
|
||||
|
||||
//move to register from status register
|
||||
//mrs{condition} rd,(c,s)psr
|
||||
if((instruction & 0x0fb000f0) == 0x01000000) {
|
||||
uint4 condition = instruction >> 28;
|
||||
uint1 psr = instruction >> 22;
|
||||
|
@ -45,6 +47,7 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
|
|||
}
|
||||
|
||||
//move to status register from register
|
||||
//msr{condition} (c,s)psr:{fields},rm
|
||||
if((instruction & 0x0fb000f0) == 0x01200000) {
|
||||
uint4 condition = instruction >> 28;
|
||||
uint1 psr = instruction >> 22;
|
||||
|
@ -89,6 +92,34 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
|
|||
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
|
||||
//{opcode}{condition}{s} rd,#immediate
|
||||
//{opcode}{condition} rn,#immediate
|
||||
|
@ -113,21 +144,58 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
|
|||
}
|
||||
|
||||
//move immediate offset
|
||||
//(ldr,str){condition}{b} rd,[rn{+offset}]
|
||||
//todo: support W flag
|
||||
//(ldr,str){condition}{b} rd,[rn{,+/-offset}]{!}
|
||||
//(ldr,str){condition}{b} rd,[rn]{,+/-offset}
|
||||
if((instruction & 0x0e000000) == 0x04000000) {
|
||||
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;
|
||||
uint12 immediate = instruction;
|
||||
|
||||
output.append(load ? "ldr" : "str", conditions[condition]);
|
||||
if(instruction & 0x00400000) output.append("b");
|
||||
output.append(" ", registers[rd], ",[", registers[rn]);
|
||||
if(immediate) output.append(u ? "+" : "-", "0x", hex<3>((uint12)instruction));
|
||||
output.append("]");
|
||||
output.append(load ? "ldr" : "str", conditions[condition], b ? "b " : " ");
|
||||
output.append(registers[rd], ",[", registers[rn]);
|
||||
if(p == 0) output.append("]");
|
||||
if(immediate) output.append(",", u ? "+" : "-", "0x", hex<3>(immediate));
|
||||
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;
|
||||
}
|
||||
|
@ -166,10 +234,12 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
|
|||
string ArmDSP::disassemble_registers() {
|
||||
return {
|
||||
"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]),
|
||||
" r12:", hex<8>(r[12]), " r13:", hex<8>(r[13]), " r14:", hex<8>(r[14]), " r15:", hex<8>(r[15]), "\n",
|
||||
"cpsr:", cpsr.n ? "N" : "n", cpsr.z ? "Z" : "z", cpsr.c ? "C" : "c", cpsr.v ? "V" : "v"
|
||||
" r12:", hex<8>(r[12]), " r13:", hex<8>(r[13]), " r14:", hex<8>(r[14]), " r15:", hex<8>(r[15]), " ",
|
||||
"spsr:", spsr.n ? "N" : "n", spsr.z ? "Z" : "z", spsr.c ? "C" : "c", spsr.v ? "V" : "v"
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
template<unsigned size>
|
||||
uint32 ArmDSP::bus_read(uint32 addr) {
|
||||
uint32 data = 0;
|
||||
|
||||
if(size == 1) {
|
||||
uint32 mask = 255u << ((addr & ~3) << 3);
|
||||
data |= bus_iread(addr) & mask;
|
||||
uint32 ArmDSP::bus_readbyte(uint32 addr) {
|
||||
return bus_iread(addr);
|
||||
}
|
||||
|
||||
if(size == 4) {
|
||||
uint32 ArmDSP::bus_readword(uint32 addr) {
|
||||
addr &= ~3;
|
||||
data |= bus_iread(addr + 0) << 0;
|
||||
data |= bus_iread(addr + 1) << 8;
|
||||
data |= bus_iread(addr + 2) << 16;
|
||||
data |= bus_iread(addr + 3) << 24;
|
||||
return (
|
||||
(bus_iread(addr + 0) << 0)
|
||||
| (bus_iread(addr + 1) << 8)
|
||||
| (bus_iread(addr + 2) << 16)
|
||||
| (bus_iread(addr + 3) << 24)
|
||||
);
|
||||
}
|
||||
|
||||
if(0&&addr >= 0x40000000 && addr <= 0x400000ff) {
|
||||
if(addr != 0x40000020 || data != 0x80)
|
||||
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);
|
||||
}
|
||||
void ArmDSP::bus_writebyte(uint32 addr, uint32 data) {
|
||||
return bus_iwrite(addr, data);
|
||||
}
|
||||
|
||||
if(size == 1) return data & 0xff;
|
||||
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) {
|
||||
void ArmDSP::bus_writeword(uint32 addr, uint32 data) {
|
||||
addr &= ~3;
|
||||
bus_iwrite(addr + 0, data >> 0);
|
||||
bus_iwrite(addr + 1, data >> 8);
|
||||
bus_iwrite(addr + 2, data >> 16);
|
||||
bus_iwrite(addr + 3, data >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,56 +29,53 @@ bool ArmDSP::condition() {
|
|||
//ro = modified target
|
||||
void ArmDSP::opcode(uint32 rm) {
|
||||
uint4 opcode = instruction >> 21;
|
||||
uint1 s = instruction >> 20;
|
||||
uint1 save = instruction >> 20;
|
||||
uint4 n = instruction >> 16;
|
||||
uint4 d = instruction >> 12;
|
||||
|
||||
uint32 rn = r[n];
|
||||
auto &rd = r[d];
|
||||
uint32 ri = rd, ro;
|
||||
|
||||
//comparison opcodes always update flags
|
||||
if(opcode >= 8 && opcode <= 11) assert(s == 1);
|
||||
//comparison opcodes always update flags (debug test)
|
||||
//this can be removed later: s=0 opcode=8-11 is invalid
|
||||
if(opcode >= 8 && opcode <= 11) assert(save == 1);
|
||||
|
||||
auto bit = [&](uint32 ro) {
|
||||
if(!s) return;
|
||||
cpsr.n = ro >> 31;
|
||||
cpsr.z = ro == 0;
|
||||
auto test = [&](uint32 result) {
|
||||
if(save) {
|
||||
cpsr.n = result >> 31;
|
||||
cpsr.z = result == 0;
|
||||
cpsr.c = shiftercarry;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
auto add = [&](uint32 ro) {
|
||||
if(!s) return;
|
||||
cpsr.n = ro >> 31;
|
||||
cpsr.z = ro == 0;
|
||||
cpsr.c = ro < ri;
|
||||
cpsr.v = ~(ri ^ rm) & (ri ^ ro) & (1u << 31);
|
||||
};
|
||||
|
||||
auto sub = [&](uint32 ro) {
|
||||
if(!s) return;
|
||||
cpsr.n = ro >> 31;
|
||||
cpsr.z = ro == 0;
|
||||
cpsr.c = ro > ri;
|
||||
cpsr.v = (ri ^ rm) & (ri ^ ro) & (1u << 31);
|
||||
auto math = [&](uint32 source, uint32 modify, bool carry) {
|
||||
uint32 result = source + modify + carry;
|
||||
if(save) {
|
||||
cpsr.n = result >> 31;
|
||||
cpsr.z = result == 0;
|
||||
cpsr.c = result < source;
|
||||
cpsr.v = ~(source ^ modify) & (source ^ result) & (1u << 31);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
switch(opcode) {
|
||||
case 0: rd = rn & rm; bit(rd); break; //AND (logical and)
|
||||
case 1: rd = rn ^ rm; bit(rd); break; //EOR (logical exclusive or)
|
||||
case 2: rd = rn - rm; sub(rd); break; //SUB (subtract)
|
||||
case 3: rd = rm - rn; sub(rd); break; //RSB (reverse subtract)
|
||||
case 4: rd = rn + rm; add(rd); break; //ADD (add)
|
||||
case 5: rd = rn + rm + cpsr.c; add(rd); break; //ADC (add with carry)
|
||||
case 6: rd = rn - rm -!cpsr.c; sub(rd); break; //SBC (subtract with carry)
|
||||
case 7: rd = rm - rn -!cpsr.c; sub(rd); break; //RSC (reverse subtract with carry)
|
||||
case 8: ro = rn & rm; bit(ro); break; //TST (test)
|
||||
case 9: ro = rn ^ rm; bit(ro); break; //TEQ (test equivalence)
|
||||
case 10: ro = rn - rm; sub(ro); break; //CMP (compare)
|
||||
case 11: ro = rn + rm; add(ro); break; //CMN (compare negated)
|
||||
case 12: rd = rn | rm; bit(rd); break; //ORR (logical inclusive or)
|
||||
case 13: rd = rm; bit(rd); break; //MOV (move)
|
||||
case 14: rd = rn &~rm; bit(rd); break; //BIC (bit clear)
|
||||
case 15: rd =~rm; bit(rd); break; //MVN (move not)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +200,7 @@ void ArmDSP::op_data_immediate_shift() {
|
|||
if(mode == 2) asr(c, rm, rs ? rs : 32);
|
||||
if(mode == 3) rs ? ror(c, rm, rs) : rrx(c, rm);
|
||||
|
||||
if(save) cpsr.c = c;
|
||||
shiftercarry = c;
|
||||
opcode(rm);
|
||||
}
|
||||
|
||||
|
@ -232,9 +229,9 @@ void ArmDSP::op_data_register_shift() {
|
|||
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) 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);
|
||||
}
|
||||
|
||||
|
@ -254,17 +251,15 @@ void ArmDSP::op_data_immediate() {
|
|||
uint4 shift = instruction >> 8;
|
||||
uint8 immediate = instruction;
|
||||
|
||||
bool c = cpsr.c;
|
||||
|
||||
uint32 rs = shift << 1;
|
||||
uint32 rm = (immediate >> rs) | (immediate << (32 - rs));
|
||||
if(rs) c = immediate >> 31;
|
||||
if(rs) shiftercarry = immediate >> 31;
|
||||
|
||||
if(save) cpsr.c = c;
|
||||
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
|
||||
//c = condition
|
||||
//p = pre (0 = post-indexed addressing)
|
||||
|
@ -288,22 +283,16 @@ void ArmDSP::op_move_immediate_offset() {
|
|||
uint32 rn = r[n];
|
||||
auto &rd = r[d];
|
||||
|
||||
if(l) {
|
||||
if(p == 1) rn = u ? rn + rm : rn - rm;
|
||||
if(b) rd = bus_read<1>(rn);
|
||||
else rd = bus_read<4>(rn);
|
||||
if(l) rd = b ? bus_readbyte(rn) : bus_readword(rn);
|
||||
else b ? bus_writebyte(rn, rd) : bus_writeword(rn, rd);
|
||||
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;
|
||||
}
|
||||
|
||||
//(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
|
||||
//c = condition
|
||||
//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 == 3) rs ? ror(c, rm, rs) : rrx(c, rm);
|
||||
|
||||
if(l) {
|
||||
if(p == 1) rn = u ? rn + rm : rn - rm;
|
||||
if(b) rd = bus_read<1>(rn);
|
||||
else rd = bus_read<4>(rn);
|
||||
if(l) rd = b ? bus_readbyte(rn) : bus_readword(rn);
|
||||
else b ? bus_writebyte(rn, rd) : bus_writeword(rn, rd);
|
||||
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;
|
||||
}
|
||||
|
@ -379,21 +361,13 @@ void ArmDSP::op_move_multiple() {
|
|||
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(l) {
|
||||
for(unsigned n = 0; n < 16; 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;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(unsigned n = 0; n < 16; n++) {
|
||||
if(list & (1 << n)) {
|
||||
bus_write<4>(rn, r[n]);
|
||||
rn += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(w) {
|
||||
if(u == 1) r[n] = r[n] + bit::count(list) * 4; //IA, IB
|
||||
|
|
|
@ -101,6 +101,8 @@ struct Register {
|
|||
}
|
||||
} r[16];
|
||||
|
||||
bool shiftercarry;
|
||||
|
||||
struct Pipeline {
|
||||
bool reload;
|
||||
struct Instruction {
|
||||
|
|
Loading…
Reference in New Issue