Update to v086r08 release.

byuu says:

Contains the fledgling beginnings of an ARM CPU core, which can execute
the first three and a half instructions of the ST-0018.
It's a start, I guess.
This commit is contained in:
Tim Allen 2012-02-26 18:59:44 +11:00
parent f1d6325bcd
commit 482b4119f6
22 changed files with 521 additions and 175 deletions

View File

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

View File

@ -527,12 +527,21 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) {
" </necdsp>\n"
);
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"
);
#endif
markup.append("</cartridge>\n");
}

70
bsnes/nall/snes/usart.hpp Executable file
View File

@ -0,0 +1,70 @@
#ifndef NALL_SNES_USART_HPP
#define NALL_SNES_USART_HPP
#include <nall/platform.hpp>
#include <nall/function.hpp>
#include <nall/serial.hpp>
#include <nall/stdint.hpp>
#define usartproc dllexport
static nall::function<void (unsigned milliseconds)> usart_usleep;
static nall::function<uint8_t ()> usart_read;
static nall::function<void (uint8_t data)> usart_write;
extern "C" usartproc void usart_init(
nall::function<void (unsigned milliseconds)> usleep,
nall::function<uint8_t ()> read,
nall::function<void (uint8_t data)> write
) {
usart_usleep = usleep;
usart_read = read;
usart_write = write;
}
extern "C" usartproc void usart_main();
//
static nall::serial usart;
static bool usart_is_virtual = true;
static bool usart_virtual() {
return usart_is_virtual;
}
//
static void usarthw_usleep(unsigned milliseconds) {
usleep(milliseconds);
}
static uint8_t usarthw_read() {
while(true) {
uint8_t buffer[1];
signed length = usart.read((uint8_t*)&buffer, 1);
if(length > 0) return buffer[0];
}
}
static void usarthw_write(uint8_t data) {
uint8_t buffer[1] = { data };
usart.write((uint8_t*)&buffer, 1);
}
int main(int argc, char **argv) {
bool result = false;
if(argc == 1) result = usart.open("/dev/ttyACM0", 57600, true);
if(argc == 2) result = usart.open(argv[1], 57600, true);
if(result == false) {
printf("error: unable to open USART hardware device\n");
return 0;
}
usart_is_virtual = false;
usart_init(usarthw_usleep, usarthw_read, usarthw_write);
usart_main();
usart.close();
return 0;
}
#endif

26
bsnes/nall/stack.hpp Executable file
View File

@ -0,0 +1,26 @@
#ifndef NALL_STACK_HPP
#define NALL_STACK_HPP
#include <nall/vector.hpp>
namespace nall {
template<typename T> struct stack : public linear_vector<T> {
void push(const T &value) {
linear_vector<T>::append(value);
}
T pull() {
if(linear_vector<T>::size() == 0) throw;
T value = linear_vector<T>::operator[](linear_vector<T>::size() - 1);
linear_vector<T>::remove(linear_vector<T>::size() - 1);
return value;
}
T& operator()() {
if(linear_vector<T>::size() == 0) throw;
return linear_vector<T>::operator[](linear_vector<T>::size() - 1);
}
};
}
#endif

View File

@ -25,13 +25,12 @@
#include <nall/string/base.hpp>
#include <nall/string/bml.hpp>
#include <nall/string/bsv.hpp>
#include <nall/string/core.hpp>
#include <nall/string/cast.hpp>
#include <nall/string/compare.hpp>
#include <nall/string/convert.hpp>
#include <nall/string/core.hpp>
#include <nall/string/cstring.hpp>
#include <nall/string/filename.hpp>
#include <nall/string/math.hpp>
#include <nall/string/math-fixed-point.hpp>
#include <nall/string/math-floating-point.hpp>
#include <nall/string/platform.hpp>
@ -40,6 +39,7 @@
#include <nall/string/trim.hpp>
#include <nall/string/replace.hpp>
#include <nall/string/split.hpp>
#include <nall/string/utf8.hpp>
#include <nall/string/utility.hpp>
#include <nall/string/variadic.hpp>
#include <nall/string/wildcard.hpp>

View File

