From e16dd58184c830b7e94a7974093ea016588cecd0 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Mon, 26 Mar 2012 21:13:02 +1100 Subject: [PATCH] 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. --- bsnes/Makefile | 2 +- bsnes/base/base.hpp | 2 +- bsnes/gba/apu/apu.cpp | 7 + bsnes/gba/cpu/cpu.cpp | 1 - bsnes/gba/memory/memory.cpp | 4 +- bsnes/nall/map.hpp | 2 +- bsnes/nall/udl.hpp | 27 ++ bsnes/phoenix/core/core.hpp | 6 +- bsnes/phoenix/gtk/platform.hpp | 3 +- bsnes/phoenix/gtk/window.cpp | 123 +++++--- bsnes/phoenix/qt/platform.cpp | 6 + bsnes/phoenix/qt/platform.moc | 2 +- bsnes/processor/Makefile | 6 +- bsnes/processor/arm/disassembler.cpp | 4 +- bsnes/processor/arm/instructions-arm.cpp | 4 +- bsnes/processor/arm/instructions-thumb.cpp | 90 ++---- bsnes/processor/arm/instructions-thumb.hpp | 1 - .../upd96050}/disassembler.cpp | 0 bsnes/processor/upd96050/instructions.cpp | 222 +++++++++++++++ .../necdsp => processor/upd96050}/memory.cpp | 22 +- .../upd96050}/registers.hpp | 0 bsnes/processor/upd96050/serialization.cpp | 49 ++++ bsnes/processor/upd96050/upd96050.cpp | 45 +++ bsnes/processor/upd96050/upd96050.hpp | 40 +++ bsnes/ruby/video/glx.cpp | 8 +- bsnes/snes/chip/necdsp/necdsp.cpp | 265 +----------------- bsnes/snes/chip/necdsp/necdsp.hpp | 28 +- bsnes/snes/chip/necdsp/serialization.cpp | 49 +--- bsnes/snes/snes.hpp | 3 +- bsnes/target-ui/Makefile | 2 +- bsnes/target-ui/main.cpp | 2 + 31 files changed, 547 insertions(+), 478 deletions(-) create mode 100755 bsnes/nall/udl.hpp rename bsnes/{snes/chip/necdsp => processor/upd96050}/disassembler.cpp (100%) create mode 100755 bsnes/processor/upd96050/instructions.cpp rename bsnes/{snes/chip/necdsp => processor/upd96050}/memory.cpp (68%) rename bsnes/{snes/chip/necdsp => processor/upd96050}/registers.hpp (100%) create mode 100755 bsnes/processor/upd96050/serialization.cpp create mode 100755 bsnes/processor/upd96050/upd96050.cpp create mode 100755 bsnes/processor/upd96050/upd96050.hpp diff --git a/bsnes/Makefile b/bsnes/Makefile index ea24f98a..167a3a20 100755 --- a/bsnes/Makefile +++ b/bsnes/Makefile @@ -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` diff --git a/bsnes/base/base.hpp b/bsnes/base/base.hpp index a0e3414b..0c087923 100755 --- a/bsnes/base/base.hpp +++ b/bsnes/base/base.hpp @@ -1,7 +1,7 @@ #ifndef BASE_HPP #define BASE_HPP -static const char Version[] = "087.08"; +static const char Version[] = "087.09"; #include #include diff --git a/bsnes/gba/apu/apu.cpp b/bsnes/gba/apu/apu.cpp index bcadcb2e..2a4ce3f3 100755 --- a/bsnes/gba/apu/apu.cpp +++ b/bsnes/gba/apu/apu.cpp @@ -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; } } diff --git a/bsnes/gba/cpu/cpu.cpp b/bsnes/gba/cpu/cpu.cpp index 80ed02ed..38fe4432 100755 --- a/bsnes/gba/cpu/cpu.cpp +++ b/bsnes/gba/cpu/cpu.cpp @@ -50,7 +50,6 @@ void CPU::power() { } uint32 CPU::read(uint32 addr, uint32 size) { - if(addr == 0x04000300) return prng() & 1; return 0u; } diff --git a/bsnes/gba/memory/memory.cpp b/bsnes/gba/memory/memory.cpp index 301db043..aa36a122 100755 --- a/bsnes/gba/memory/memory.cpp +++ b/bsnes/gba/memory/memory.cpp @@ -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; diff --git a/bsnes/nall/map.hpp b/bsnes/nall/map.hpp index 84709781..537aa9ac 100755 --- a/bsnes/nall/map.hpp +++ b/bsnes/nall/map.hpp @@ -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 }; } diff --git a/bsnes/nall/udl.hpp b/bsnes/nall/udl.hpp new file mode 100755 index 00000000..40bceba0 --- /dev/null +++ b/bsnes/nall/udl.hpp @@ -0,0 +1,27 @@ +#ifndef NALL_UDL_HPP +#define NALL_UDL_HPP + +//user-defined literals + +#include + +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 diff --git a/bsnes/phoenix/core/core.hpp b/bsnes/phoenix/core/core.hpp index d44e0596..d3506235 100755 --- a/bsnes/phoenix/core/core.hpp +++ b/bsnes/phoenix/core/core.hpp @@ -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 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 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 inline Geometry(X x, Y y, W width, H height) : x(x), y(y), width(width), height(height) {} Geometry(const nall::string &text); }; diff --git a/bsnes/phoenix/gtk/platform.hpp b/bsnes/phoenix/gtk/platform.hpp index 037dd5a9..56534ca6 100755 --- a/bsnes/phoenix/gtk/platform.hpp +++ b/bsnes/phoenix/gtk/platform.hpp @@ -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); diff --git a/bsnes/phoenix/gtk/window.cpp b/bsnes/phoenix/gtk/window.cpp index 8248104a..be3f2a7f 100755 --- a/bsnes/phoenix/gtk/window.cpp +++ b/bsnes/phoenix/gtk/window.cpp @@ -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(); - } - - 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(); + if(geometry.width != window->state.geometry.width || geometry.height != window->state.geometry.height) { + window->p.onSizePending = true; } - 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() { diff --git a/bsnes/phoenix/qt/platform.cpp b/bsnes/phoenix/qt/platform.cpp index 0ff46b2b..86f659c8 100755 --- a/bsnes/phoenix/qt/platform.cpp +++ b/bsnes/phoenix/qt/platform.cpp @@ -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" diff --git a/bsnes/phoenix/qt/platform.moc b/bsnes/phoenix/qt/platform.moc index bd9cf54b..645f7457 100755 --- a/bsnes/phoenix/qt/platform.moc +++ b/bsnes/phoenix/qt/platform.moc @@ -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! diff --git a/bsnes/processor/Makefile b/bsnes/processor/Makefile index 4eb32026..2397d557 100755 --- a/bsnes/processor/Makefile +++ b/bsnes/processor/Makefile @@ -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-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) diff --git a/bsnes/processor/arm/disassembler.cpp b/bsnes/processor/arm/disassembler.cpp index 6a2d423c..69f7514b 100755 --- a/bsnes/processor/arm/disassembler.cpp +++ b/bsnes/processor/arm/disassembler.cpp @@ -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], ","); } diff --git a/bsnes/processor/arm/instructions-arm.cpp b/bsnes/processor/arm/instructions-arm.cpp index f3fc50b8..486a19f4 100755 --- a/bsnes/processor/arm/instructions-arm.cpp +++ b/bsnes/processor/arm/instructions-arm.cpp @@ -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 diff --git a/bsnes/processor/arm/instructions-thumb.cpp b/bsnes/processor/arm/instructions-thumb.cpp index 1dae860e..00b8d727 100755 --- a/bsnes/processor/arm/instructions-thumb.cpp +++ b/bsnes/processor/arm/instructions-thumb.cpp @@ -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) { - 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; + 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)) { + 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)); - } + if(branch) { + //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; } + + if(load == 1) r(13) += (bit::count(list) + branch) * 4; + if(load == 0) r(13) -= (bit::count(list) + branch) * 4; } -//(ldmia,stmdb) rn!,{r...} +//(ldmia,stmia) rn!,{r...} //1100 lnnn llll llll //l = load (0 = save) //n = rn @@ -460,21 +441,11 @@ 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); - 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)); - } + for(unsigned l = 0; l < 8; l++) { + if(list & (1 << l)) { + 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; } } } @@ -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 diff --git a/bsnes/processor/arm/instructions-thumb.hpp b/bsnes/processor/arm/instructions-thumb.hpp index 4efd1475..0fe6bab3 100755 --- a/bsnes/processor/arm/instructions-thumb.hpp +++ b/bsnes/processor/arm/instructions-thumb.hpp @@ -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); diff --git a/bsnes/snes/chip/necdsp/disassembler.cpp b/bsnes/processor/upd96050/disassembler.cpp similarity index 100% rename from bsnes/snes/chip/necdsp/disassembler.cpp rename to bsnes/processor/upd96050/disassembler.cpp diff --git a/bsnes/processor/upd96050/instructions.cpp b/bsnes/processor/upd96050/instructions.cpp new file mode 100755 index 00000000..62226738 --- /dev/null +++ b/bsnes/processor/upd96050/instructions.cpp @@ -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; + } +} diff --git a/bsnes/snes/chip/necdsp/memory.cpp b/bsnes/processor/upd96050/memory.cpp similarity index 68% rename from bsnes/snes/chip/necdsp/memory.cpp rename to bsnes/processor/upd96050/memory.cpp index 0b11d594..62c5bb62 100755 --- a/bsnes/snes/chip/necdsp/memory.cpp +++ b/bsnes/processor/upd96050/memory.cpp @@ -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 diff --git a/bsnes/snes/chip/necdsp/registers.hpp b/bsnes/processor/upd96050/registers.hpp similarity index 100% rename from bsnes/snes/chip/necdsp/registers.hpp rename to bsnes/processor/upd96050/registers.hpp diff --git a/bsnes/processor/upd96050/serialization.cpp b/bsnes/processor/upd96050/serialization.cpp new file mode 100755 index 00000000..024cd087 --- /dev/null +++ b/bsnes/processor/upd96050/serialization.cpp @@ -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); +} diff --git a/bsnes/processor/upd96050/upd96050.cpp b/bsnes/processor/upd96050/upd96050.cpp new file mode 100755 index 00000000..390cfefb --- /dev/null +++ b/bsnes/processor/upd96050/upd96050.cpp @@ -0,0 +1,45 @@ +#include +#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; +} + +} diff --git a/bsnes/processor/upd96050/upd96050.hpp b/bsnes/processor/upd96050/upd96050.hpp new file mode 100755 index 00000000..a20cfa67 --- /dev/null +++ b/bsnes/processor/upd96050/upd96050.hpp @@ -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 diff --git a/bsnes/ruby/video/glx.cpp b/bsnes/ruby/video/glx.cpp index 7e1fec0b..74a4f991 100755 --- a/bsnes/ruby/video/glx.cpp +++ b/bsnes/ruby/video/glx.cpp @@ -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, }; diff --git a/bsnes/snes/chip/necdsp/necdsp.cpp b/bsnes/snes/chip/necdsp/necdsp.cpp index 9f92131a..b0267dcf 100755 --- a/bsnes/snes/chip/necdsp/necdsp.cpp +++ b/bsnes/snes/chip/necdsp/necdsp.cpp @@ -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(); } } diff --git a/bsnes/snes/chip/necdsp/necdsp.hpp b/bsnes/snes/chip/necdsp/necdsp.hpp index 3c041cf7..fcdd2573 100755 --- a/bsnes/snes/chip/necdsp/necdsp.hpp +++ b/bsnes/snes/chip/necdsp/necdsp.hpp @@ -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; diff --git a/bsnes/snes/chip/necdsp/serialization.cpp b/bsnes/snes/chip/necdsp/serialization.cpp index 8ec267f7..2d28c754 100755 --- a/bsnes/snes/chip/necdsp/serialization.cpp +++ b/bsnes/snes/chip/necdsp/serialization.cpp @@ -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 diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index 4eb32b6e..88548408 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -4,11 +4,12 @@ #include #include #include +#include namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const unsigned SerializerVersion = 23; + static const unsigned SerializerVersion = 24; } } diff --git a/bsnes/target-ui/Makefile b/bsnes/target-ui/Makefile index aac70529..285b9f39 100755 --- a/bsnes/target-ui/Makefile +++ b/bsnes/target-ui/Makefile @@ -1,4 +1,4 @@ -processors := arm hg51b +processors := arm hg51b upd96050 include processor/Makefile include $(nes)/Makefile diff --git a/bsnes/target-ui/main.cpp b/bsnes/target-ui/main.cpp index 2c2d7c2c..f3a4b49d 100755 --- a/bsnes/target-ui/main.cpp +++ b/bsnes/target-ui/main.cpp @@ -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();