mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
395e5a5639
commit
e16dd58184
|
@ -92,7 +92,7 @@ sync:
|
||||||
rm -r phoenix/nall
|
rm -r phoenix/nall
|
||||||
rm -r phoenix/test
|
rm -r phoenix/test
|
||||||
|
|
||||||
archive-all:
|
archive:
|
||||||
if [ -f bsnes.tar.bz2 ]; then rm bsnes.tar.bz2; fi
|
if [ -f bsnes.tar.bz2 ]; then rm bsnes.tar.bz2; fi
|
||||||
tar -cjf bsnes.tar.bz2 `ls`
|
tar -cjf bsnes.tar.bz2 `ls`
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef BASE_HPP
|
#ifndef BASE_HPP
|
||||||
#define BASE_HPP
|
#define BASE_HPP
|
||||||
|
|
||||||
static const char Version[] = "087.08";
|
static const char Version[] = "087.09";
|
||||||
|
|
||||||
#include <nall/platform.hpp>
|
#include <nall/platform.hpp>
|
||||||
#include <nall/algorithm.hpp>
|
#include <nall/algorithm.hpp>
|
||||||
|
|
|
@ -19,6 +19,11 @@ void APU::step(unsigned clocks) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 APU::read(uint32 addr, uint32 size) {
|
uint32 APU::read(uint32 addr, uint32 size) {
|
||||||
|
if(addr == 0x04000088) {
|
||||||
|
//SOUNDBIAS
|
||||||
|
return 0x0200;
|
||||||
|
}
|
||||||
|
|
||||||
return 0u;
|
return 0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +32,8 @@ void APU::write(uint32 addr, uint32 size, uint32 word) {
|
||||||
|
|
||||||
void APU::power() {
|
void APU::power() {
|
||||||
create(APU::Enter, 16777216);
|
create(APU::Enter, 16777216);
|
||||||
|
|
||||||
|
bus.mmio[0x0088] = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,6 @@ void CPU::power() {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 CPU::read(uint32 addr, uint32 size) {
|
uint32 CPU::read(uint32 addr, uint32 size) {
|
||||||
if(addr == 0x04000300) return prng() & 1;
|
|
||||||
return 0u;
|
return 0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ namespace GBA {
|
||||||
Bus bus;
|
Bus bus;
|
||||||
|
|
||||||
struct UnmappedMemory : Memory {
|
struct UnmappedMemory : Memory {
|
||||||
uint32 read(uint32 addr, uint32 size) { return 0u; }
|
uint32 read(uint32 addr, uint32 size) { print(hex<8>(addr), ":", decimal<2>(size), "\n"); return 0u; }
|
||||||
void write(uint32 addr, uint32 size, uint32 word) {}
|
void write(uint32 addr, uint32 size, uint32 word) { print(hex<8>(addr), ":", decimal<2>(size), "=", hex<8>(word), "\n"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
static UnmappedMemory unmappedMemory;
|
static UnmappedMemory unmappedMemory;
|
||||||
|
|
|
@ -27,7 +27,7 @@ struct map {
|
||||||
signed middle = (first + last) / 2;
|
signed middle = (first + last) / 2;
|
||||||
if(name < list[middle].name) last = middle - 1; //search lower half
|
if(name < list[middle].name) last = middle - 1; //search lower half
|
||||||
else if(list[middle].name < name) first = middle + 1; //search upper 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 };
|
return { false, 0u };
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
@ -52,13 +52,13 @@ struct Color {
|
||||||
struct Position {
|
struct Position {
|
||||||
signed x, y;
|
signed x, y;
|
||||||
inline Position() : x(0), y(0) {}
|
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 {
|
struct Size {
|
||||||
unsigned width, height;
|
unsigned width, height;
|
||||||
inline Size() : width(0), height(0) {}
|
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 {
|
struct Geometry {
|
||||||
|
@ -69,7 +69,7 @@ struct Geometry {
|
||||||
nall::string text() const;
|
nall::string text() const;
|
||||||
inline Geometry() : x(0), y(0), width(0), height(0) {}
|
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(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);
|
Geometry(const nall::string &text);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,8 @@ struct pWindow : public pObject {
|
||||||
GtkWidget *statusContainer;
|
GtkWidget *statusContainer;
|
||||||
GtkWidget *menu;
|
GtkWidget *menu;
|
||||||
GtkWidget *status;
|
GtkWidget *status;
|
||||||
GdkEventConfigure lastConfigure;
|
GtkAllocation lastAllocation;
|
||||||
|
bool onSizePending;
|
||||||
|
|
||||||
void append(Layout &layout);
|
void append(Layout &layout);
|
||||||
void append(Menu &menu);
|
void append(Menu &menu);
|
||||||
|
|
|
@ -53,36 +53,27 @@ static gboolean Window_configure(GtkWidget *widget, GdkEvent *event, Window *win
|
||||||
settings->save();
|
settings->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Geometry geometry = {
|
||||||
|
client.x,
|
||||||
|
client.y + window->p.menuHeight(),
|
||||||
|
client.width,
|
||||||
|
client.height - window->p.menuHeight() - window->p.statusHeight()
|
||||||
|
};
|
||||||
|
|
||||||
//move
|
//move
|
||||||
if(event->configure.x != window->p.lastConfigure.x
|
if(geometry.x != window->state.geometry.x || geometry.y != window->state.geometry.y) {
|
||||||
|| event->configure.y != window->p.lastConfigure.y
|
|
||||||
) {
|
|
||||||
if(window->state.fullScreen == false) {
|
if(window->state.fullScreen == false) {
|
||||||
window->state.geometry.x = client.x;
|
window->state.geometry.x = geometry.x;
|
||||||
window->state.geometry.y = client.y + window->p.menuHeight();
|
window->state.geometry.y = geometry.y;
|
||||||
}
|
}
|
||||||
if(window->p.locked == false && window->onMove) window->onMove();
|
if(window->p.locked == false && window->onMove) window->onMove();
|
||||||
}
|
}
|
||||||
|
|
||||||
//size
|
//size
|
||||||
if(event->configure.width != window->p.lastConfigure.width
|
if(geometry.width != window->state.geometry.width || geometry.height != window->state.geometry.height) {
|
||||||
|| event->configure.height != window->p.lastConfigure.height
|
window->p.onSizePending = true;
|
||||||
) {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
window->p.lastConfigure = event->configure;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +89,33 @@ static gboolean Window_keyReleaseEvent(GtkWidget *widget, GdkEventKey *event, Wi
|
||||||
return false;
|
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) {
|
void pWindow::append(Layout &layout) {
|
||||||
Geometry geometry = this->geometry();
|
Geometry geometry = this->geometry();
|
||||||
geometry.x = geometry.y = 0;
|
geometry.x = geometry.y = 0;
|
||||||
|
@ -131,7 +149,13 @@ Color pWindow::backgroundColor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Geometry pWindow::frameMargin() {
|
Geometry pWindow::frameMargin() {
|
||||||
if(window.state.fullScreen) return { 0, menuHeight(), 0, menuHeight() + statusHeight() };
|
if(window.state.fullScreen) return {
|
||||||
|
0,
|
||||||
|
menuHeight(),
|
||||||
|
0,
|
||||||
|
menuHeight() + statusHeight()
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
settings->frameGeometryX,
|
settings->frameGeometryX,
|
||||||
settings->frameGeometryY + menuHeight(),
|
settings->frameGeometryY + menuHeight(),
|
||||||
|
@ -145,9 +169,13 @@ bool pWindow::focused() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Geometry pWindow::geometry() {
|
Geometry pWindow::geometry() {
|
||||||
if(window.state.fullScreen == true) {
|
if(window.state.fullScreen == true) return {
|
||||||
return { 0, menuHeight(), Desktop::size().width, Desktop::size().height - menuHeight() - statusHeight() };
|
0,
|
||||||
|
menuHeight(),
|
||||||
|
Desktop::size().width,
|
||||||
|
Desktop::size().height - menuHeight() - statusHeight()
|
||||||
};
|
};
|
||||||
|
|
||||||
return window.state.geometry;
|
return window.state.geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,38 +206,23 @@ void pWindow::setFocused() {
|
||||||
void pWindow::setFullScreen(bool fullScreen) {
|
void pWindow::setFullScreen(bool fullScreen) {
|
||||||
if(fullScreen == false) {
|
if(fullScreen == false) {
|
||||||
gtk_window_unfullscreen(GTK_WINDOW(widget));
|
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 {
|
} else {
|
||||||
gtk_window_fullscreen(GTK_WINDOW(widget));
|
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) {
|
void pWindow::setGeometry(const Geometry &geometry) {
|
||||||
OS::processEvents();
|
|
||||||
|
|
||||||
Geometry margin = frameMargin();
|
Geometry margin = frameMargin();
|
||||||
gtk_window_move(GTK_WINDOW(widget), geometry.x - margin.x, geometry.y - margin.y);
|
gtk_window_move(GTK_WINDOW(widget), geometry.x - margin.x, geometry.y - margin.y);
|
||||||
|
|
||||||
//GdkGeometry geom;
|
GdkGeometry geom;
|
||||||
//geom.min_width = 1;
|
geom.min_width = window.state.resizable ? 1 : window.state.geometry.width;
|
||||||
//geom.min_height = 1;
|
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_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_widget_set_size_request(formContainer, geometry.width, geometry.height);
|
||||||
gtk_window_resize(GTK_WINDOW(widget), geometry.width, geometry.height + menuHeight() + statusHeight());
|
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) {
|
void pWindow::setMenuFont(const string &font) {
|
||||||
|
@ -244,6 +257,19 @@ void pWindow::setTitle(const string &text) {
|
||||||
|
|
||||||
void pWindow::setVisible(bool visible) {
|
void pWindow::setVisible(bool visible) {
|
||||||
gtk_widget_set_visible(widget, 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) {
|
void pWindow::setWidgetFont(const string &font) {
|
||||||
|
@ -253,7 +279,10 @@ void pWindow::setWidgetFont(const string &font) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::constructor() {
|
void pWindow::constructor() {
|
||||||
memset(&lastConfigure, 0, sizeof(GdkEventConfigure));
|
lastAllocation.width = 0;
|
||||||
|
lastAllocation.height = 0;
|
||||||
|
onSizePending = false;
|
||||||
|
|
||||||
widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||||
|
|
||||||
if(gdk_screen_is_composited(gdk_screen_get_default())) {
|
if(gdk_screen_is_composited(gdk_screen_get_default())) {
|
||||||
|
@ -289,6 +318,7 @@ void pWindow::constructor() {
|
||||||
gtk_widget_show(statusContainer);
|
gtk_widget_show(statusContainer);
|
||||||
|
|
||||||
setTitle("");
|
setTitle("");
|
||||||
|
setResizable(window.state.resizable);
|
||||||
setGeometry(window.state.geometry);
|
setGeometry(window.state.geometry);
|
||||||
setMenuFont("Sans, 8");
|
setMenuFont("Sans, 8");
|
||||||
setStatusFont("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), "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-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(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() {
|
unsigned pWindow::menuHeight() {
|
||||||
|
|
|
@ -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.hpp"
|
||||||
#include "platform.moc"
|
#include "platform.moc"
|
||||||
#include "utility.cpp"
|
#include "utility.cpp"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** Meta object code from reading C++ file 'platform.moc.hpp'
|
** 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)
|
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3)
|
||||||
**
|
**
|
||||||
** WARNING! All changes made in this file will be lost!
|
** WARNING! All changes made in this file will be lost!
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
processor_objects :=
|
processor_objects :=
|
||||||
processor_objects += $(if $(findstring arm,$(processors)),processor-arm)
|
processor_objects += $(if $(findstring arm,$(processors)),processor-arm)
|
||||||
processor_objects += $(if $(findstring hg51b,$(processors)),processor-hg51b)
|
processor_objects += $(if $(findstring hg51b,$(processors)),processor-hg51b)
|
||||||
|
processor_objects += $(if $(findstring upd96050,$(processors)),processor-upd96050)
|
||||||
objects += $(processor_objects)
|
objects += $(processor_objects)
|
||||||
|
|
||||||
processor := processor
|
processor := processor
|
||||||
obj/processor-arm.o: $(processor)/arm/arm.cpp $(call rwildcard,$(processor)/arm)
|
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-hg51b.o: $(processor)/hg51b/hg51b.cpp $(call rwildcard,$(processor)/hg51b)
|
||||||
|
obj/processor-upd96050.o: $(processor)/upd96050/upd96050.cpp $(call rwildcard,$(processor)/upd96050)
|
||||||
|
|
|
@ -568,13 +568,13 @@ string ARM::disassemble_thumb_instruction(uint32 pc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//move_multiple()
|
//move_multiple()
|
||||||
//(ldmia,stmdb) rn,{r...}
|
//(ldmia,stmia) rn,{r...}
|
||||||
if((instruction & 0xf000) == 0xc000) {
|
if((instruction & 0xf000) == 0xc000) {
|
||||||
uint1 load = instruction >> 11;
|
uint1 load = instruction >> 11;
|
||||||
uint3 rn = instruction >> 8;
|
uint3 rn = instruction >> 8;
|
||||||
uint8 list = instruction;
|
uint8 list = instruction;
|
||||||
|
|
||||||
output.append(load ? "ldmia " : "stmdb ", registers[rn], "!,{");
|
output.append(load ? "ldmia " : "stmia ", registers[rn], "!,{");
|
||||||
for(unsigned l = 0; l < 8; l++) {
|
for(unsigned l = 0; l < 8; l++) {
|
||||||
if(list & (1 << l)) output.append(registers[l], ",");
|
if(list & (1 << l)) output.append(registers[l], ",");
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ void ARM::arm_step() {
|
||||||
if((instruction() & 0x0fb000f0) == 0x01000000) { arm_op_move_to_register_from_status(); return; }
|
if((instruction() & 0x0fb000f0) == 0x01000000) { arm_op_move_to_register_from_status(); return; }
|
||||||
if((instruction() & 0x0fb000f0) == 0x01000090) { arm_op_memory_swap(); return; }
|
if((instruction() & 0x0fb000f0) == 0x01000090) { arm_op_memory_swap(); return; }
|
||||||
if((instruction() & 0x0fb000f0) == 0x01200000) { arm_op_move_to_status_from_register(); 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() & 0x0fb00000) == 0x03200000) { arm_op_move_to_status_from_immediate(); return; }
|
||||||
|
|
||||||
if((instruction() & 0x0e000010) == 0x00000000) { arm_op_data_immediate_shift(); 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() {
|
void ARM::arm_op_branch_exchange_register() {
|
||||||
uint4 m = instruction();
|
uint4 m = instruction();
|
||||||
|
|
||||||
r(15) = r(m);
|
|
||||||
cpsr().t = r(m) & 1;
|
cpsr().t = r(m) & 1;
|
||||||
|
r(15) = r(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
//msr{condition} (c,s)psr:{fields},#immediate
|
//msr{condition} (c,s)psr:{fields},#immediate
|
||||||
|
|
|
@ -96,15 +96,6 @@ uint32 ARM::thumb_tst(uint32 modify) {
|
||||||
return 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 ARM::thumb_add(uint32 source, uint32 modify, bool carry) {
|
||||||
uint32 result = source + modify + carry;
|
uint32 result = source + modify + carry;
|
||||||
uint32 overflow = ~(source ^ modify) & (source ^ result);
|
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 ARM::thumb_sub(uint32 source, uint32 modify, bool carry) {
|
||||||
uint32 result = source - modify + carry;
|
thumb_add(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 ARM::thumb_lsl(uint32 source, uint32 modify) {
|
uint32 ARM::thumb_lsl(uint32 source, uint32 modify) {
|
||||||
|
@ -240,7 +225,7 @@ void ARM::thumb_op_immediate() {
|
||||||
|
|
||||||
switch(opcode) {
|
switch(opcode) {
|
||||||
case 0: r(d) = thumb_tst( immediate); break;
|
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 2: r(d) = thumb_add(r(d), immediate); break;
|
||||||
case 3: r(d) = thumb_sub(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() {
|
void ARM::thumb_op_branch_exchange() {
|
||||||
uint4 m = instruction() >> 3;
|
uint4 m = instruction() >> 3;
|
||||||
|
|
||||||
r(15) = r(m);
|
|
||||||
cpsr().t = r(m) & 1;
|
cpsr().t = r(m) & 1;
|
||||||
|
r(15) = r(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
//{opcode} rd,rm
|
//{opcode} rd,rm
|
||||||
|
@ -423,34 +408,30 @@ void ARM::thumb_op_stack_multiple() {
|
||||||
uint1 branch = instruction() >> 8;
|
uint1 branch = instruction() >> 8;
|
||||||
uint8 list = instruction();
|
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++) {
|
for(unsigned l = 0; l < 8; l++) {
|
||||||
if(list & (1 << l)) {
|
if(list & (1 << l)) {
|
||||||
r(l) = bus_read(r(13), Word);
|
if(load == 1) r(l) = bus_read(sp, Word); //POP
|
||||||
r(13) += 4;
|
if(load == 0) bus_write(sp, Word, r(l)); //PUSH
|
||||||
}
|
sp += 4;
|
||||||
}
|
|
||||||
if(branch) {
|
|
||||||
r(15) = bus_read(r(13), Word);
|
|
||||||
r(13) += 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) {
|
if(branch) {
|
||||||
r(13) -= 4;
|
//note: ARMv5+ POP sets cpsr().t
|
||||||
bus_write(r(13), Word, r(14));
|
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
|
//1100 lnnn llll llll
|
||||||
//l = load (0 = save)
|
//l = load (0 = save)
|
||||||
//n = rn
|
//n = rn
|
||||||
|
@ -460,25 +441,15 @@ void ARM::thumb_op_move_multiple() {
|
||||||
uint3 n = instruction() >> 8;
|
uint3 n = instruction() >> 8;
|
||||||
uint8 list = instruction();
|
uint8 list = instruction();
|
||||||
|
|
||||||
if(load == 1) {
|
|
||||||
for(unsigned l = 0; l < 8; l++) {
|
for(unsigned l = 0; l < 8; l++) {
|
||||||
if(list & (1 << 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;
|
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
|
//swi #immediate
|
||||||
//1101 1111 iiii iiii
|
//1101 1111 iiii iiii
|
||||||
//i = immediate
|
//i = immediate
|
||||||
|
@ -513,9 +484,9 @@ void ARM::thumb_op_branch_short() {
|
||||||
//1111 0ooo oooo oooo
|
//1111 0ooo oooo oooo
|
||||||
//o = offset
|
//o = offset
|
||||||
void ARM::thumb_op_branch_long_prefix() {
|
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
|
//bl address
|
||||||
|
@ -524,9 +495,8 @@ void ARM::thumb_op_branch_long_prefix() {
|
||||||
void ARM::thumb_op_branch_long_suffix() {
|
void ARM::thumb_op_branch_long_suffix() {
|
||||||
uint11 offsetlo = instruction();
|
uint11 offsetlo = instruction();
|
||||||
|
|
||||||
int22 displacement = ((uint11)r(14) << 11) | offsetlo;
|
r(15) = r(14) + (offsetlo * 2);
|
||||||
r(14) = r(15) | 1;
|
r(14) = pipeline.decode.address | 1;
|
||||||
r(15) += displacement * 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,7 +4,6 @@ bool thumb_condition(uint4 condition);
|
||||||
void thumb_opcode(uint4 opcode, uint4 d, uint4 s);
|
void thumb_opcode(uint4 opcode, uint4 d, uint4 s);
|
||||||
|
|
||||||
uint32 thumb_tst(uint32 modify);
|
uint32 thumb_tst(uint32 modify);
|
||||||
void thumb_cmp(uint32 source, uint32 modify);
|
|
||||||
uint32 thumb_add(uint32 source, uint32 modify, bool carry = 0);
|
uint32 thumb_add(uint32 source, uint32 modify, bool carry = 0);
|
||||||
uint32 thumb_sub(uint32 source, uint32 modify, bool carry = 1);
|
uint32 thumb_sub(uint32 source, uint32 modify, bool carry = 1);
|
||||||
uint32 thumb_lsl(uint32 source, uint32 modify);
|
uint32 thumb_lsl(uint32 source, uint32 modify);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,11 @@
|
||||||
#ifdef NECDSP_CPP
|
uint8 uPD96050::sr_read() {
|
||||||
|
|
||||||
uint8 NECDSP::sr_read(unsigned) {
|
|
||||||
cpu.synchronize_coprocessors();
|
|
||||||
return regs.sr >> 8;
|
return regs.sr >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::sr_write(unsigned, uint8 data) {
|
void uPD96050::sr_write(uint8 data) {
|
||||||
cpu.synchronize_coprocessors();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 NECDSP::dr_read(unsigned) {
|
uint8 uPD96050::dr_read() {
|
||||||
cpu.synchronize_coprocessors();
|
|
||||||
if(regs.sr.drc == 0) {
|
if(regs.sr.drc == 0) {
|
||||||
//16-bit
|
//16-bit
|
||||||
if(regs.sr.drs == 0) {
|
if(regs.sr.drs == 0) {
|
||||||
|
@ -28,8 +23,7 @@ uint8 NECDSP::dr_read(unsigned) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::dr_write(unsigned, uint8 data) {
|
void uPD96050::dr_write(uint8 data) {
|
||||||
cpu.synchronize_coprocessors();
|
|
||||||
if(regs.sr.drc == 0) {
|
if(regs.sr.drc == 0) {
|
||||||
//16-bit
|
//16-bit
|
||||||
if(regs.sr.drs == 0) {
|
if(regs.sr.drs == 0) {
|
||||||
|
@ -47,8 +41,7 @@ void NECDSP::dr_write(unsigned, uint8 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 NECDSP::dp_read(unsigned addr) {
|
uint8 uPD96050::dp_read(uint12 addr) {
|
||||||
cpu.synchronize_coprocessors();
|
|
||||||
bool hi = addr & 1;
|
bool hi = addr & 1;
|
||||||
addr = (addr >> 1) & 2047;
|
addr = (addr >> 1) & 2047;
|
||||||
|
|
||||||
|
@ -59,8 +52,7 @@ uint8 NECDSP::dp_read(unsigned addr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::dp_write(unsigned addr, uint8 data) {
|
void uPD96050::dp_write(uint12 addr, uint8 data) {
|
||||||
cpu.synchronize_coprocessors();
|
|
||||||
bool hi = addr & 1;
|
bool hi = addr & 1;
|
||||||
addr = (addr >> 1) & 2047;
|
addr = (addr >> 1) & 2047;
|
||||||
|
|
||||||
|
@ -70,5 +62,3 @@ void NECDSP::dp_write(unsigned addr, uint8 data) {
|
||||||
dataRAM[addr] = (dataRAM[addr] & 0x00ff) | (data << 8);
|
dataRAM[addr] = (dataRAM[addr] & 0x00ff) | (data << 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
|
@ -164,8 +164,6 @@ public:
|
||||||
bool init() {
|
bool init() {
|
||||||
term();
|
term();
|
||||||
|
|
||||||
// display = XOpenDisplay(0);
|
|
||||||
// screen = DefaultScreen(display);
|
|
||||||
glXQueryVersion(display, &glx.version_major, &glx.version_minor);
|
glXQueryVersion(display, &glx.version_major, &glx.version_minor);
|
||||||
//require GLX 1.2+ API
|
//require GLX 1.2+ API
|
||||||
if(glx.version_major < 1 || (glx.version_major == 1 && glx.version_minor < 2)) return false;
|
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_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||||
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||||
GLX_DOUBLEBUFFER, True,
|
GLX_DOUBLEBUFFER, True,
|
||||||
GLX_RED_SIZE, (settings.depth / 3),
|
GLX_RED_SIZE, (signed)(settings.depth / 3),
|
||||||
GLX_GREEN_SIZE, (settings.depth / 3) + (settings.depth % 3),
|
GLX_GREEN_SIZE, (signed)(settings.depth / 3) + (signed)(settings.depth % 3),
|
||||||
GLX_BLUE_SIZE, (settings.depth / 3),
|
GLX_BLUE_SIZE, (signed)(settings.depth / 3),
|
||||||
None,
|
None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
#define NECDSP_CPP
|
#define NECDSP_CPP
|
||||||
namespace SNES {
|
namespace SNES {
|
||||||
|
|
||||||
#include "memory.cpp"
|
|
||||||
#include "disassembler.cpp"
|
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
NECDSP necdsp;
|
NECDSP necdsp;
|
||||||
|
|
||||||
|
@ -16,231 +14,20 @@ void NECDSP::enter() {
|
||||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint24 opcode = programROM[regs.pc++];
|
exec();
|
||||||
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
|
|
||||||
|
|
||||||
step(1);
|
step(1);
|
||||||
synchronize_cpu();
|
synchronize_cpu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::exec_op(uint24 opcode) {
|
uint8 NECDSP::sr_read(unsigned) { cpu.synchronize_coprocessors(); return uPD96050::sr_read(); }
|
||||||
uint2 pselect = opcode >> 20; //P select
|
void NECDSP::sr_write(unsigned, uint8 data) { cpu.synchronize_coprocessors(); return uPD96050::sr_write(data); }
|
||||||
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;
|
uint8 NECDSP::dr_read(unsigned) { cpu.synchronize_coprocessors(); return uPD96050::dr_read(); }
|
||||||
switch(src) {
|
void NECDSP::dr_write(unsigned, uint8 data) { cpu.synchronize_coprocessors(); return uPD96050::dr_write(data); }
|
||||||
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) {
|
uint8 NECDSP::dp_read(unsigned addr) { cpu.synchronize_coprocessors(); return uPD96050::dp_read(addr); }
|
||||||
uint16 p, q, r;
|
void NECDSP::dp_write(unsigned addr, uint8 data) { cpu.synchronize_coprocessors(); return uPD96050::dp_write(addr, data); }
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NECDSP::init() {
|
void NECDSP::init() {
|
||||||
}
|
}
|
||||||
|
@ -255,47 +42,11 @@ void NECDSP::unload() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NECDSP::power() {
|
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() {
|
void NECDSP::reset() {
|
||||||
create(NECDSP::Enter, frequency);
|
create(NECDSP::Enter, frequency);
|
||||||
|
uPD96050::power();
|
||||||
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() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,7 @@
|
||||||
//NEC uPD7725
|
struct NECDSP : Processor::uPD96050, Coprocessor {
|
||||||
//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;
|
|
||||||
|
|
||||||
static void Enter();
|
static void Enter();
|
||||||
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);
|
uint8 sr_read(unsigned);
|
||||||
void sr_write(unsigned, uint8 data);
|
void sr_write(unsigned, uint8 data);
|
||||||
|
|
||||||
|
@ -42,8 +18,6 @@ public:
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
void serialize(serializer&);
|
void serialize(serializer&);
|
||||||
NECDSP();
|
|
||||||
~NECDSP();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NECDSP necdsp;
|
extern NECDSP necdsp;
|
||||||
|
|
|
@ -1,55 +1,8 @@
|
||||||
#ifdef NECDSP_CPP
|
#ifdef NECDSP_CPP
|
||||||
|
|
||||||
void NECDSP::serialize(serializer &s) {
|
void NECDSP::serialize(serializer &s) {
|
||||||
|
uPD96050::serialize(s);
|
||||||
Thread::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
|
#endif
|
||||||
|
|
|
@ -4,11 +4,12 @@
|
||||||
#include <base/base.hpp>
|
#include <base/base.hpp>
|
||||||
#include <processor/arm/arm.hpp>
|
#include <processor/arm/arm.hpp>
|
||||||
#include <processor/hg51b/hg51b.hpp>
|
#include <processor/hg51b/hg51b.hpp>
|
||||||
|
#include <processor/upd96050/upd96050.hpp>
|
||||||
|
|
||||||
namespace SNES {
|
namespace SNES {
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const unsigned SerializerVersion = 23;
|
static const unsigned SerializerVersion = 24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
processors := arm hg51b
|
processors := arm hg51b upd96050
|
||||||
include processor/Makefile
|
include processor/Makefile
|
||||||
|
|
||||||
include $(nes)/Makefile
|
include $(nes)/Makefile
|
||||||
|
|
|
@ -123,6 +123,8 @@ Application::Application(int argc, char **argv) {
|
||||||
Application::run();
|
Application::run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(GBA::cartridge.loaded()) print(GBA::cpu.disassemble_registers(), "\n");
|
||||||
|
|
||||||
interface->unloadCartridge();
|
interface->unloadCartridge();
|
||||||
windowManager->saveGeometry();
|
windowManager->saveGeometry();
|
||||||
windowManager->hideAll();
|
windowManager->hideAll();
|
||||||
|
|
Loading…
Reference in New Issue