@ -1,167 +0,0 @@
#ifdef NALL_STRING_INTERNAL_HPP
namespace nall {
static function<int64_t (const char *&)> eval_fallback;
static int eval_integer(const char *&s) {
if(!*s) throw "unrecognized_integer";
int value = 0, x = *s, y = *(s + 1);
//hexadecimal
if(x == '0' && (y == 'X' || y == 'x')) {
s += 2;
while(true) {
if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; }
if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; }
if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; }
return value;
}
}
//binary
if(x == '0' && (y == 'B' || y == 'b')) {
s += 2;
while(true) {
if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; }
return value;
}
}
//octal (or decimal '0')
if(x == '0') {
s += 1;
while(true) {
if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; }
return value;
}
}
//decimal
if(x >= '0' && x <= '9') {
while(true) {
if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; }
return value;
}
}
//char
if(x == '\'' && y != '\'') {
s += 1;
while(true) {
value = value * 256 + *s++;
if(*s == '\'') { s += 1; return value; }
if(!*s) throw "mismatched_char";
}
}
throw "unrecognized_integer";
}
static int eval(const char *&s, int depth = 0) {
while(*s == ' ' || *s == '\t') s++; //trim whitespace
if(!*s) throw "unrecognized_token";
int value = 0, x = *s, y = *(s + 1);
if(*s == '(') {
value = eval(++s, 1);
if(*s++ != ')') throw "mismatched_group";
}
else if(x == '!') value = !eval(++s, 13);
else if(x == '~') value = ~eval(++s, 13);
else if(x == '+') value = +eval(++s, 13);
else if(x == '-') value = -eval(++s, 13);
else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s);
else if(eval_fallback) value = eval_fallback(s); //optional user-defined syntax parsing
else throw "unrecognized_token";
while(true) {
while(*s == ' ' || *s == '\t') s++; //trim whitespace
if(!*s) break;
x = *s, y = *(s + 1);
if(depth >= 13) break;
if(x == '*') { value *= eval(++s, 13); continue; }
if(x == '/') { int result = eval(++s, 13); if(result == 0) throw "division_by_zero"; value /= result; continue; }
if(x == '%') { int result = eval(++s, 13); if(result == 0) throw "division_by_zero"; value %= result; continue; }
if(depth >= 12) break;
if(x == '+') { value += eval(++s, 12); continue; }
if(x == '-') { value -= eval(++s, 12); continue; }
if(depth >= 11) break;
if(x == '<' && y == '<') { value <<= eval(++++s, 11); continue; }
if(x == '>' && y == '>') { value >>= eval(++++s, 11); continue; }
if(depth >= 10) break;
if(x == '<' && y == '=') { value = value <= eval(++++s, 10); continue; }
if(x == '>' && y == '=') { value = value >= eval(++++s, 10); continue; }
if(x == '<') { value = value < eval(++s, 10); continue; }
if(x == '>') { value = value > eval(++s, 10); continue; }
if(depth >= 9) break;
if(x == '=' && y == '=') { value = value == eval(++++s, 9); continue; }
if(x == '!' && y == '=') { value = value != eval(++++s, 9); continue; }
if(depth >= 8) break;
if(x == '&' && y != '&') { value = value & eval(++s, 8); continue; }
if(depth >= 7) break;
if(x == '^' && y != '^') { value = value ^ eval(++s, 7); continue; }
if(depth >= 6) break;
if(x == '|' && y != '|') { value = value | eval(++s, 6); continue; }
if(depth >= 5) break;
if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; }
if(depth >= 4) break;
if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; }
if(depth >= 3) break;
if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; }
if(x == '?') {
int lhs = eval(++s, 2);
if(*s != ':') throw "mismatched_ternary";
int rhs = eval(++s, 2);
value = value ? lhs : rhs;
continue;
}
if(depth >= 2) break;
if(depth > 0 && x == ')') break;
throw "unrecognized_token";
}
return value;
}
bool strint(const char *s, int &result) {
try {
result = eval_integer(s);
return true;
} catch(const char*) {
result = 0;
return false;
}
}
bool strmath(const char *s, int &result) {
try {
result = eval(s);
return true;
} catch(const char*) {
result = 0;
return false;
}
}
}
#endif

