Update to v087r09 release.

byuu says:

Split apart necdsp: core is now in processor/upd96050 (wish I had
a better name for it, but there's no family name that is maskable.)
I would like to support the uPD7720 in the core as well, just for
completeness' sake, but I'll have to modify the decoder to drop one bit
from each mode.
So ... I'll do that later. Worst part is even if I do, I won't be able
to test it :(

Added all of Cydrak's changes. I also simplified LDMIA/STMIA and
PUSH/POP by merging the outer loops.
Probably infinitesimally slower, but less code is nicer. Maybe GCC
optimization will expand it, who knows.
This commit is contained in:
Tim Allen 2012-03-26 21:13:02 +11:00
parent 395e5a5639
commit e16dd58184
31 changed files with 547 additions and 478 deletions

View File

@ -92,7 +92,7 @@ sync:
rm -r phoenix/nall
rm -r phoenix/test
archive-all:
archive:
if [ -f bsnes.tar.bz2 ]; then rm bsnes.tar.bz2; fi
tar -cjf bsnes.tar.bz2 `ls`

View File

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

View File

@ -19,6 +19,11 @@ void APU::step(unsigned clocks) {
}
uint32 APU::read(uint32 addr, uint32 size) {
if(addr == 0x04000088) {
//SOUNDBIAS
return 0x0200;
}
return 0u;
}
@ -27,6 +32,8 @@ void APU::write(uint32 addr, uint32 size, uint32 word) {
void APU::power() {
create(APU::Enter, 16777216);
bus.mmio[0x0088] = this;
}
}

View File

@ -50,7 +50,6 @@ void CPU::power() {
}
uint32 CPU::read(uint32 addr, uint32 size) {
if(addr == 0x04000300) return prng() & 1;
return 0u;
}

View File

@ -5,8 +5,8 @@ namespace GBA {
Bus bus;
struct UnmappedMemory : Memory {
uint32 read(uint32 addr, uint32 size) { return 0u; }
void write(uint32 addr, uint32 size, uint32 word) {}
uint32 read(uint32 addr, uint32 size) { print(hex<8>(addr), ":", decimal<2>(size), "\n"); return 0u; }
void write(uint32 addr, uint32 size, uint32 word) { print(hex<8>(addr), ":", decimal<2>(size), "=", hex<8>(word), "\n"); }
};
static UnmappedMemory unmappedMemory;

View File

@ -27,7 +27,7 @@ struct map {
signed middle = (first + last) / 2;
if(name < list[middle].name) last = middle - 1; //search lower half
else if(list[middle].name < name) first = middle + 1; //search upper half
else return { true, middle }; //match found
else return { true, (unsigned)middle }; //match found
}
return { false, 0u };
}

27
bsnes/nall/udl.hpp Executable file
View File

@ -0,0 +1,27 @@
#ifndef NALL_UDL_HPP
#define NALL_UDL_HPP
//user-defined literals
#include <nall/atoi.hpp>
namespace nall {
constexpr inline uintmax_t operator"" _b(const char *n) { return binary(n); }
//convert to bytes
constexpr inline uintmax_t operator"" _kb(unsigned long long n) { return 1024 * n; }
constexpr inline uintmax_t operator"" _mb(unsigned long long n) { return 1024 * 1024 * n; }
constexpr inline uintmax_t operator"" _gb(unsigned long long n) { return 1024 * 1024 * 1024 * n; }
//convert to bits
constexpr inline uintmax_t operator"" _kbit(unsigned long long n) { return 1024 * n / 8; }
constexpr inline uintmax_t operator"" _mbit(unsigned long long n) { return 1024 * 1024 * n / 8; }
constexpr inline uintmax_t operator"" _gbit(unsigned long long n) { return 1024 * 1024 * 1024 * n / 8; }
//convert to hz
constexpr inline uintmax_t operator"" _khz(long double n) { return n * 1000; }
constexpr inline uintmax_t operator"" _mhz(long double n) { return n * 1000000; }
constexpr inline uintmax_t operator"" _ghz(long double n) { return n * 1000000000; }
}
#endif

View File

@ -52,13 +52,13 @@ struct Color {
struct Position {
signed x, y;
inline Position() : x(0), y(0) {}
inline Position(signed x, signed y) : x(x), y(y) {}
template<typename X, typename Y> inline Position(X x, Y y) : x(x), y(y) {}
};
struct Size {
unsigned width, height;
inline Size() : width(0), height(0) {}
inline Size(unsigned width, unsigned height) : width(width), height(height) {}
template<typename W, typename H> inline Size(W width, H height) : width(width), height(height) {}
};
struct Geometry {
@ -69,7 +69,7 @@ struct Geometry {
nall::string text() const;
inline Geometry() : x(0), y(0), width(0), height(0) {}
inline Geometry(const Position& position, const Size& size) : x(position.x), y(position.y), width(size.width), height(size.height) {}
inline Geometry(signed x, signed y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
template<typename X, typename Y, typename W, typename H> inline Geometry(X x, Y y, W width, H height) : x(x), y(y), width(width), height(height) {}
Geometry(const nall::string &text);
};

View File

@ -100,7 +100,8 @@ struct pWindow : public pObject {
GtkWidget *statusContainer;
GtkWidget *menu;
GtkWidget *status;
GdkEventConfigure lastConfigure;
GtkAllocation lastAllocation;
bool onSizePending;
void append(Layout &layout);
void append(Menu &menu);

View File

@ -53,36 +53,27 @@ static gboolean Window_configure(GtkWidget *widget, GdkEvent *event, Window *win
settings->save();
}
Geometry geometry = {
client.x,
client.y + window->p.menuHeight(),
client.width,
client.height - window->p.menuHeight() - window->p.statusHeight()
};
//move
if(event->configure.x != window->p.lastConfigure.x
|| event->configure.y != window->p.lastConfigure.y
) {
if(geometry.x != window->state.geometry.x || geometry.y != window->state.geometry.y) {
if(window->state.fullScreen == false) {
window->state.geometry.x = client.x;
window->state.geometry.y = client.y + window->p.menuHeight();
window->state.geometry.x = geometry.x;
window->state.geometry.y = geometry.y;
}
if(window->p.locked == false && window->onMove) window->onMove();
}
//size
if(event->configure.width != window->p.lastConfigure.width
|| event->configure.height != window->p.lastConfigure.height
) {
if(window->state.fullScreen == false) {
window->state.geometry.width = client.width;
window->state.geometry.height = client.height - window->p.menuHeight() - window->p.statusHeight();
if(geometry.width != window->state.geometry.width || geometry.height != window->state.geometry.height) {
window->p.onSizePending = true;
}
for(auto &layout : window->state.layout) {
Geometry geometry = window->geometry();
geometry.x = geometry.y = 0;
layout.setGeometry(geometry);
}
if(window->p.locked == false && window->onSize) window->onSize();
}
window->p.lastConfigure = event->configure;
return false;
}
@ -98,6 +89,33 @@ static gboolean Window_keyReleaseEvent(GtkWidget *widget, GdkEventKey *event, Wi
return false;
}
static void Window_sizeAllocate(GtkWidget *widget, GtkAllocation *allocation, Window *window) {
//size-allocate sent from gtk_fixed_move(); detect if layout unchanged and return
if(allocation->width == window->p.lastAllocation.width
&& allocation->height == window->p.lastAllocation.height) return;
window->state.geometry.width = allocation->width;
window->state.geometry.height = allocation->height;
for(auto &layout : window->state.layout) {
Geometry geometry = window->geometry();
geometry.x = geometry.y = 0;
layout.setGeometry(geometry);
}
if(window->p.onSizePending && window->p.locked == false && window->onSize) {
window->p.onSizePending = false;
window->onSize();
}
window->p.lastAllocation = *allocation;
}
static void Window_sizeRequest(GtkWidget *widget, GtkRequisition *requisition, Window *window) {
requisition->width = window->state.geometry.width;
requisition->height = window->state.geometry.height;
}
void pWindow::append(Layout &layout) {
Geometry geometry = this->geometry();
geometry.x = geometry.y = 0;
@ -131,7 +149,13 @@ Color pWindow::backgroundColor() {
}
Geometry pWindow::frameMargin() {
if(window.state.fullScreen) return { 0, menuHeight(), 0, menuHeight() + statusHeight() };
if(window.state.fullScreen) return {
0,
menuHeight(),
0,
menuHeight() + statusHeight()
};
return {
settings->frameGeometryX,
settings->frameGeometryY + menuHeight(),
@ -145,9 +169,13 @@ bool pWindow::focused() {
}
Geometry pWindow::geometry() {
if(window.state.fullScreen == true) {
return { 0, menuHeight(), Desktop::size().width, Desktop::size().height - menuHeight() - statusHeight() };
if(window.state.fullScreen == true) return {
0,
menuHeight(),
Desktop::size().width,
Desktop::size().height - menuHeight() - statusHeight()
};
return window.state.geometry;
}
@ -178,38 +206,23 @@ void pWindow::setFocused() {
void pWindow::setFullScreen(bool fullScreen) {
if(fullScreen == false) {
gtk_window_unfullscreen(GTK_WINDOW(widget));
gtk_window_set_resizable(GTK_WINDOW(widget), window.state.resizable);
gtk_widget_set_size_request(widget, -1, -1);
gdk_display_sync(gtk_widget_get_display(widget));
setGeometry(window.state.geometry);
} else {
gtk_window_fullscreen(GTK_WINDOW(widget));
gtk_widget_set_size_request(widget, Desktop::size().width, Desktop::size().height);
gtk_window_set_resizable(GTK_WINDOW(widget), false);
}
gdk_display_sync(gtk_widget_get_display(widget));
}
void pWindow::setGeometry(const Geometry &geometry) {
OS::processEvents();
Geometry margin = frameMargin();
gtk_window_move(GTK_WINDOW(widget), geometry.x - margin.x, geometry.y - margin.y);
//GdkGeometry geom;
//geom.min_width = 1;
//geom.min_height = 1;
//gtk_window_set_geometry_hints(GTK_WINDOW(widget), GTK_WIDGET(widget), &geom, GDK_HINT_MIN_SIZE);
GdkGeometry geom;
geom.min_width = window.state.resizable ? 1 : window.state.geometry.width;
geom.min_height = window.state.resizable ? 1 : window.state.geometry.height;
gtk_window_set_geometry_hints(GTK_WINDOW(widget), GTK_WIDGET(widget), &geom, GDK_HINT_MIN_SIZE);
gtk_window_set_policy(GTK_WINDOW(widget), true, true, false);
//gtk_window_set_policy(GTK_WINDOW(widget), true, true, false);
gtk_widget_set_size_request(formContainer, geometry.width, geometry.height);
gtk_window_resize(GTK_WINDOW(widget), geometry.width, geometry.height + menuHeight() + statusHeight());
for(auto &layout : window.state.layout) {
Geometry geometry = this->geometry();
geometry.x = geometry.y = 0;
layout.setGeometry(geometry);
}
}
void pWindow::setMenuFont(const string &font) {
@ -244,6 +257,19 @@ void pWindow::setTitle(const string &text) {
void pWindow::setVisible(bool visible) {
gtk_widget_set_visible(widget, visible);
if(visible) {
if(gtk_widget_get_visible(menu)) {
GtkAllocation allocation;
gtk_widget_get_allocation(menu, &allocation);
settings->menuGeometryHeight = allocation.height;
}
if(gtk_widget_get_visible(status)) {
GtkAllocation allocation;
gtk_widget_get_allocation(status, &allocation);
settings->statusGeometryHeight = allocation.height;
}
}
}
void pWindow::setWidgetFont(const string &font) {
@ -253,7 +279,10 @@ void pWindow::setWidgetFont(const string &font) {
}
void pWindow::constructor() {
memset(&lastConfigure, 0, sizeof(GdkEventConfigure));
lastAllocation.width = 0;
lastAllocation.height = 0;
onSizePending = false;
widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
if(gdk_screen_is_composited(gdk_screen_get_default())) {
@ -289,6 +318,7 @@ void pWindow::constructor() {
gtk_widget_show(statusContainer);
setTitle("");
setResizable(window.state.resizable);
setGeometry(window.state.geometry);
setMenuFont("Sans, 8");
setStatusFont("Sans, 8");
@ -298,6 +328,9 @@ void pWindow::constructor() {
g_signal_connect(G_OBJECT(widget), "configure-event", G_CALLBACK(Window_configure), (gpointer)&window);
g_signal_connect(G_OBJECT(widget), "key-press-event", G_CALLBACK(Window_keyPressEvent), (gpointer)&window);
g_signal_connect(G_OBJECT(widget), "key-release-event", G_CALLBACK(Window_keyPressEvent), (gpointer)&window);
g_signal_connect(G_OBJECT(formContainer), "size-allocate", G_CALLBACK(Window_sizeAllocate), (gpointer)&window);
g_signal_connect(G_OBJECT(formContainer), "size-request", G_CALLBACK(Window_sizeRequest), (gpointer)&window);
}
unsigned pWindow::menuHeight() {

View File

@ -1,3 +1,9 @@
//Qt 4.8.0 and earlier improperly define the QLOCATION macro
//in C++11, it is detected as a malformed user-defined literal
//below is a workaround to fix compilation errors caused by this
#undef QLOCATION
#define QLOCATION "\0" __FILE__ ":" QTOSTRING(__LINE__)
#include "platform.moc.hpp"
#include "platform.moc"
#include "utility.cpp"

View File

@ -1,7 +1,7 @@
/****************************************************************************
** Meta object code from reading C++ file 'platform.moc.hpp'
**
** Created: Fri Feb 10 22:23:15 2012
** Created: Thu Mar 22 11:27:37 2012
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3)
**
** WARNING! All changes made in this file will be lost!

View File

@ -1,8 +1,10 @@
processor_objects :=
processor_objects += $(if $(findstring arm,$(processors)),processor-arm)
processor_objects += $(if $(findstring hg51b,$(processors)),processor-hg51b)
processor_objects += $(if $(findstring upd96050,$(processors)),processor-upd96050)
objects += $(processor_objects)
processor := processor
obj/processor-arm.o: $(processor)/arm/arm.cpp $(call rwildcard,$(processor)/arm)
obj/processor-hg51b.o: $(processor)/hg51b/hg51b.cpp $(call rwildcard,$(processor)/hg51b)
obj/processor-upd96050.o: $(processor)/upd96050/upd96050.cpp $(call rwildcard,$(processor)/upd96050)

View File

@ -568,13 +568,13 @@ string ARM::disassemble_thumb_instruction(uint32 pc) {
}
//move_multiple()
//(ldmia,stmdb) rn,{r...}
//(ldmia,stmia) rn,{r...}
if((instruction & 0xf000) == 0xc000) {
uint1 load = instruction >> 11;
uint3 rn = instruction >> 8;
uint8 list = instruction;
output.append(load ? "ldmia " : "stmdb ", registers[rn], "!,{");
output.append(load ? "ldmia " : "stmia ", registers[rn], "!,{");
for(unsigned l = 0; l < 8; l++) {
if(list & (1 << l)) output.append(registers[l], ",");
}

View File

@ -30,7 +30,7 @@ void ARM::arm_step() {
if((instruction() & 0x0fb000f0) == 0x01000000) { arm_op_move_to_register_from_status(); return; }
if((instruction() & 0x0fb000f0) == 0x01000090) { arm_op_memory_swap(); return; }
if((instruction() & 0x0fb000f0) == 0x01200000) { arm_op_move_to_status_from_register(); return; }
if((instruction() & 0x0ff000f0) == 0x01200010) { arm_op_branch_exchange_register(); return; } //ARMv4
if((instruction() & 0x0ff000f0) == 0x01200010) { arm_op_branch_exchange_register(); return; } //ARMv4+
if((instruction() & 0x0fb00000) == 0x03200000) { arm_op_move_to_status_from_immediate(); return; }
if((instruction() & 0x0e000010) == 0x00000000) { arm_op_data_immediate_shift(); return; }
@ -289,8 +289,8 @@ void ARM::arm_op_move_to_status_from_register() {
void ARM::arm_op_branch_exchange_register() {
uint4 m = instruction();
r(15) = r(m);
cpsr().t = r(m) & 1;
r(15) = r(m);
}
//msr{condition} (c,s)psr:{fields},#immediate

View File

@ -96,15 +96,6 @@ uint32 ARM::thumb_tst(uint32 modify) {
return modify;
}
void ARM::thumb_cmp(uint32 source, uint32 modify) {
uint32 result = source - modify;
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);
}
uint32 ARM::thumb_add(uint32 source, uint32 modify, bool carry) {
uint32 result = source + modify + carry;
uint32 overflow = ~(source ^ modify) & (source ^ result);
@ -116,13 +107,7 @@ uint32 ARM::thumb_add(uint32 source, uint32 modify, bool carry) {
}
uint32 ARM::thumb_sub(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;
thumb_add(source, ~modify, carry);
}
uint32 ARM::thumb_lsl(uint32 source, uint32 modify) {
@ -240,7 +225,7 @@ void ARM::thumb_op_immediate() {
switch(opcode) {
case 0: r(d) = thumb_tst( immediate); break;
case 1: thumb_cmp(r(d), 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;
}
@ -265,8 +250,8 @@ void ARM::thumb_op_alu() {
void ARM::thumb_op_branch_exchange() {
uint4 m = instruction() >> 3;
r(15) = r(m);
cpsr().t = r(m) & 1;
r(15) = r(m);
}
//{opcode} rd,rm
@ -423,34 +408,30 @@ void ARM::thumb_op_stack_multiple() {
uint1 branch = instruction() >> 8;
uint8 list = instruction();
if(load == 1) {
uint32 sp = 0;
if(load == 1) sp = r(13);
if(load == 0) sp = r(13) - (bit::count(list) + branch) * 4;
for(unsigned l = 0; l < 8; l++) {
if(list & (1 << l)) {
r(l) = bus_read(r(13), Word);
r(13) += 4;
}
}
if(branch) {
r(15) = bus_read(r(13), Word);
r(13) += 4;
if(load == 1) r(l) = bus_read(sp, Word); //POP
if(load == 0) bus_write(sp, Word, r(l)); //PUSH
sp += 4;
}
}
if(load == 0) {
for(unsigned l = 0; l < 8; l++) {
if(list & (1 << l)) {
r(13) -= 4;
bus_write(r(13), Word, r(l));
}
}
if(branch) {
r(13) -= 4;
bus_write(r(13), Word, r(14));
}
}
//note: ARMv5+ POP sets cpsr().t
if(load == 1) r(15) = bus_read(sp, Word); //POP
if(load == 0) bus_write(sp, Word, r(14)); //PUSH
sp += 4;
}
//(ldmia,stmdb) rn!,{r...}
if(load == 1) r(13) += (bit::count(list) + branch) * 4;
if(load == 0) r(13) -= (bit::count(list) + branch) * 4;
}
//(ldmia,stmia) rn!,{r...}
//1100 lnnn llll llll
//l = load (0 = save)
//n = rn
@ -460,25 +441,15 @@ void ARM::thumb_op_move_multiple() {
uint3 n = instruction() >> 8;
uint8 list = instruction();
if(load == 1) {
for(unsigned l = 0; l < 8; l++) {
if(list & (1 << l)) {
r(l) = bus_read(r(n), Word);
if(load == 1) r(l) = bus_read(r(n), Word); //LDMIA
if(load == 0) bus_write(r(n), Word, r(l)); //STMIA
r(n) += 4;
}
}
}
if(load == 0) {
for(unsigned l = 0; l < 8; l++) {
if(list & (1 << l)) {
r(n) -= 4;
bus_write(r(n), Word, r(l));
}
}
}
}
//swi #immediate
//1101 1111 iiii iiii
//i = immediate
@ -513,9 +484,9 @@ void ARM::thumb_op_branch_short() {
//1111 0ooo oooo oooo
//o = offset
void ARM::thumb_op_branch_long_prefix() {
uint11 offsethi = instruction();
int11 offsethi = instruction();
r(14) = offsethi;
r(14) = r(15) + ((offsethi * 2) << 11);
}
//bl address
@ -524,9 +495,8 @@ void ARM::thumb_op_branch_long_prefix() {
void ARM::thumb_op_branch_long_suffix() {
uint11 offsetlo = instruction();
int22 displacement = ((uint11)r(14) << 11) | offsetlo;
r(14) = r(15) | 1;
r(15) += displacement * 2;
r(15) = r(14) + (offsetlo * 2);
r(14) = pipeline.decode.address | 1;
}
#endif

View File

@ -4,7 +4,6 @@ bool thumb_condition(uint4 condition);
void thumb_opcode(uint4 opcode, uint4 d, uint4 s);
uint32 thumb_tst(uint32 modify);
void thumb_cmp(uint32 source, 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);

View File

@ -0,0 +1,222 @@
void uPD96050::exec() {
uint24 opcode = programROM[regs.pc++];
switch(opcode >> 22) {
case 0: exec_op(opcode); break;
case 1: exec_rt(opcode); break;
case 2: exec_jp(opcode); break;
case 3: exec_ld(opcode); break;
}
int32 result = (int32)regs.k * regs.l; //sign + 30-bit result
regs.m = result >> 15; //store sign + top 15-bits
regs.n = result << 1; //store low 15-bits + zero
}
void uPD96050::exec_op(uint24 opcode) {
uint2 pselect = opcode >> 20; //P select
uint4 alu = opcode >> 16; //ALU operation mode
uint1 asl = opcode >> 15; //accumulator select
uint2 dpl = opcode >> 13; //DP low modify
uint4 dphm = opcode >> 9; //DP high XOR modify
uint1 rpdcr = opcode >> 8; //RP decrement
uint4 src = opcode >> 4; //move source
uint4 dst = opcode >> 0; //move destination
uint16 idb;
switch(src) {
case 0: idb = regs.trb; break;
case 1: idb = regs.a; break;
case 2: idb = regs.b; break;
case 3: idb = regs.tr; break;
case 4: idb = regs.dp; break;
case 5: idb = regs.rp; break;
case 6: idb = dataROM[regs.rp]; break;
case 7: idb = 0x8000 - regs.flaga.s1; break;
case 8: idb = regs.dr; regs.sr.rqm = 1; break;
case 9: idb = regs.dr; break;
case 10: idb = regs.sr; break;
case 11: idb = regs.si; break; //MSB
case 12: idb = regs.si; break; //LSB
case 13: idb = regs.k; break;
case 14: idb = regs.l; break;
case 15: idb = dataRAM[regs.dp]; break;
}
if(alu) {
uint16 p, q, r;
Flag flag;
bool c;
switch(pselect) {
case 0: p = dataRAM[regs.dp]; break;
case 1: p = idb; break;
case 2: p = regs.m; break;
case 3: p = regs.n; break;
}
switch(asl) {
case 0: q = regs.a; flag = regs.flaga; c = regs.flagb.c; break;
case 1: q = regs.b; flag = regs.flagb; c = regs.flaga.c; break;
}
switch(alu) {
case 1: r = q | p; break; //OR
case 2: r = q & p; break; //AND
case 3: r = q ^ p; break; //XOR
case 4: r = q - p; break; //SUB
case 5: r = q + p; break; //ADD
case 6: r = q - p - c; break; //SBB
case 7: r = q + p + c; break; //ADC
case 8: r = q - 1; p = 1; break; //DEC
case 9: r = q + 1; p = 1; break; //INC
case 10: r = ~q; break; //CMP
case 11: r = (q >> 1) | (q & 0x8000); break; //SHR1 (ASR)
case 12: r = (q << 1) | c; break; //SHL1 (ROL)
case 13: r = (q << 2) | 3; break; //SHL2
case 14: r = (q << 4) | 15; break; //SHL4
case 15: r = (q << 8) | (q >> 8); break; //XCHG
}
flag.s0 = (r & 0x8000);
flag.z = (r == 0);
switch(alu) {
case 1: case 2: case 3: case 10: case 13: case 14: case 15: {
flag.c = 0;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 4: case 5: case 6: case 7: case 8: case 9: {
if(alu & 1) {
//addition
flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000;
flag.c = (r < q);
} else {
//subtraction
flag.ov0 = (q ^ r) & (q ^ p) & 0x8000;
flag.c = (r > q);
}
if(flag.ov0) {
flag.s1 = flag.ov1 ^ !(r & 0x8000);
flag.ov1 = !flag.ov1;
}
break;
}
case 11: {
flag.c = q & 1;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 12: {
flag.c = q >> 15;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
}
switch(asl) {
case 0: regs.a = r; regs.flaga = flag; break;
case 1: regs.b = r; regs.flagb = flag; break;
}
}
exec_ld((idb << 6) + dst);
switch(dpl) {
case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC
case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC
case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR
}
regs.dp ^= dphm << 4;
if(rpdcr) regs.rp--;
}
void uPD96050::exec_rt(uint24 opcode) {
exec_op(opcode);
regs.pc = regs.stack[--regs.sp];
}
void uPD96050::exec_jp(uint24 opcode) {
uint9 brch = opcode >> 13; //branch
uint11 na = opcode >> 2; //next address
uint2 bank = opcode >> 0; //bank address
uint14 jp = (regs.pc & 0x2000) | (bank << 11) | (na << 0);
switch(brch) {
case 0x000: regs.pc = regs.so; return; //JMPSO
case 0x080: if(regs.flaga.c == 0) regs.pc = jp; return; //JNCA
case 0x082: if(regs.flaga.c == 1) regs.pc = jp; return; //JCA
case 0x084: if(regs.flagb.c == 0) regs.pc = jp; return; //JNCB
case 0x086: if(regs.flagb.c == 1) regs.pc = jp; return; //JCB
case 0x088: if(regs.flaga.z == 0) regs.pc = jp; return; //JNZA
case 0x08a: if(regs.flaga.z == 1) regs.pc = jp; return; //JZA
case 0x08c: if(regs.flagb.z == 0) regs.pc = jp; return; //JNZB
case 0x08e: if(regs.flagb.z == 1) regs.pc = jp; return; //JZB
case 0x090: if(regs.flaga.ov0 == 0) regs.pc = jp; return; //JNOVA0
case 0x092: if(regs.flaga.ov0 == 1) regs.pc = jp; return; //JOVA0
case 0x094: if(regs.flagb.ov0 == 0) regs.pc = jp; return; //JNOVB0
case 0x096: if(regs.flagb.ov0 == 1) regs.pc = jp; return; //JOVB0
case 0x098: if(regs.flaga.ov1 == 0) regs.pc = jp; return; //JNOVA1
case 0x09a: if(regs.flaga.ov1 == 1) regs.pc = jp; return; //JOVA1
case 0x09c: if(regs.flagb.ov1 == 0) regs.pc = jp; return; //JNOVB1
case 0x09e: if(regs.flagb.ov1 == 1) regs.pc = jp; return; //JOVB1
case 0x0a0: if(regs.flaga.s0 == 0) regs.pc = jp; return; //JNSA0
case 0x0a2: if(regs.flaga.s0 == 1) regs.pc = jp; return; //JSA0
case 0x0a4: if(regs.flagb.s0 == 0) regs.pc = jp; return; //JNSB0
case 0x0a6: if(regs.flagb.s0 == 1) regs.pc = jp; return; //JSB0
case 0x0a8: if(regs.flaga.s1 == 0) regs.pc = jp; return; //JNSA1
case 0x0aa: if(regs.flaga.s1 == 1) regs.pc = jp; return; //JSA1
case 0x0ac: if(regs.flagb.s1 == 0) regs.pc = jp; return; //JNSB1
case 0x0ae: if(regs.flagb.s1 == 1) regs.pc = jp; return; //JSB1
case 0x0b0: if((regs.dp & 0x0f) == 0x00) regs.pc = jp; return; //JDPL0
case 0x0b1: if((regs.dp & 0x0f) != 0x00) regs.pc = jp; return; //JDPLN0
case 0x0b2: if((regs.dp & 0x0f) == 0x0f) regs.pc = jp; return; //JDPLF
case 0x0b3: if((regs.dp & 0x0f) != 0x0f) regs.pc = jp; return; //JDPLNF
case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jp; return; //JNRQM
case 0x0be: if(regs.sr.rqm == 1) regs.pc = jp; return; //JRQM
case 0x100: regs.pc = jp & ~0x2000; return; //LJMP
case 0x101: regs.pc = jp | 0x2000; return; //HJMP
case 0x140: regs.stack[regs.sp++] = regs.pc; regs.pc = jp & ~0x2000; return; //LCALL
case 0x141: regs.stack[regs.sp++] = regs.pc; regs.pc = jp | 0x2000; return; //HCALL
}
}
void uPD96050::exec_ld(uint24 opcode) {
uint16 id = opcode >> 6; //immediate data
uint4 dst = opcode >> 0; //destination
switch(dst) {
case 0: break;
case 1: regs.a = id; break;
case 2: regs.b = id; break;
case 3: regs.tr = id; break;
case 4: regs.dp = id; break;
case 5: regs.rp = id; break;
case 6: regs.dr = id; regs.sr.rqm = 1; break;
case 7: regs.sr = (regs.sr & 0x907c) | (id & ~0x907c); break;
case 8: regs.so = id; break; //LSB
case 9: regs.so = id; break; //MSB
case 10: regs.k = id; break;
case 11: regs.k = id; regs.l = dataROM[regs.rp]; break;
case 12: regs.l = id; regs.k = dataRAM[regs.dp | 0x40]; break;
case 13: regs.l = id; break;
case 14: regs.trb = id; break;
case 15: dataRAM[regs.dp] = id; break;
}
}

View File

@ -1,16 +1,11 @@
#ifdef NECDSP_CPP
uint8 NECDSP::sr_read(unsigned) {
cpu.synchronize_coprocessors();
uint8 uPD96050::sr_read() {
return regs.sr >> 8;
}
void NECDSP::sr_write(unsigned, uint8 data) {
cpu.synchronize_coprocessors();
void uPD96050::sr_write(uint8 data) {
}
uint8 NECDSP::dr_read(unsigned) {
cpu.synchronize_coprocessors();
uint8 uPD96050::dr_read() {
if(regs.sr.drc == 0) {
//16-bit
if(regs.sr.drs == 0) {
@ -28,8 +23,7 @@ uint8 NECDSP::dr_read(unsigned) {
}
}
void NECDSP::dr_write(unsigned, uint8 data) {
cpu.synchronize_coprocessors();
void uPD96050::dr_write(uint8 data) {
if(regs.sr.drc == 0) {
//16-bit
if(regs.sr.drs == 0) {
@ -47,8 +41,7 @@ void NECDSP::dr_write(unsigned, uint8 data) {
}
}
uint8 NECDSP::dp_read(unsigned addr) {
cpu.synchronize_coprocessors();
uint8 uPD96050::dp_read(uint12 addr) {
bool hi = addr & 1;
addr = (addr >> 1) & 2047;
@ -59,8 +52,7 @@ uint8 NECDSP::dp_read(unsigned addr) {
}
}
void NECDSP::dp_write(unsigned addr, uint8 data) {
cpu.synchronize_coprocessors();
void uPD96050::dp_write(uint12 addr, uint8 data) {
bool hi = addr & 1;
addr = (addr >> 1) & 2047;
@ -70,5 +62,3 @@ void NECDSP::dp_write(unsigned addr, uint8 data) {
dataRAM[addr] = (dataRAM[addr] & 0x00ff) | (data << 8);
}
}
#endif

View File

@ -0,0 +1,49 @@
void uPD96050::serialize(serializer &s) {
s.array(dataRAM);
s.array(regs.stack);
s.integer(regs.pc);
s.integer(regs.rp);
s.integer(regs.dp);
s.integer(regs.sp);
s.integer(regs.k);
s.integer(regs.l);
s.integer(regs.m);
s.integer(regs.n);
s.integer(regs.a);
s.integer(regs.b);
s.integer(regs.flaga.s1);
s.integer(regs.flaga.s0);
s.integer(regs.flaga.c);
s.integer(regs.flaga.z);
s.integer(regs.flaga.ov1);
s.integer(regs.flaga.ov0);
s.integer(regs.flagb.s1);
s.integer(regs.flagb.s0);
s.integer(regs.flagb.c);
s.integer(regs.flagb.z);
s.integer(regs.flagb.ov1);
s.integer(regs.flagb.ov0);
s.integer(regs.tr);
s.integer(regs.trb);
s.integer(regs.sr.rqm);
s.integer(regs.sr.usf1);
s.integer(regs.sr.usf0);
s.integer(regs.sr.drs);
s.integer(regs.sr.dma);
s.integer(regs.sr.drc);
s.integer(regs.sr.soc);
s.integer(regs.sr.sic);
s.integer(regs.sr.ei);
s.integer(regs.sr.p1);
s.integer(regs.sr.p0);
s.integer(regs.dr);
s.integer(regs.si);
s.integer(regs.so);
}

View File

@ -0,0 +1,45 @@
#include <processor/processor.hpp>
#include "upd96050.hpp"
namespace Processor {
#include "instructions.cpp"
#include "memory.cpp"
#include "disassembler.cpp"
#include "serialization.cpp"
void uPD96050::power() {
if(revision == Revision::uPD7725) {
regs.pc.bits(11);
regs.rp.bits(10);
regs.dp.bits( 8);
}
if(revision == Revision::uPD96050) {
regs.pc.bits(14);
regs.rp.bits(11);
regs.dp.bits(11);
}
for(unsigned n = 0; n < 16; n++) regs.stack[n] = 0x0000;
regs.pc = 0x0000;
regs.rp = 0x0000;
regs.dp = 0x0000;
regs.sp = 0x0;
regs.k = 0x0000;
regs.l = 0x0000;
regs.m = 0x0000;
regs.n = 0x0000;
regs.a = 0x0000;
regs.b = 0x0000;
regs.flaga = 0x00;
regs.flagb = 0x00;
regs.tr = 0x0000;
regs.trb = 0x0000;
regs.sr = 0x0000;
regs.dr = 0x0000;
regs.si = 0x0000;
regs.so = 0x0000;
}
}

View File

@ -0,0 +1,40 @@
#ifndef PROCESSOR_UPD96050_HPP
#define PROCESSOR_UPD96050_HPP
namespace Processor {
//NEC uPD7720 (not supported)
//NEC uPD7725
//NEC uPD96050
struct uPD96050 {
enum class Revision : unsigned { uPD7725, uPD96050 } revision;
uint24 programROM[16384];
uint16 dataROM[2048];
uint16 dataRAM[2048];
#include "registers.hpp"
void power();
void exec();
void serialize(serializer&);
void exec_op(uint24 opcode);
void exec_rt(uint24 opcode);
void exec_jp(uint24 opcode);
void exec_ld(uint24 opcode);
uint8 sr_read();
void sr_write(uint8 data);
uint8 dr_read();
void dr_write(uint8 data);
uint8 dp_read(uint12 addr);
void dp_write(uint12 addr, uint8 data);
string disassemble(uint14 ip);
};
}
#endif

View File

@ -164,8 +164,6 @@ public:
bool init() {
term();
// display = XOpenDisplay(0);
// screen = DefaultScreen(display);
glXQueryVersion(display, &glx.version_major, &glx.version_minor);
//require GLX 1.2+ API
if(glx.version_major < 1 || (glx.version_major == 1 && glx.version_minor < 2)) return false;
@ -179,9 +177,9 @@ public:
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DOUBLEBUFFER, True,
GLX_RED_SIZE, (settings.depth / 3),
GLX_GREEN_SIZE, (settings.depth / 3) + (settings.depth % 3),
GLX_BLUE_SIZE, (settings.depth / 3),
GLX_RED_SIZE, (signed)(settings.depth / 3),
GLX_GREEN_SIZE, (signed)(settings.depth / 3) + (signed)(settings.depth % 3),
GLX_BLUE_SIZE, (signed)(settings.depth / 3),
None,
};

View File

@ -3,8 +3,6 @@
#define NECDSP_CPP
namespace SNES {
#include "memory.cpp"
#include "disassembler.cpp"
#include "serialization.cpp"
NECDSP necdsp;
@ -16,231 +14,20 @@ void NECDSP::enter() {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
uint24 opcode = programROM[regs.pc++];
switch(opcode >> 22) {
case 0: exec_op(opcode); break;
case 1: exec_rt(opcode); break;
case 2: exec_jp(opcode); break;
case 3: exec_ld(opcode); break;
}
int32 result = (int32)regs.k * regs.l; //sign + 30-bit result
regs.m = result >> 15; //store sign + top 15-bits
regs.n = result << 1; //store low 15-bits + zero
exec();
step(1);
synchronize_cpu();
}
}
void NECDSP::exec_op(uint24 opcode) {
uint2 pselect = opcode >> 20; //P select
uint4 alu = opcode >> 16; //ALU operation mode
uint1 asl = opcode >> 15; //accumulator select
uint2 dpl = opcode >> 13; //DP low modify
uint4 dphm = opcode >> 9; //DP high XOR modify
uint1 rpdcr = opcode >> 8; //RP decrement
uint4 src = opcode >> 4; //move source
uint4 dst = opcode >> 0; //move destination
uint8 NECDSP::sr_read(unsigned) { cpu.synchronize_coprocessors(); return uPD96050::sr_read(); }
void NECDSP::sr_write(unsigned, uint8 data) { cpu.synchronize_coprocessors(); return uPD96050::sr_write(data); }
uint16 idb;
switch(src) {
case 0: idb = regs.trb; break;
case 1: idb = regs.a; break;
case 2: idb = regs.b; break;
case 3: idb = regs.tr; break;
case 4: idb = regs.dp; break;
case 5: idb = regs.rp; break;
case 6: idb = dataROM[regs.rp]; break;
case 7: idb = 0x8000 - regs.flaga.s1; break;
case 8: idb = regs.dr; regs.sr.rqm = 1; break;
case 9: idb = regs.dr; break;
case 10: idb = regs.sr; break;
case 11: idb = regs.si; break; //MSB
case 12: idb = regs.si; break; //LSB
case 13: idb = regs.k; break;
case 14: idb = regs.l; break;
case 15: idb = dataRAM[regs.dp]; break;
}
uint8 NECDSP::dr_read(unsigned) { cpu.synchronize_coprocessors(); return uPD96050::dr_read(); }
void NECDSP::dr_write(unsigned, uint8 data) { cpu.synchronize_coprocessors(); return uPD96050::dr_write(data); }
if(alu) {
uint16 p, q, r;
Flag flag;
bool c;
switch(pselect) {
case 0: p = dataRAM[regs.dp]; break;
case 1: p = idb; break;
case 2: p = regs.m; break;
case 3: p = regs.n; break;
}
switch(asl) {
case 0: q = regs.a; flag = regs.flaga; c = regs.flagb.c; break;
case 1: q = regs.b; flag = regs.flagb; c = regs.flaga.c; break;
}
switch(alu) {
case 1: r = q | p; break; //OR
case 2: r = q & p; break; //AND
case 3: r = q ^ p; break; //XOR
case 4: r = q - p; break; //SUB
case 5: r = q + p; break; //ADD
case 6: r = q - p - c; break; //SBB
case 7: r = q + p + c; break; //ADC
case 8: r = q - 1; p = 1; break; //DEC
case 9: r = q + 1; p = 1; break; //INC
case 10: r = ~q; break; //CMP
case 11: r = (q >> 1) | (q & 0x8000); break; //SHR1 (ASR)
case 12: r = (q << 1) | c; break; //SHL1 (ROL)
case 13: r = (q << 2) | 3; break; //SHL2
case 14: r = (q << 4) | 15; break; //SHL4
case 15: r = (q << 8) | (q >> 8); break; //XCHG
}
flag.s0 = (r & 0x8000);
flag.z = (r == 0);
switch(alu) {
case 1: case 2: case 3: case 10: case 13: case 14: case 15: {
flag.c = 0;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 4: case 5: case 6: case 7: case 8: case 9: {
if(alu & 1) {
//addition
flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000;
flag.c = (r < q);
} else {
//subtraction
flag.ov0 = (q ^ r) & (q ^ p) & 0x8000;
flag.c = (r > q);
}
if(flag.ov0) {
flag.s1 = flag.ov1 ^ !(r & 0x8000);
flag.ov1 = !flag.ov1;
}
break;
}
case 11: {
flag.c = q & 1;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 12: {
flag.c = q >> 15;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
}
switch(asl) {
case 0: regs.a = r; regs.flaga = flag; break;
case 1: regs.b = r; regs.flagb = flag; break;
}
}
exec_ld((idb << 6) + dst);
switch(dpl) {
case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC
case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC
case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR
}
regs.dp ^= dphm << 4;
if(rpdcr) regs.rp--;
}
void NECDSP::exec_rt(uint24 opcode) {
exec_op(opcode);
regs.pc = regs.stack[--regs.sp];
}
void NECDSP::exec_jp(uint24 opcode) {
uint9 brch = opcode >> 13; //branch
uint11 na = opcode >> 2; //next address
uint2 bank = opcode >> 0; //bank address
uint14 jp = (regs.pc & 0x2000) | (bank << 11) | (na << 0);
switch(brch) {
case 0x000: regs.pc = regs.so; return; //JMPSO
case 0x080: if(regs.flaga.c == 0) regs.pc = jp; return; //JNCA
case 0x082: if(regs.flaga.c == 1) regs.pc = jp; return; //JCA
case 0x084: if(regs.flagb.c == 0) regs.pc = jp; return; //JNCB
case 0x086: if(regs.flagb.c == 1) regs.pc = jp; return; //JCB
case 0x088: if(regs.flaga.z == 0) regs.pc = jp; return; //JNZA
case 0x08a: if(regs.flaga.z == 1) regs.pc = jp; return; //JZA
case 0x08c: if(regs.flagb.z == 0) regs.pc = jp; return; //JNZB
case 0x08e: if(regs.flagb.z == 1) regs.pc = jp; return; //JZB
case 0x090: if(regs.flaga.ov0 == 0) regs.pc = jp; return; //JNOVA0
case 0x092: if(regs.flaga.ov0 == 1) regs.pc = jp; return; //JOVA0
case 0x094: if(regs.flagb.ov0 == 0) regs.pc = jp; return; //JNOVB0
case 0x096: if(regs.flagb.ov0 == 1) regs.pc = jp; return; //JOVB0
case 0x098: if(regs.flaga.ov1 == 0) regs.pc = jp; return; //JNOVA1
case 0x09a: if(regs.flaga.ov1 == 1) regs.pc = jp; return; //JOVA1
case 0x09c: if(regs.flagb.ov1 == 0) regs.pc = jp; return; //JNOVB1
case 0x09e: if(regs.flagb.ov1 == 1) regs.pc = jp; return; //JOVB1
case 0x0a0: if(regs.flaga.s0 == 0) regs.pc = jp; return; //JNSA0
case 0x0a2: if(regs.flaga.s0 == 1) regs.pc = jp; return; //JSA0
case 0x0a4: if(regs.flagb.s0 == 0) regs.pc = jp; return; //JNSB0
case 0x0a6: if(regs.flagb.s0 == 1) regs.pc = jp; return; //JSB0
case 0x0a8: if(regs.flaga.s1 == 0) regs.pc = jp; return; //JNSA1
case 0x0aa: if(regs.flaga.s1 == 1) regs.pc = jp; return; //JSA1
case 0x0ac: if(regs.flagb.s1 == 0) regs.pc = jp; return; //JNSB1
case 0x0ae: if(regs.flagb.s1 == 1) regs.pc = jp; return; //JSB1
case 0x0b0: if((regs.dp & 0x0f) == 0x00) regs.pc = jp; return; //JDPL0
case 0x0b1: if((regs.dp & 0x0f) != 0x00) regs.pc = jp; return; //JDPLN0
case 0x0b2: if((regs.dp & 0x0f) == 0x0f) regs.pc = jp; return; //JDPLF
case 0x0b3: if((regs.dp & 0x0f) != 0x0f) regs.pc = jp; return; //JDPLNF
case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jp; return; //JNRQM
case 0x0be: if(regs.sr.rqm == 1) regs.pc = jp; return; //JRQM
case 0x100: regs.pc = jp & ~0x2000; return; //LJMP
case 0x101: regs.pc = jp | 0x2000; return; //HJMP
case 0x140: regs.stack[regs.sp++] = regs.pc; regs.pc = jp & ~0x2000; return; //LCALL
case 0x141: regs.stack[regs.sp++] = regs.pc; regs.pc = jp | 0x2000; return; //HCALL
}
}
void NECDSP::exec_ld(uint24 opcode) {
uint16 id = opcode >> 6; //immediate data
uint4 dst = opcode >> 0; //destination
switch(dst) {
case 0: break;
case 1: regs.a = id; break;
case 2: regs.b = id; break;
case 3: regs.tr = id; break;
case 4: regs.dp = id; break;
case 5: regs.rp = id; break;
case 6: regs.dr = id; regs.sr.rqm = 1; break;
case 7: regs.sr = (regs.sr & 0x907c) | (id & ~0x907c); break;
case 8: regs.so = id; break; //LSB
case 9: regs.so = id; break; //MSB
case 10: regs.k = id; break;
case 11: regs.k = id; regs.l = dataROM[regs.rp]; break;
case 12: regs.l = id; regs.k = dataRAM[regs.dp | 0x40]; break;
case 13: regs.l = id; break;
case 14: regs.trb = id; break;
case 15: dataRAM[regs.dp] = id; break;
}
}
uint8 NECDSP::dp_read(unsigned addr) { cpu.synchronize_coprocessors(); return uPD96050::dp_read(addr); }
void NECDSP::dp_write(unsigned addr, uint8 data) { cpu.synchronize_coprocessors(); return uPD96050::dp_write(addr, data); }
void NECDSP::init() {
}
@ -255,47 +42,11 @@ void NECDSP::unload() {
}
void NECDSP::power() {
if(revision == Revision::uPD7725) {
regs.pc.bits(11);
regs.rp.bits(10);
regs.dp.bits( 8);
}
if(revision == Revision::uPD96050) {
regs.pc.bits(14);
regs.rp.bits(11);
regs.dp.bits(11);
}
}
void NECDSP::reset() {
create(NECDSP::Enter, frequency);
for(unsigned n = 0; n < 16; n++) regs.stack[n] = 0x0000;
regs.pc = 0x0000;
regs.rp = 0x0000;
regs.dp = 0x0000;
regs.sp = 0x0;
regs.k = 0x0000;
regs.l = 0x0000;
regs.m = 0x0000;
regs.n = 0x0000;
regs.a = 0x0000;
regs.b = 0x0000;
regs.flaga = 0x00;
regs.flagb = 0x00;
regs.tr = 0x0000;
regs.trb = 0x0000;
regs.sr = 0x0000;
regs.dr = 0x0000;
regs.si = 0x0000;
regs.so = 0x0000;
}
NECDSP::NECDSP() {
}
NECDSP::~NECDSP() {
uPD96050::power();
}
}

View File

@ -1,31 +1,7 @@
//NEC uPD7725
//NEC uPD96050
class NECDSP : public Coprocessor {
public:
enum class Revision : unsigned { uPD7725, uPD96050 } revision;
unsigned frequency;
#include "registers.hpp"
uint24 programROM[16384];
uint16 dataROM[2048];
uint16 dataRAM[2048];
unsigned programROMSize;
unsigned dataROMSize;
unsigned dataRAMSize;
struct NECDSP : Processor::uPD96050, Coprocessor {
static void Enter();
void enter();
void exec_op(uint24 opcode);
void exec_rt(uint24 opcode);
void exec_jp(uint24 opcode);
void exec_ld(uint24 opcode);
string disassemble(uint14 ip);
uint8 sr_read(unsigned);
void sr_write(unsigned, uint8 data);
@ -42,8 +18,6 @@ public:
void reset();
void serialize(serializer&);
NECDSP();
~NECDSP();
};
extern NECDSP necdsp;

View File

@ -1,55 +1,8 @@
#ifdef NECDSP_CPP
void NECDSP::serialize(serializer &s) {
uPD96050::serialize(s);
Thread::serialize(s);
s.array(dataRAM);
s.array(regs.stack);
s.integer(regs.pc);
s.integer(regs.rp);
s.integer(regs.dp);
s.integer(regs.sp);
s.integer(regs.k);
s.integer(regs.l);
s.integer(regs.m);
s.integer(regs.n);
s.integer(regs.a);
s.integer(regs.b);
s.integer(regs.flaga.s1);
s.integer(regs.flaga.s0);
s.integer(regs.flaga.c);
s.integer(regs.flaga.z);
s.integer(regs.flaga.ov1);
s.integer(regs.flaga.ov0);
s.integer(regs.flagb.s1);
s.integer(regs.flagb.s0);
s.integer(regs.flagb.c);
s.integer(regs.flagb.z);
s.integer(regs.flagb.ov1);
s.integer(regs.flagb.ov0);
s.integer(regs.tr);
s.integer(regs.trb);
s.integer(regs.sr.rqm);
s.integer(regs.sr.usf1);
s.integer(regs.sr.usf0);
s.integer(regs.sr.drs);
s.integer(regs.sr.dma);
s.integer(regs.sr.drc);
s.integer(regs.sr.soc);
s.integer(regs.sr.sic);
s.integer(regs.sr.ei);
s.integer(regs.sr.p1);
s.integer(regs.sr.p0);
s.integer(regs.dr);
s.integer(regs.si);
s.integer(regs.so);
}
#endif

View File

@ -4,11 +4,12 @@
#include <base/base.hpp>
#include <processor/arm/arm.hpp>
#include <processor/hg51b/hg51b.hpp>
#include <processor/upd96050/upd96050.hpp>
namespace SNES {
namespace Info {
static const char Name[] = "bsnes";
static const unsigned SerializerVersion = 23;
static const unsigned SerializerVersion = 24;
}
}

View File

@ -1,4 +1,4 @@
processors := arm hg51b
processors := arm hg51b upd96050
include processor/Makefile
include $(nes)/Makefile

View File

@ -123,6 +123,8 @@ Application::Application(int argc, char **argv) {
Application::run();
}
if(GBA::cartridge.loaded()) print(GBA::cpu.disassemble_registers(), "\n");
interface->unloadCartridge();
windowManager->saveGeometry();
windowManager->hideAll();