Update to v086r12 release.

byuu says:

Attract demonstration game is fully playable.
This commit is contained in:
Tim Allen 2012-02-29 23:56:21 +11:00
parent 112520cf45
commit a00c7cb639
6 changed files with 85 additions and 36 deletions

View File

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

View File

@ -52,6 +52,7 @@ void ArmDSP::enter() {
}
instruction = pipeline.instruction.opcode;
if((instruction & 0x0fc000f0) == 0x00000090) { op_multiply(); continue; }
if((instruction & 0x0fb000f0) == 0x01000000) { op_move_to_register_from_status_register(); continue; }
if((instruction & 0x0fb000f0) == 0x01200000) { op_move_to_status_register_from_register(); continue; }
if((instruction & 0x0e000010) == 0x00000000) { op_data_immediate_shift(); continue; }
@ -126,7 +127,7 @@ void ArmDSP::power() {
string filename = interface->path(Cartridge::Slot::Base, "st0018d.rom");
file fp;
if(fp.open(filename, file::mode::read)) {
fp.read(aoRAM, 32 * 1024);
fp.read(dataROM, 32 * 1024);
fp.close();
}
}

View File

@ -3,7 +3,7 @@
struct ArmDSP : public Coprocessor {
uint8 programROM[128 * 1024];
uint8 programRAM[16 * 1024];
uint8 aoRAM[32 * 1024];
uint8 dataROM[32 * 1024];
#include "registers.hpp"
@ -23,6 +23,7 @@ struct ArmDSP : public Coprocessor {
bool condition();
void opcode(uint32 data);
void op_multiply();
void op_move_to_status_register_from_register();
void op_move_to_register_from_status_register();
void op_data_immediate_shift();

View File

@ -40,7 +40,7 @@ string ArmDSP::disassemble_opcode(uint32 pc) {
//{opcode}{condition}{s} rd,rm {shift} #immediate
//{opcode}{condition} rn,rm {shift} #immediate
//{opcode}{condition}{s} rd,rn,rm {shift} #immediate
if((instruction & 0x0e000000) == 0x00000000) {
if((instruction & 0x0e000010) == 0x00000000) {
uint4 condition = instruction >> 28;
uint4 opcode = instruction >> 21;
uint1 save = instruction >> 20;

View File

@ -25,7 +25,7 @@ uint8 ArmDSP::bus_iread(uint32 addr) {
}
if(addr >= 0xa0000000 && addr <= 0xa0007fff) {
return aoRAM[addr & 0x00007fff];
return dataROM[addr & 0x00007fff];
}
if(addr >= 0xe0000000 && addr <= 0xe0003fff) {
@ -50,9 +50,6 @@ void ArmDSP::bus_iwrite(uint32 addr, uint8 data) {
if(addr == 0x4000002c) return print("* w4000002c = ", hex<2>(data), "\n");
}
if(addr >= 0xa0000000 && addr <= 0xa0007fff) {
}
if(addr >= 0xe0000000 && addr <= 0xe0003fff) {
programRAM[addr & 0x00003fff] = data;
return;
@ -64,10 +61,19 @@ void ArmDSP::bus_iwrite(uint32 addr, uint8 data) {
template<unsigned size>
uint32 ArmDSP::bus_read(uint32 addr) {
uint32 data = 0;
data |= bus_iread(addr + 0) << 0;
data |= bus_iread(addr + 1) << 8;
data |= bus_iread(addr + 2) << 16;
data |= bus_iread(addr + 3) << 24;
if(size == 1) {
uint32 mask = 255u << ((addr & ~3) << 3);
data |= bus_iread(addr) & mask;
}
if(size == 4) {
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;
}
if(0&&addr >= 0x40000000 && addr <= 0x400000ff) {
if(addr != 0x40000020 || data != 0x80)
@ -95,12 +101,18 @@ void ArmDSP::bus_write(uint32 addr, uint32 data) {
}
}
if(size == 1) data = (bus_read<1>(addr) & 0xffffff00) | (data & 0x000000ff);
if(size == 2) data = (bus_read<2>(addr) & 0xffff0000) | (data & 0x0000ffff);
bus_iwrite(addr + 0, data >> 0);
bus_iwrite(addr + 1, data >> 8);
bus_iwrite(addr + 2, data >> 16);
bus_iwrite(addr + 3, data >> 24);
if(size == 1) {
uint32 mask = 255u << ((addr & ~3) << 3);
bus_iwrite(addr, data);
}
if(size == 4) {
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

View File

@ -36,13 +36,13 @@ void ArmDSP::opcode(uint32 rm) {
//comparison opcodes always update flags
if(opcode >= 8 && opcode <= 11) assert(s == 1);
static auto nz = [&](uint32 ro) {
static auto bit = [&](uint32 ro) {
if(!s) return;
cpsr.n = ro & 0x80000000;
cpsr.z = ro == 0;
};
static auto nzcv = [&](uint32 ro) {
static auto add = [&](uint32 ro) {
if(!s) return;
cpsr.n = ro & 0x80000000;
cpsr.z = ro == 0;
@ -50,23 +50,58 @@ void ArmDSP::opcode(uint32 rm) {
cpsr.v = ~(ri ^ rm) & (ri ^ ro) & 0x80000000;
};
static auto sub = [&](uint32 ro) {
if(!s) return;
cpsr.n = ro & 0x80000000;
cpsr.z = ro == 0;
cpsr.c = ro > ri;
cpsr.v = (ri ^ rm) & (ri ^ ro) & 0x80000000;
};
switch(opcode) {
case 0: rd = rn & rm; nz(rd); break; //AND (logical and)
case 1: rd = rn ^ rm; nz(rd); break; //EOR (logical exclusive or)
case 2: rd = rn +~rm + 1; nzcv(rd); break; //SUB (subtract)
case 3: rd = rm +~rn + 1; nzcv(rd); break; //RSB (reverse subtract)
case 4: rd = rn + rm; nzcv(rd); break; //ADD (add)
case 5: rd = rn + rm + cpsr.c; nzcv(rd); break; //ADC (add with carry)
case 6: rd = rn +~rm + cpsr.c; nzcv(rd); break; //SBC (subtract with carry)
case 7: rd = rm +~rn + cpsr.c; nzcv(rd); break; //RSC (reverse subtract with carry)
case 8: ro = rn & rm; nz(ro); break; //TST (test)
case 9: ro = rn ^ rm; nz(ro); break; //TEQ (test equivalence)
case 10: ro = rn +~rm + 1; nzcv(ro); break; //CMP (compare)
case 11: ro = rn + rm; nzcv(ro); break; //CMN (compare negated)
case 12: rd = rn | rm; nz(rd); break; //ORR (logical inclusive or)
case 13: rd = rm; nz(rd); break; //MOV (move)
case 14: rd = rn &~rm; nz(rd); break; //BIC (bit clear)
case 15: rd =~rm; nz(rd); break; //MVN (move not)
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)
}
}
//(mul,mla){condition}{s}
//cccc 0000 00as dddd nnnn ssss 1001 mmmm
//c = condition
//a = accumulate
//s = save flags
//d = rd
//n = rn
//s = rs
//n = rm
void ArmDSP::op_multiply() {
if(!condition()) return;
uint1 accumulate = instruction >> 21;
uint1 save = instruction >> 20;
uint4 d = instruction >> 16;
uint4 n = instruction >> 12;
uint4 s = instruction >> 8;
uint4 m = instruction >> 0;
r[d] = r[m] * r[s];
if(accumulate) r[d] += r[n];
if(save) {
cpsr.n = r[d] & 0x80000000;
cpsr.z = r[d] == 0;
}
}