43
bsnes/nall/string/utf8.hpp Executable file
View File

@ -0,0 +1,43 @@
#ifdef NALL_STRING_INTERNAL_HPP
namespace nall {
struct UTF8 {
unsigned size; //size of encoded codepoint
uint64_t data; //encoded codepoint
unsigned codepoint; //decoded codepoint
};
inline UTF8 utf8_read(const char *s) {
UTF8 utf8;
if((*s & 0xfe) == 0xfc) utf8.size = 6;
else if((*s & 0xfc) == 0xf8) utf8.size = 5;
else if((*s & 0xf8) == 0xf0) utf8.size = 4;
else if((*s & 0xf0) == 0xe0) utf8.size = 3;
else if((*s & 0xe0) == 0xc0) utf8.size = 2;
else utf8.size = 1;
utf8.data = 0;
for(unsigned n = 0; n < utf8.size; n++) {
utf8.data = (utf8.data << 8) | (uint8_t)s[n];
}
static uint8_t mask[] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
utf8.codepoint = s[0] & mask[utf8.size];
for(unsigned n = 1; n < utf8.size; n++) {
utf8.codepoint = (utf8.codepoint << 6) | (s[n] & 0x3f);
}
return utf8;
}
inline void utf8_write(char *s, const UTF8 &utf8) {
for(signed n = utf8.size - 1, shift = 0; n >= 0; n--, shift += 8) {
s[n] = utf8.data >> shift;
}
}
}
#endif

View File

@ -2,7 +2,8 @@ snes_objects := snes-interface snes-system snes-controller
snes_objects += snes-cartridge snes-cheat
snes_objects += snes-memory snes-cpucore snes-smpcore
snes_objects += snes-cpu snes-smp snes-dsp snes-ppu
snes_objects += snes-icd2 snes-nss snes-superfx snes-sa1 snes-necdsp snes-hitachidsp
snes_objects += snes-icd2 snes-nss snes-superfx snes-sa1
snes_objects += snes-necdsp snes-hitachidsp snes-armdsp
snes_objects += snes-bsx snes-srtc snes-sdd1 snes-spc7110
snes_objects += snes-obc1 snes-st0018 snes-sufamiturbo
snes_objects += snes-msu1 snes-link
@ -47,6 +48,7 @@ obj/snes-superfx.o : $(snes)/chip/superfx/superfx.cpp $(call rwildcard,$(snes
obj/snes-sa1.o : $(snes)/chip/sa1/sa1.cpp $(call rwildcard,$(snes)/chip/sa1/)
obj/snes-necdsp.o : $(snes)/chip/necdsp/necdsp.cpp $(call rwildcard,$(snes)/chip/necdsp/)
obj/snes-hitachidsp.o : $(snes)/chip/hitachidsp/hitachidsp.cpp $(call rwildcard,$(snes)/chip/hitachidsp/)
obj/snes-armdsp.o : $(snes)/chip/armdsp/armdsp.cpp $(call rwildcard,$(snes)/chip/armdsp/)
obj/snes-bsx.o : $(snes)/chip/bsx/bsx.cpp $(call rwildcard,$(snes)/chip/bsx/)
obj/snes-srtc.o : $(snes)/chip/srtc/srtc.cpp $(snes)/chip/srtc/*
obj/snes-sdd1.o : $(snes)/chip/sdd1/sdd1.cpp $(snes)/chip/sdd1/*

View File

@ -22,6 +22,7 @@ void Cartridge::load(Mode cartridge_mode, const char *markup) {
has_sa1 = false;
has_necdsp = false;
has_hitachidsp = false;
has_armdsp = false;
has_srtc = false;
has_sdd1 = false;
has_spc7110 = false;

View File

@ -38,6 +38,7 @@ struct Cartridge : property<Cartridge> {
readonly<bool> has_sa1;
readonly<bool> has_necdsp;
readonly<bool> has_hitachidsp;
readonly<bool> has_armdsp;
readonly<bool> has_srtc;
readonly<bool> has_sdd1;
readonly<bool> has_spc7110;
@ -101,6 +102,7 @@ private:
void parse_markup_sa1(XML::Node&);
void parse_markup_necdsp(XML::Node&);
void parse_markup_hitachidsp(XML::Node&);
void parse_markup_armdsp(XML::Node&);
void parse_markup_bsx(XML::Node&);
void parse_markup_sufamiturbo(XML::Node&);
void parse_markup_srtc(XML::Node&);

View File

@ -16,6 +16,7 @@ void Cartridge::parse_markup(const char *markup) {
parse_markup_superfx(cartridge["superfx"]);
parse_markup_necdsp(cartridge["necdsp"]);
parse_markup_hitachidsp(cartridge["hitachidsp"]);
parse_markup_armdsp(cartridge["armdsp"]);
parse_markup_bsx(cartridge["bsx"]);
parse_markup_sufamiturbo(cartridge["sufamiturbo"]);
parse_markup_srtc(cartridge["srtc"]);
@ -238,7 +239,7 @@ void Cartridge::parse_markup_necdsp(XML::Node &root) {
for(unsigned n = 0; n < promsize; n++) necdsp.programROM[n] = fp.readm(3);
for(unsigned n = 0; n < dromsize; n++) necdsp.dataROM[n] = fp.readm(2);
if(sha256 != "") {
if(!sha256.empty()) {
//XML file specified SHA256 sum for program. Verify file matches the hash.
fp.seek(0);
uint8_t data[filesize];
@ -298,7 +299,7 @@ void Cartridge::parse_markup_hitachidsp(XML::Node &root) {
} else {
for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = fp.readl(3);
if(sha256 != "") {
if(!sha256.empty()) {
//XML file specified SHA256 sum for program. Verify file matches the hash.
fp.seek(0);
uint8 data[3072];
@ -331,6 +332,41 @@ void Cartridge::parse_markup_hitachidsp(XML::Node &root) {
}
}
void Cartridge::parse_markup_armdsp(XML::Node &root) {
if(root.exists() == false) return;
has_armdsp = true;
for(auto &byte : armdsp.programROM) byte = 0x00;
string firmware = root["firmware"].data;
string sha256 = root["sha256"].data;
string path = interface->path(Slot::Base, firmware);
file fp;
if(fp.open(path, file::mode::read) == false) {
interface->message({ "Warning: ARM DSP firmware ", firmware, " is missing." });
} else if(fp.size() != 128 * 1024) {
interface->message({ "Warning: ARM DSP firmware ", firmware, " is of the wrong file size." });
fp.close();
} else {
for(auto &byte : armdsp.programROM) byte = fp.read();
if(!sha256.empty()) {
if(sha256 != nall::sha256(armdsp.programROM, 128 * 1024)) {
interface->message({ "Warning: ARM DSP firmware ", firmware, " SHA256 sum is incorrect." });
}
}
fp.close();
}
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({ &ArmDSP::mmio_read, &armdsp }, { &ArmDSP::mmio_write, &armdsp });
parse_markup_map(m, node);
mapping.append(m);
}
}
void Cartridge::parse_markup_bsx(XML::Node &root) {
if(root.exists() == false) return;
if(mode != Mode::BsxSlotted && mode != Mode::Bsx) return;

View File

@ -0,0 +1,65 @@
#include <snes/snes.hpp>
#define ARMDSP_CPP
namespace SNES {
#include "opcodes.cpp"
#include "memory.cpp"
#include "disassembler.cpp"
#include "serialization.cpp"
ArmDSP armdsp;
void ArmDSP::Enter() { armdsp.enter(); }
void ArmDSP::enter() {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
step(16);
synchronize_cpu();
print(disassemble_opcode(r[15]), "\n", disassemble_registers(), "\n");
instruction = bus_read(r[15]);
r[15] += 8; //pipeline adjust
if((instruction & 0x0e000000) == 0x0a000000) { op_branch(); continue; }
if((instruction & 0x0e000000) == 0x02000000) { op_data_immediate(); r[15] -= 4; continue; }
print("* ARM unknown instruction\n");
while(true) {
step(21477272);
synchronize_cpu();
}
}
}
uint8 ArmDSP::mmio_read(unsigned addr) {
//print("* r", hex<4>(addr), "\n");
return 0x00;
}
void ArmDSP::mmio_write(unsigned addr, uint8 data) {
print("* w", hex<4>(addr), "w = ", hex<2>(data), "\n");
}
void ArmDSP::init() {
}
void ArmDSP::load() {
}
void ArmDSP::unload() {
}
void ArmDSP::power() {
}
void ArmDSP::reset() {
create(ArmDSP::Enter, 21477272);
for(auto &rd : r) rd = 0x00000000;
}
}

View File

@ -0,0 +1,41 @@
//ARM v3 (ARM6?)
struct ArmDSP : public Coprocessor {
uint8 programROM[128 * 1024];
#include "registers.hpp"
static void Enter();
void enter();
void init();
void load();
void unload();
void power();
void reset();
uint8 mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8 data);
//opcodes.cpp
bool condition();
void opcode(uint32 &rd, uint32 &rn, uint32 shifter);
void flags(uint32 rd);
void op_branch();
void op_data_immediate();
void op_move_immediate_offset();
//memory.cpp
uint32 bus_read(uint32 addr);
void bus_write(uint32 addr, uint32 data);
//disassembler.cpp
string disassemble_opcode(uint32 pc);
string disassemble_registers();
//serialization.cpp
void serialize(serializer&);
};
extern ArmDSP armdsp;

View File

@ -0,0 +1,46 @@
#ifdef ARMDSP_CPP
string ArmDSP::disassemble_opcode(uint32 pc) {
static string conditions[] = { "eq", "ne", "cs", "cc", "mi" ,"pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", "al", "nv" };
static string opcodes[] = { "and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc", "tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn" };
string output{hex<8>(pc), " "};
uint32 instruction = bus_read(pc);
output.append(hex<8>(instruction), " ");
uint4 condition = instruction >> 28;
uint4 opcode = instruction >> 21;
uint4 rn = instruction >> 16;
uint4 rd = instruction >> 12;
uint4 rs = instruction >> 8;
if((instruction & 0x0e000000) == 0x0a000000) {
output.append("b");
if(condition != 14) output.append(conditions[condition]);
output.append(" 0x", hex<8>(pc + 8 + (int24)instruction * 4));
return output;
}
if((instruction & 0x0e000000) == 0x02000000) {
uint5 rotate = 2 * (uint4)(instruction >> 8);
uint32 immediate = (uint8)instruction;
immediate = (immediate >> rotate) | (immediate << (32 - rotate));
output.append(opcodes[opcode], " r", rd, ",#0x", hex<8>(immediate));
return output;
}
output.append("???");
return output;
}
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",
"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"
};
}
#endif

View File

@ -0,0 +1,18 @@
#ifdef ARMDSP_CPP
uint32 ArmDSP::bus_read(uint32 addr) {
if(addr >= 0x00000000 && addr <= 0x0001ffff) {
addr &= 0x0001ffff;
return (programROM[addr + 0] << 0)
+ (programROM[addr + 1] << 8)
+ (programROM[addr + 2] << 16)
+ (programROM[addr + 3] << 24);
}
return 0x00000000;
}
void ArmDSP::bus_write(uint32 addr, uint32 data) {
}
#endif

View File

@ -0,0 +1,96 @@
#ifdef ARMDSP_CPP
bool ArmDSP::condition() {
switch((uint4)(instruction >> 28)) { default:
case 0: return cpsr.z == 1; //EQ (equal)
case 1: return cpsr.z == 0; //NE (not equal)
case 2: return cpsr.c == 1; //CS (carry set)
case 3: return cpsr.c == 0; //CC (carry clear)
case 4: return cpsr.n == 1; //MI (negative)
case 5: return cpsr.n == 0; //PL (positive)
case 6: return cpsr.v == 1; //VS (overflow)
case 7: return cpsr.v == 0; //VC (no overflow)
case 8: return cpsr.c == 1 && cpsr.z == 0; //HI (unsigned higher)
case 9: return cpsr.c == 0 || cpsr.z == 1; //LS (unsigned lower or same)
case 10: return cpsr.n == cpsr.v; //GE (signed greater than or equal)
case 11: return cpsr.n != cpsr.v; //LT (signed less than)
case 12: return cpsr.z == 0 && cpsr.n == cpsr.v; //GT (signed greater than)
case 13: return cpsr.z == 1 || cpsr.n != cpsr.v; //LE (signed less than or equal)
case 14: return true; //AL (always)
case 15: return false; //NV (never)
}
}
void ArmDSP::opcode(uint32 &rd, uint32 &rn, uint32 shifter) {
switch((uint4)(instruction >> 21)) {
case 0: rd = rn & shifter; break; //AND (logical and)
case 1: rd = rn & shifter; break; //EOR (logical exclusive or)
case 2: rd = rn - shifter; break; //SUB (subtract)
case 3: rd = shifter - rn; break; //RSB (reverse subtract)
case 4: rd = rn + shifter; break; //ADD (add)
case 5: rd = rn + shifter + cpsr.c; break; //ADC (add with carry)
case 6: rd = rn - shifter - !cpsr.c; break; //SBC (subtract with carry)
case 7: rd = shifter - rn - !cpsr.c; break; //RSC (reverse subtract with carry)
case 8: flags(rn & shifter); break; //TST (test)
case 9: flags(rn ^ shifter); break; //TEQ (test equivalence)
case 10: flags(rn - shifter); break; //CMP (compare)
case 11: flags(rn + shifter); break; //CMN (compare negated)
case 12: rd = rn | shifter; break; //ORR (logical inclusive or)
case 13: rd = shifter; break; //MOV (move)
case 14: rd = rn & ~shifter; break; //BIC (bit clear)
case 15: rd = ~shifter; //MVN (move not)
}
}
void ArmDSP::flags(uint32 rd) {
cpsr.n = rd & 0x80000000;
cpsr.z = rd == 0;
}
//CCCC 101L DDDD DDDD DDDD DDDD DDDD DDDD
//C = condition
//L = link
//D = displacement (24-bit signed)
void ArmDSP::op_branch() {
if(!condition()) return;
int24 displacement = (int24)instruction;
r[15] += displacement * 4;
}
//CCCC 001O OOOS NNNN DDDD RRRR IIII IIII
//C = condition
//O = opcode
//S = update flags
//N = Rn
//D = Rd
//R = rotate
//I = immediate
void ArmDSP::op_data_immediate() {
if(!condition()) return;
bool s = (uint1)(instruction >> 20);
uint4 n = (uint4)(instruction >> 16);
uint4 d = (uint4)(instruction >> 12);
uint5 rotate = 2 * (uint4)(instruction >> 8);
uint32 immediate = (uint8)instruction;
immediate = (immediate >> rotate) | (immediate << (32 - rotate));
opcode(r[d], r[n], immediate);
}
//CCCC 010P UBWL NNNN DDDD IIII IIII
//C = condition
//P = pre/post-indexed addressing
//U = add/sub offset to base
//B = byte/word access
//W = ...
//L = load/save
//N = Rn
//D = Rd
//I = immediate
void ArmDSP::op_move_immediate_offset() {
if(!condition()) return;
}
#endif

View File

@ -0,0 +1,41 @@
//Exceptions:
//00000000 = reset
//00000004 = undefined instruction
//00000008 = software interrupt
//0000000c = prefetch abort
//00000010 = data abort
//00000018 = IRQ (interrupt)
//0000001c = FIQ (fast interrupt)
struct CPSR {
bool n;
bool z;
bool c;
bool v;
bool i;
bool f;
uint5 m;
operator unsigned() const {
return (n << 31) | (z << 30) | (c << 29) | (v << 28) | (i << 7) | (f << 6) | (m << 0);
}
CPSR& operator=(uint32 data) {
n = data & 0x80000000;
z = data & 0x40000000;
c = data & 0x20000000;
v = data & 0x10000000;
i = data & 0x00000080;
f = data & 0x00000040;
m = data & 0x0000001f;
return *this;
}
} cpsr;
//r13 = SP (stack pointer)
//r14 = LR (link register)
//r15 = PC (program counter)
uint32 r[16];
uint32 instruction;
uint32 prefetch;

View File

@ -0,0 +1,7 @@
#ifdef ARMDSP_CPP
void ArmDSP::serialize(serializer &s) {
Processor::serialize(s);
}
#endif

View File

@ -12,6 +12,7 @@ struct Coprocessor : Processor {
#include <snes/chip/sa1/sa1.hpp>
#include <snes/chip/necdsp/necdsp.hpp>
#include <snes/chip/hitachidsp/hitachidsp.hpp>
#include <snes/chip/armdsp/armdsp.hpp>
#include <snes/chip/bsx/bsx.hpp>
#include <snes/chip/srtc/srtc.hpp>
#include <snes/chip/sdd1/sdd1.hpp>

View File

@ -17,8 +17,10 @@
// GND GND
void USART::enter() {
init({ &USART::usleep, this }, { &USART::read, this }, { &USART::write, this });
main();
if(init && main) {
init({ &USART::usleep, this }, { &USART::read, this }, { &USART::write, this });
main();
}
while(true) step(1000000); //fallback; main should never return
}

View File

@ -65,6 +65,7 @@ void System::serialize_all(serializer &s) {
if(cartridge.has_sa1()) sa1.serialize(s);
if(cartridge.has_necdsp()) necdsp.serialize(s);
if(cartridge.has_hitachidsp()) hitachidsp.serialize(s);
if(cartridge.has_armdsp()) armdsp.serialize(s);
if(cartridge.has_srtc()) srtc.serialize(s);
if(cartridge.has_sdd1()) sdd1.serialize(s);
if(cartridge.has_spc7110()) spc7110.serialize(s);

View File

@ -72,6 +72,7 @@ void System::init() {
sa1.init();
necdsp.init();
hitachidsp.init();
armdsp.init();
bsxsatellaview.init();
bsxcartridge.init();
bsxflash.init();
@ -115,6 +116,7 @@ void System::load() {
if(cartridge.has_sa1()) sa1.load();
if(cartridge.has_necdsp()) necdsp.load();
if(cartridge.has_hitachidsp()) hitachidsp.load();
if(cartridge.has_armdsp()) armdsp.load();
if(cartridge.has_srtc()) srtc.load();
if(cartridge.has_sdd1()) sdd1.load();
if(cartridge.has_spc7110()) spc7110.load();
@ -141,6 +143,7 @@ void System::unload() {
if(cartridge.has_sa1()) sa1.unload();
if(cartridge.has_necdsp()) necdsp.unload();
if(cartridge.has_hitachidsp()) hitachidsp.unload();
if(cartridge.has_armdsp()) armdsp.unload();
if(cartridge.has_srtc()) srtc.unload();
if(cartridge.has_sdd1()) sdd1.unload();
if(cartridge.has_spc7110()) spc7110.unload();
@ -179,6 +182,7 @@ void System::power() {
if(cartridge.has_sa1()) sa1.power();
if(cartridge.has_necdsp()) necdsp.power();
if(cartridge.has_hitachidsp()) hitachidsp.power();
if(cartridge.has_armdsp()) armdsp.power();
if(cartridge.has_srtc()) srtc.power();
if(cartridge.has_sdd1()) sdd1.power();
if(cartridge.has_spc7110()) spc7110.power();
@ -209,6 +213,7 @@ void System::reset() {
if(cartridge.has_sa1()) sa1.reset();
if(cartridge.has_necdsp()) necdsp.reset();
if(cartridge.has_hitachidsp()) hitachidsp.reset();
if(cartridge.has_armdsp()) armdsp.reset();
if(cartridge.has_srtc()) srtc.reset();
if(cartridge.has_sdd1()) sdd1.reset();
if(cartridge.has_spc7110()) spc7110.reset();
@ -224,6 +229,7 @@ void System::reset() {
if(cartridge.has_sa1()) cpu.coprocessors.append(&sa1);
if(cartridge.has_necdsp()) cpu.coprocessors.append(&necdsp);
if(cartridge.has_hitachidsp()) cpu.coprocessors.append(&hitachidsp);
if(cartridge.has_armdsp()) cpu.coprocessors.append(&armdsp);
if(cartridge.has_msu1()) cpu.coprocessors.append(&msu1);
if(cartridge.has_link()) cpu.coprocessors.append(&link);