Back to BasiliskII uae_cpu but with ARAnyM JIT
This commit is contained in:
parent
1758ef58b5
commit
77e20bda2a
|
@ -36,25 +36,7 @@ extern void (*Screen_blit)(uint8 * dest, const uint8 * source, uint32 length);
|
|||
extern bool Screen_blitter_init(VisualFormat const & visual_format, bool native_byte_order, int mac_depth);
|
||||
extern uint32 ExpandMap[256];
|
||||
|
||||
// Glue for SheepShaver and BasiliskII
|
||||
#ifdef SHEEPSHAVER
|
||||
enum {
|
||||
VIDEO_DEPTH_1BIT = APPLE_1_BIT,
|
||||
VIDEO_DEPTH_2BIT = APPLE_2_BIT,
|
||||
VIDEO_DEPTH_4BIT = APPLE_4_BIT,
|
||||
VIDEO_DEPTH_8BIT = APPLE_8_BIT,
|
||||
VIDEO_DEPTH_16BIT = APPLE_16_BIT,
|
||||
VIDEO_DEPTH_32BIT = APPLE_32_BIT
|
||||
};
|
||||
#define VIDEO_MODE VideoInfo
|
||||
#define VIDEO_MODE_INIT VideoInfo const & mode = VModes[cur_mode]
|
||||
#define VIDEO_MODE_INIT_MONITOR VIDEO_MODE_INIT
|
||||
#define VIDEO_MODE_ROW_BYTES mode.viRowBytes
|
||||
#define VIDEO_MODE_X mode.viXsize
|
||||
#define VIDEO_MODE_Y mode.viYsize
|
||||
#define VIDEO_MODE_RESOLUTION mode.viAppleID
|
||||
#define VIDEO_MODE_DEPTH mode.viAppleMode
|
||||
#else
|
||||
// Glue for BasiliskII
|
||||
enum {
|
||||
VIDEO_DEPTH_1BIT = VDEPTH_1BIT,
|
||||
VIDEO_DEPTH_2BIT = VDEPTH_2BIT,
|
||||
|
@ -71,7 +53,6 @@ enum {
|
|||
#define VIDEO_MODE_Y mode.y
|
||||
#define VIDEO_MODE_RESOLUTION mode.resolution_id
|
||||
#define VIDEO_MODE_DEPTH mode.depth
|
||||
#endif
|
||||
|
||||
#endif /* VIDEO_BLIT_H */
|
||||
|
||||
|
|
|
@ -21,651 +21,4 @@
|
|||
#ifndef VIDEO_VOSF_H
|
||||
#define VIDEO_VOSF_H
|
||||
|
||||
// Note: this file must be #include'd only in video_x.cpp
|
||||
#ifdef ENABLE_VOSF
|
||||
|
||||
#include "sigsegv.h"
|
||||
#include "vm_alloc.h"
|
||||
|
||||
// Glue for SDL and X11 support
|
||||
#ifdef TEST_VOSF_PERFORMANCE
|
||||
#define MONITOR_INIT /* nothing */
|
||||
#else
|
||||
#ifdef USE_SDL_VIDEO
|
||||
#define MONITOR_INIT SDL_monitor_desc &monitor
|
||||
#define VIDEO_DRV_WIN_INIT driver_base *drv
|
||||
#define VIDEO_DRV_DGA_INIT driver_base *drv
|
||||
#define VIDEO_DRV_LOCK_PIXELS SDL_VIDEO_LOCK_SURFACE(drv->s)
|
||||
#define VIDEO_DRV_UNLOCK_PIXELS SDL_VIDEO_UNLOCK_SURFACE(drv->s)
|
||||
#define VIDEO_DRV_DEPTH drv->s->format->BitsPerPixel
|
||||
#define VIDEO_DRV_WIDTH drv->s->w
|
||||
#define VIDEO_DRV_HEIGHT drv->s->h
|
||||
#define VIDEO_DRV_ROW_BYTES drv->s->pitch
|
||||
#else
|
||||
#ifdef SHEEPSHAVER
|
||||
#define MONITOR_INIT /* nothing */
|
||||
#define VIDEO_DRV_WIN_INIT /* nothing */
|
||||
#define VIDEO_DRV_DGA_INIT /* nothing */
|
||||
#define VIDEO_DRV_WINDOW the_win
|
||||
#define VIDEO_DRV_GC the_gc
|
||||
#define VIDEO_DRV_IMAGE img
|
||||
#define VIDEO_DRV_HAVE_SHM have_shm
|
||||
#else
|
||||
#define MONITOR_INIT X11_monitor_desc &monitor
|
||||
#define VIDEO_DRV_WIN_INIT driver_window *drv
|
||||
#define VIDEO_DRV_DGA_INIT driver_dga *drv
|
||||
#define VIDEO_DRV_WINDOW drv->w
|
||||
#define VIDEO_DRV_GC drv->gc
|
||||
#define VIDEO_DRV_IMAGE drv->img
|
||||
#define VIDEO_DRV_HAVE_SHM drv->have_shm
|
||||
#endif
|
||||
#define VIDEO_DRV_LOCK_PIXELS /* nothing */
|
||||
#define VIDEO_DRV_UNLOCK_PIXELS /* nothing */
|
||||
#define VIDEO_DRV_DEPTH VIDEO_DRV_IMAGE->depth
|
||||
#define VIDEO_DRV_WIDTH VIDEO_DRV_IMAGE->width
|
||||
#define VIDEO_DRV_HEIGHT VIDEO_DRV_IMAGE->height
|
||||
#define VIDEO_DRV_ROW_BYTES VIDEO_DRV_IMAGE->bytes_per_line
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Prototypes
|
||||
static void vosf_do_set_dirty_area(uintptr first, uintptr last);
|
||||
static void vosf_set_dirty_area(int x, int y, int w, int h, unsigned screen_width, unsigned screen_height, unsigned bytes_per_row);
|
||||
|
||||
// Variables for Video on SEGV support
|
||||
static uint8 *the_host_buffer; // Host frame buffer in VOSF mode
|
||||
|
||||
struct ScreenPageInfo {
|
||||
unsigned top, bottom; // Mapping between this virtual page and Mac scanlines
|
||||
};
|
||||
|
||||
struct ScreenInfo {
|
||||
uintptr memStart; // Start address aligned to page boundary
|
||||
uint32 memLength; // Length of the memory addressed by the screen pages
|
||||
|
||||
uintptr pageSize; // Size of a page
|
||||
int pageBits; // Shift count to get the page number
|
||||
uint32 pageCount; // Number of pages allocated to the screen
|
||||
|
||||
bool dirty; // Flag: set if the frame buffer was touched
|
||||
bool very_dirty; // Flag: set if the frame buffer was completely modified (e.g. colormap changes)
|
||||
char * dirtyPages; // Table of flags set if page was altered
|
||||
ScreenPageInfo * pageInfo; // Table of mappings page -> Mac scanlines
|
||||
};
|
||||
|
||||
static ScreenInfo mainBuffer;
|
||||
|
||||
#define PFLAG_SET_VALUE 0x00
|
||||
#define PFLAG_CLEAR_VALUE 0x01
|
||||
#define PFLAG_SET_VALUE_4 0x00000000
|
||||
#define PFLAG_CLEAR_VALUE_4 0x01010101
|
||||
#define PFLAG_SET(page) mainBuffer.dirtyPages[page] = PFLAG_SET_VALUE
|
||||
#define PFLAG_CLEAR(page) mainBuffer.dirtyPages[page] = PFLAG_CLEAR_VALUE
|
||||
#define PFLAG_ISSET(page) (mainBuffer.dirtyPages[page] == PFLAG_SET_VALUE)
|
||||
#define PFLAG_ISCLEAR(page) (mainBuffer.dirtyPages[page] != PFLAG_SET_VALUE)
|
||||
|
||||
#ifdef UNALIGNED_PROFITABLE
|
||||
# define PFLAG_ISSET_4(page) (*((uint32 *)(mainBuffer.dirtyPages + (page))) == PFLAG_SET_VALUE_4)
|
||||
# define PFLAG_ISCLEAR_4(page) (*((uint32 *)(mainBuffer.dirtyPages + (page))) == PFLAG_CLEAR_VALUE_4)
|
||||
#else
|
||||
# define PFLAG_ISSET_4(page) \
|
||||
PFLAG_ISSET(page ) && PFLAG_ISSET(page+1) \
|
||||
&& PFLAG_ISSET(page+2) && PFLAG_ISSET(page+3)
|
||||
# define PFLAG_ISCLEAR_4(page) \
|
||||
PFLAG_ISCLEAR(page ) && PFLAG_ISCLEAR(page+1) \
|
||||
&& PFLAG_ISCLEAR(page+2) && PFLAG_ISCLEAR(page+3)
|
||||
#endif
|
||||
|
||||
// Set the selected page range [ first_page, last_page [ into the SET state
|
||||
#define PFLAG_SET_RANGE(first_page, last_page) \
|
||||
memset(mainBuffer.dirtyPages + (first_page), PFLAG_SET_VALUE, \
|
||||
(last_page) - (first_page))
|
||||
|
||||
// Set the selected page range [ first_page, last_page [ into the CLEAR state
|
||||
#define PFLAG_CLEAR_RANGE(first_page, last_page) \
|
||||
memset(mainBuffer.dirtyPages + (first_page), PFLAG_CLEAR_VALUE, \
|
||||
(last_page) - (first_page))
|
||||
|
||||
#define PFLAG_SET_ALL do { \
|
||||
PFLAG_SET_RANGE(0, mainBuffer.pageCount); \
|
||||
mainBuffer.dirty = true; \
|
||||
} while (0)
|
||||
|
||||
#define PFLAG_CLEAR_ALL do { \
|
||||
PFLAG_CLEAR_RANGE(0, mainBuffer.pageCount); \
|
||||
mainBuffer.dirty = false; \
|
||||
mainBuffer.very_dirty = false; \
|
||||
} while (0)
|
||||
|
||||
#define PFLAG_SET_VERY_DIRTY do { \
|
||||
mainBuffer.very_dirty = true; \
|
||||
} while (0)
|
||||
|
||||
// Set the following macro definition to 1 if your system
|
||||
// provides a really fast strchr() implementation
|
||||
//#define HAVE_FAST_STRCHR 0
|
||||
|
||||
static inline unsigned find_next_page_set(unsigned page)
|
||||
{
|
||||
#if HAVE_FAST_STRCHR
|
||||
char *match = strchr(mainBuffer.dirtyPages + page, PFLAG_SET_VALUE);
|
||||
return match ? match - mainBuffer.dirtyPages : mainBuffer.pageCount;
|
||||
#else
|
||||
while (PFLAG_ISCLEAR_4(page))
|
||||
page += 4;
|
||||
while (PFLAG_ISCLEAR(page))
|
||||
page++;
|
||||
return page;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline unsigned find_next_page_clear(unsigned page)
|
||||
{
|
||||
#if HAVE_FAST_STRCHR
|
||||
char *match = strchr(mainBuffer.dirtyPages + page, PFLAG_CLEAR_VALUE);
|
||||
return match ? match - mainBuffer.dirtyPages : mainBuffer.pageCount;
|
||||
#else
|
||||
while (PFLAG_ISSET_4(page))
|
||||
page += 4;
|
||||
while (PFLAG_ISSET(page))
|
||||
page++;
|
||||
return page;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(HAVE_PTHREADS)
|
||||
static pthread_mutex_t vosf_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect frame buffer (dirtyPages in fact)
|
||||
#define LOCK_VOSF pthread_mutex_lock(&vosf_lock);
|
||||
#define UNLOCK_VOSF pthread_mutex_unlock(&vosf_lock);
|
||||
#elif defined(HAVE_SPINLOCKS)
|
||||
static spinlock_t vosf_lock = SPIN_LOCK_UNLOCKED; // Mutex to protect frame buffer (dirtyPages in fact)
|
||||
#define LOCK_VOSF spin_lock(&vosf_lock)
|
||||
#define UNLOCK_VOSF spin_unlock(&vosf_lock)
|
||||
#else
|
||||
#define LOCK_VOSF
|
||||
#define UNLOCK_VOSF
|
||||
#endif
|
||||
|
||||
static int log_base_2(uint32 x)
|
||||
{
|
||||
uint32 mask = 0x80000000;
|
||||
int l = 31;
|
||||
while (l >= 0 && (x & mask) == 0) {
|
||||
mask >>= 1;
|
||||
l--;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
// Extend size to page boundary
|
||||
static uint32 page_extend(uint32 size)
|
||||
{
|
||||
const uint32 page_size = vm_get_page_size();
|
||||
const uint32 page_mask = page_size - 1;
|
||||
return (size + page_mask) & ~page_mask;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check if VOSF acceleration is profitable on this platform
|
||||
*/
|
||||
|
||||
#ifndef VOSF_PROFITABLE_TRIES
|
||||
#define VOSF_PROFITABLE_TRIES VOSF_PROFITABLE_TRIES_DFL
|
||||
#endif
|
||||
const int VOSF_PROFITABLE_TRIES_DFL = 3; // Make 3 attempts for full screen update
|
||||
const int VOSF_PROFITABLE_THRESHOLD = 16667/2; // 60 Hz (half of the quantum)
|
||||
|
||||
static bool video_vosf_profitable(uint32 *duration_p = NULL, uint32 *n_page_faults_p = NULL)
|
||||
{
|
||||
uint32 duration = 0;
|
||||
uint32 n_tries = VOSF_PROFITABLE_TRIES;
|
||||
const uint32 n_page_faults = mainBuffer.pageCount * n_tries;
|
||||
|
||||
#ifdef SHEEPSHAVER
|
||||
const bool accel = PrefsFindBool("gfxaccel");
|
||||
#else
|
||||
const bool accel = false;
|
||||
#endif
|
||||
|
||||
for (uint32 i = 0; i < n_tries; i++) {
|
||||
uint64 start = GetTicks_usec();
|
||||
for (uint32 p = 0; p < mainBuffer.pageCount; p++) {
|
||||
uint8 *addr = (uint8 *)(mainBuffer.memStart + (p * mainBuffer.pageSize));
|
||||
if (accel)
|
||||
vosf_do_set_dirty_area((uintptr)addr, (uintptr)addr + mainBuffer.pageSize - 1);
|
||||
else
|
||||
addr[0] = 0; // Trigger Screen_fault_handler()
|
||||
}
|
||||
duration += uint32(GetTicks_usec() - start);
|
||||
|
||||
PFLAG_CLEAR_ALL;
|
||||
mainBuffer.dirty = false;
|
||||
if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (duration_p)
|
||||
*duration_p = duration;
|
||||
if (n_page_faults_p)
|
||||
*n_page_faults_p = n_page_faults;
|
||||
|
||||
D(bug("Triggered %d page faults in %ld usec (%.1f usec per fault)\n", n_page_faults, duration, double(duration) / double(n_page_faults)));
|
||||
return ((duration / n_tries) < (VOSF_PROFITABLE_THRESHOLD * (frame_skip ? frame_skip : 1)));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the VOSF system (mainBuffer structure, SIGSEGV handler)
|
||||
*/
|
||||
|
||||
static bool video_vosf_init(MONITOR_INIT)
|
||||
{
|
||||
VIDEO_MODE_INIT_MONITOR;
|
||||
|
||||
const uintptr page_size = vm_get_page_size();
|
||||
const uintptr page_mask = page_size - 1;
|
||||
|
||||
// Round up frame buffer base to page boundary
|
||||
mainBuffer.memStart = (((uintptr) the_buffer) + page_mask) & ~page_mask;
|
||||
|
||||
// The frame buffer size shall already be aligned to page boundary (use page_extend)
|
||||
mainBuffer.memLength = the_buffer_size;
|
||||
|
||||
mainBuffer.pageSize = page_size;
|
||||
mainBuffer.pageBits = log_base_2(mainBuffer.pageSize);
|
||||
mainBuffer.pageCount = (mainBuffer.memLength + page_mask)/mainBuffer.pageSize;
|
||||
|
||||
// The "2" more bytes requested are a safety net to insure the
|
||||
// loops in the update routines will terminate.
|
||||
// See "How can we deal with array overrun conditions ?" hereunder for further details.
|
||||
mainBuffer.dirtyPages = (char *) malloc(mainBuffer.pageCount + 2);
|
||||
if (mainBuffer.dirtyPages == NULL)
|
||||
return false;
|
||||
|
||||
PFLAG_CLEAR_ALL;
|
||||
PFLAG_CLEAR(mainBuffer.pageCount);
|
||||
PFLAG_SET(mainBuffer.pageCount+1);
|
||||
|
||||
// Allocate and fill in pageInfo with start and end (inclusive) row in number of bytes
|
||||
mainBuffer.pageInfo = (ScreenPageInfo *) malloc(mainBuffer.pageCount * sizeof(ScreenPageInfo));
|
||||
if (mainBuffer.pageInfo == NULL)
|
||||
return false;
|
||||
|
||||
uint32 a = 0;
|
||||
for (unsigned i = 0; i < mainBuffer.pageCount; i++) {
|
||||
unsigned y1 = a / VIDEO_MODE_ROW_BYTES;
|
||||
if (y1 >= VIDEO_MODE_Y)
|
||||
y1 = VIDEO_MODE_Y - 1;
|
||||
|
||||
unsigned y2 = (a + mainBuffer.pageSize) / VIDEO_MODE_ROW_BYTES;
|
||||
if (y2 >= VIDEO_MODE_Y)
|
||||
y2 = VIDEO_MODE_Y - 1;
|
||||
|
||||
mainBuffer.pageInfo[i].top = y1;
|
||||
mainBuffer.pageInfo[i].bottom = y2;
|
||||
|
||||
a += mainBuffer.pageSize;
|
||||
if (a > mainBuffer.memLength)
|
||||
a = mainBuffer.memLength;
|
||||
}
|
||||
|
||||
// We can now write-protect the frame buffer
|
||||
if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0)
|
||||
return false;
|
||||
|
||||
// The frame buffer is sane, i.e. there is no write to it yet
|
||||
mainBuffer.dirty = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialize VOSF system
|
||||
*/
|
||||
|
||||
static void video_vosf_exit(void)
|
||||
{
|
||||
if (mainBuffer.pageInfo) {
|
||||
free(mainBuffer.pageInfo);
|
||||
mainBuffer.pageInfo = NULL;
|
||||
}
|
||||
if (mainBuffer.dirtyPages) {
|
||||
free(mainBuffer.dirtyPages);
|
||||
mainBuffer.dirtyPages = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Update VOSF state with specified dirty area
|
||||
*/
|
||||
|
||||
static void vosf_do_set_dirty_area(uintptr first, uintptr last)
|
||||
{
|
||||
const int first_page = (first - mainBuffer.memStart) >> mainBuffer.pageBits;
|
||||
const int last_page = (last - mainBuffer.memStart) >> mainBuffer.pageBits;
|
||||
uint8 *addr = (uint8 *)(first & ~(mainBuffer.pageSize - 1));
|
||||
for (int i = first_page; i <= last_page; i++) {
|
||||
if (PFLAG_ISCLEAR(i)) {
|
||||
PFLAG_SET(i);
|
||||
vm_protect(addr, mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE);
|
||||
}
|
||||
addr += mainBuffer.pageSize;
|
||||
}
|
||||
}
|
||||
|
||||
static void vosf_set_dirty_area(int x, int y, int w, int h, unsigned screen_width, unsigned screen_height, unsigned bytes_per_row)
|
||||
{
|
||||
if (x < 0) {
|
||||
w -= -x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0) {
|
||||
h -= -y;
|
||||
y = 0;
|
||||
}
|
||||
if (w <= 0 || h <= 0)
|
||||
return;
|
||||
if (unsigned(x + w) > screen_width)
|
||||
w -= unsigned(x + w) - screen_width;
|
||||
if (unsigned(y + h) > screen_height)
|
||||
h -= unsigned(y + h) - screen_height;
|
||||
LOCK_VOSF;
|
||||
if (bytes_per_row >= screen_width) {
|
||||
const int bytes_per_pixel = bytes_per_row / screen_width;
|
||||
if (bytes_per_row <= mainBuffer.pageSize) {
|
||||
const uintptr a0 = mainBuffer.memStart + y * bytes_per_row + x * bytes_per_pixel;
|
||||
const uintptr a1 = mainBuffer.memStart + (y + h - 1) * bytes_per_row + (x + w - 1) * bytes_per_pixel;
|
||||
vosf_do_set_dirty_area(a0, a1);
|
||||
} else {
|
||||
for (int j = y; j < y + h; j++) {
|
||||
const uintptr a0 = mainBuffer.memStart + j * bytes_per_row + x * bytes_per_pixel;
|
||||
const uintptr a1 = a0 + (w - 1) * bytes_per_pixel;
|
||||
vosf_do_set_dirty_area(a0, a1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const int pixels_per_byte = screen_width / bytes_per_row;
|
||||
if (bytes_per_row <= mainBuffer.pageSize) {
|
||||
const uintptr a0 = mainBuffer.memStart + y * bytes_per_row + x / pixels_per_byte;
|
||||
const uintptr a1 = mainBuffer.memStart + (y + h - 1) * bytes_per_row + (x + w - 1) / pixels_per_byte;
|
||||
vosf_do_set_dirty_area(a0, a1);
|
||||
} else {
|
||||
for (int j = y; j < y + h; j++) {
|
||||
const uintptr a0 = mainBuffer.memStart + j * bytes_per_row + x / pixels_per_byte;
|
||||
const uintptr a1 = mainBuffer.memStart + j * bytes_per_row + (x + w - 1) / pixels_per_byte;
|
||||
vosf_do_set_dirty_area(a0, a1);
|
||||
}
|
||||
}
|
||||
}
|
||||
mainBuffer.dirty = true;
|
||||
UNLOCK_VOSF;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Screen fault handler
|
||||
*/
|
||||
|
||||
bool Screen_fault_handler(sigsegv_info_t *sip)
|
||||
{
|
||||
const uintptr addr = (uintptr)sigsegv_get_fault_address(sip);
|
||||
|
||||
/* Someone attempted to write to the frame buffer. Make it writeable
|
||||
* now so that the data could actually be written to. It will be made
|
||||
* read-only back in one of the screen update_*() functions.
|
||||
*/
|
||||
if (((uintptr)addr - mainBuffer.memStart) < mainBuffer.memLength) {
|
||||
const int page = ((uintptr)addr - mainBuffer.memStart) >> mainBuffer.pageBits;
|
||||
LOCK_VOSF;
|
||||
if (PFLAG_ISCLEAR(page)) {
|
||||
PFLAG_SET(page);
|
||||
vm_protect((char *)(addr & ~(mainBuffer.pageSize - 1)), mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE);
|
||||
}
|
||||
mainBuffer.dirty = true;
|
||||
UNLOCK_VOSF;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Otherwise, we don't know how to handle the fault, let it crash */
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Update display for Windowed mode and VOSF
|
||||
*/
|
||||
|
||||
/* How can we deal with array overrun conditions ?
|
||||
|
||||
The state of the framebuffer pages that have been touched are maintained
|
||||
in the dirtyPages[] table. That table is (pageCount + 2) bytes long.
|
||||
|
||||
Terminology
|
||||
|
||||
"Last Page" denotes the pageCount-nth page, i.e. dirtyPages[pageCount - 1].
|
||||
"CLEAR Page Guard" refers to the page following the Last Page but is always
|
||||
in the CLEAR state. "SET Page Guard" refers to the page following the CLEAR
|
||||
Page Guard but is always in the SET state.
|
||||
|
||||
Rough process
|
||||
|
||||
The update routines must determine which pages have to be blitted to the
|
||||
screen. This job consists in finding the first_page that was touched.
|
||||
i.e. find the next page that is SET. Then, finding how many pages were
|
||||
touched starting from first_page. i.e. find the next page that is CLEAR.
|
||||
|
||||
There are two cases to check:
|
||||
|
||||
- Last Page is CLEAR: find_next_page_set() will reach the SET Page Guard
|
||||
but it is beyond the valid pageCount value. Therefore, we exit from the
|
||||
update routine.
|
||||
|
||||
- Last Page is SET: first_page equals (pageCount - 1) and
|
||||
find_next_page_clear() will reach the CLEAR Page Guard. We blit the last
|
||||
page to the screen. On the next iteration, page equals pageCount and
|
||||
find_next_page_set() will reach the SET Page Guard. We still safely exit
|
||||
from the update routine because the SET Page Guard position is greater
|
||||
than pageCount.
|
||||
*/
|
||||
|
||||
#ifndef TEST_VOSF_PERFORMANCE
|
||||
static void update_display_window_vosf(VIDEO_DRV_WIN_INIT)
|
||||
{
|
||||
VIDEO_MODE_INIT;
|
||||
|
||||
unsigned page = 0;
|
||||
for (;;) {
|
||||
const unsigned first_page = find_next_page_set(page);
|
||||
if (first_page >= mainBuffer.pageCount)
|
||||
break;
|
||||
|
||||
page = find_next_page_clear(first_page);
|
||||
PFLAG_CLEAR_RANGE(first_page, page);
|
||||
|
||||
// Make the dirty pages read-only again
|
||||
const int32 offset = first_page << mainBuffer.pageBits;
|
||||
const uint32 length = (page - first_page) << mainBuffer.pageBits;
|
||||
vm_protect((char *)mainBuffer.memStart + offset, length, VM_PAGE_READ);
|
||||
|
||||
// There is at least one line to update
|
||||
const int y1 = mainBuffer.pageInfo[first_page].top;
|
||||
const int y2 = mainBuffer.pageInfo[page - 1].bottom;
|
||||
const int height = y2 - y1 + 1;
|
||||
|
||||
// Update the_host_buffer
|
||||
VIDEO_DRV_LOCK_PIXELS;
|
||||
const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES;
|
||||
const int dst_bytes_per_row = VIDEO_DRV_ROW_BYTES;
|
||||
int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j;
|
||||
for (j = y1; j <= y2; j++) {
|
||||
Screen_blit(the_host_buffer + i2, the_buffer + i1, src_bytes_per_row);
|
||||
i1 += src_bytes_per_row;
|
||||
i2 += dst_bytes_per_row;
|
||||
}
|
||||
VIDEO_DRV_UNLOCK_PIXELS;
|
||||
|
||||
#ifdef USE_SDL_VIDEO
|
||||
SDL_UpdateRect(drv->s, 0, y1, VIDEO_MODE_X, height);
|
||||
#else
|
||||
if (VIDEO_DRV_HAVE_SHM)
|
||||
XShmPutImage(x_display, VIDEO_DRV_WINDOW, VIDEO_DRV_GC, VIDEO_DRV_IMAGE, 0, y1, 0, y1, VIDEO_MODE_X, height, 0);
|
||||
else
|
||||
XPutImage(x_display, VIDEO_DRV_WINDOW, VIDEO_DRV_GC, VIDEO_DRV_IMAGE, 0, y1, 0, y1, VIDEO_MODE_X, height);
|
||||
#endif
|
||||
}
|
||||
mainBuffer.dirty = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Update display for DGA mode and VOSF
|
||||
* (only in Real or Direct Addressing mode)
|
||||
*/
|
||||
|
||||
#ifndef TEST_VOSF_PERFORMANCE
|
||||
#if DIRECT_ADDRESSING
|
||||
static void update_display_dga_vosf(VIDEO_DRV_DGA_INIT)
|
||||
{
|
||||
VIDEO_MODE_INIT;
|
||||
|
||||
// Compute number of bytes per row, take care to virtual screens
|
||||
const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES;
|
||||
const int dst_bytes_per_row = TrivialBytesPerRow(VIDEO_MODE_X, DepthModeForPixelDepth(VIDEO_DRV_DEPTH));
|
||||
const int scr_bytes_per_row = VIDEO_DRV_ROW_BYTES;
|
||||
assert(dst_bytes_per_row <= scr_bytes_per_row);
|
||||
const int scr_bytes_left = scr_bytes_per_row - dst_bytes_per_row;
|
||||
|
||||
// Full screen update requested?
|
||||
if (mainBuffer.very_dirty) {
|
||||
PFLAG_CLEAR_ALL;
|
||||
vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ);
|
||||
memcpy(the_buffer_copy, the_buffer, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y);
|
||||
VIDEO_DRV_LOCK_PIXELS;
|
||||
int i1 = 0, i2 = 0;
|
||||
for (uint32_t j = 0; j < VIDEO_MODE_Y; j++) {
|
||||
Screen_blit(the_host_buffer + i2, the_buffer + i1, src_bytes_per_row);
|
||||
i1 += src_bytes_per_row;
|
||||
i2 += scr_bytes_per_row;
|
||||
}
|
||||
#ifdef USE_SDL_VIDEO
|
||||
SDL_UpdateRect(drv->s, 0, 0, VIDEO_MODE_X, VIDEO_MODE_Y);
|
||||
#endif
|
||||
VIDEO_DRV_UNLOCK_PIXELS;
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup partial blitter (use 64-pixel wide chunks)
|
||||
const uint32 n_pixels = 64;
|
||||
const uint32 n_chunks = VIDEO_MODE_X / n_pixels;
|
||||
const uint32 n_pixels_left = VIDEO_MODE_X - (n_chunks * n_pixels);
|
||||
const uint32 src_chunk_size = src_bytes_per_row / n_chunks;
|
||||
const uint32 dst_chunk_size = dst_bytes_per_row / n_chunks;
|
||||
const uint32 src_chunk_size_left = src_bytes_per_row - (n_chunks * src_chunk_size);
|
||||
const uint32 dst_chunk_size_left = dst_bytes_per_row - (n_chunks * dst_chunk_size);
|
||||
|
||||
unsigned page = 0;
|
||||
uint32 last_scanline = uint32(-1);
|
||||
for (;;) {
|
||||
const unsigned first_page = find_next_page_set(page);
|
||||
if (first_page >= mainBuffer.pageCount)
|
||||
break;
|
||||
|
||||
page = find_next_page_clear(first_page);
|
||||
PFLAG_CLEAR_RANGE(first_page, page);
|
||||
|
||||
// Make the dirty pages read-only again
|
||||
const int32 offset = first_page << mainBuffer.pageBits;
|
||||
const uint32 length = (page - first_page) << mainBuffer.pageBits;
|
||||
vm_protect((char *)mainBuffer.memStart + offset, length, VM_PAGE_READ);
|
||||
|
||||
// Optimized for scanlines, don't process overlapping lines again
|
||||
uint32 y1 = mainBuffer.pageInfo[first_page].top;
|
||||
uint32 y2 = mainBuffer.pageInfo[page - 1].bottom;
|
||||
if (last_scanline != uint32(-1)) {
|
||||
if (y1 <= last_scanline && ++y1 >= VIDEO_MODE_Y)
|
||||
continue;
|
||||
if (y2 <= last_scanline && ++y2 >= VIDEO_MODE_Y)
|
||||
continue;
|
||||
}
|
||||
last_scanline = y2;
|
||||
|
||||
// Update the_host_buffer and copy of the_buffer, one line at a time
|
||||
uint32 i1 = y1 * src_bytes_per_row;
|
||||
uint32 i2 = y1 * scr_bytes_per_row;
|
||||
#ifdef USE_SDL_VIDEO
|
||||
int bbi = 0;
|
||||
SDL_Rect bb[3] = {
|
||||
{ Sint16(VIDEO_MODE_X), Sint16(y1), 0, 0 },
|
||||
{ Sint16(VIDEO_MODE_X), -1, 0, 0 },
|
||||
{ Sint16(VIDEO_MODE_X), -1, 0, 0 }
|
||||
};
|
||||
#endif
|
||||
VIDEO_DRV_LOCK_PIXELS;
|
||||
for (uint32 j = y1; j <= y2; j++) {
|
||||
for (uint32 i = 0; i < n_chunks; i++) {
|
||||
if (memcmp(the_buffer_copy + i1, the_buffer + i1, src_chunk_size) != 0) {
|
||||
memcpy(the_buffer_copy + i1, the_buffer + i1, src_chunk_size);
|
||||
Screen_blit(the_host_buffer + i2, the_buffer + i1, src_chunk_size);
|
||||
#ifdef USE_SDL_VIDEO
|
||||
const int x = i * n_pixels;
|
||||
if (x < bb[bbi].x) {
|
||||
if (bb[bbi].w)
|
||||
bb[bbi].w += bb[bbi].x - x;
|
||||
else
|
||||
bb[bbi].w = n_pixels;
|
||||
bb[bbi].x = x;
|
||||
}
|
||||
else if (x >= bb[bbi].x + bb[bbi].w)
|
||||
bb[bbi].w = x + n_pixels - bb[bbi].x;
|
||||
#endif
|
||||
}
|
||||
i1 += src_chunk_size;
|
||||
i2 += dst_chunk_size;
|
||||
}
|
||||
if (src_chunk_size_left && dst_chunk_size_left) {
|
||||
if (memcmp(the_buffer_copy + i1, the_buffer + i1, src_chunk_size_left) != 0) {
|
||||
memcpy(the_buffer_copy + i1, the_buffer + i1, src_chunk_size_left);
|
||||
Screen_blit(the_host_buffer + i2, the_buffer + i1, src_chunk_size_left);
|
||||
}
|
||||
i1 += src_chunk_size_left;
|
||||
i2 += dst_chunk_size_left;
|
||||
#ifdef USE_SDL_VIDEO
|
||||
const int x = n_chunks * n_pixels;
|
||||
if (x < bb[bbi].x) {
|
||||
if (bb[bbi].w)
|
||||
bb[bbi].w += bb[bbi].x - x;
|
||||
else
|
||||
bb[bbi].w = n_pixels_left;
|
||||
bb[bbi].x = x;
|
||||
}
|
||||
else if (x >= bb[bbi].x + bb[bbi].w)
|
||||
bb[bbi].w = x + n_pixels_left - bb[bbi].x;
|
||||
#endif
|
||||
}
|
||||
i2 += scr_bytes_left;
|
||||
#ifdef USE_SDL_VIDEO
|
||||
bb[bbi].h++;
|
||||
if (bb[bbi].w && (j == y1 || j == y2 - 1 || j == y2)) {
|
||||
bbi++;
|
||||
assert(bbi <= 3);
|
||||
if (j != y2)
|
||||
bb[bbi].y = j + 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_SDL_VIDEO
|
||||
SDL_UpdateRects(drv->s, bbi, bb);
|
||||
#endif
|
||||
VIDEO_DRV_UNLOCK_PIXELS;
|
||||
}
|
||||
mainBuffer.dirty = false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* ENABLE_VOSF */
|
||||
|
||||
#endif /* VIDEO_VOSF_H */
|
||||
|
|
|
@ -67,19 +67,11 @@ using std::vector;
|
|||
static vector<VIDEO_MODE> VideoModes;
|
||||
|
||||
// Display types
|
||||
#ifdef SHEEPSHAVER
|
||||
enum {
|
||||
DISPLAY_WINDOW = DIS_WINDOW, // windowed display
|
||||
DISPLAY_SCREEN = DIS_SCREEN // fullscreen display
|
||||
};
|
||||
extern int display_type; // See enum above
|
||||
#else
|
||||
enum {
|
||||
DISPLAY_WINDOW, // windowed display
|
||||
DISPLAY_SCREEN // fullscreen display
|
||||
};
|
||||
static int display_type = DISPLAY_WINDOW; // See enum above
|
||||
#endif
|
||||
|
||||
// Constants
|
||||
const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
|
||||
|
@ -102,11 +94,7 @@ static volatile bool thread_stop_req = false;
|
|||
static volatile bool thread_stop_ack = false; // Acknowledge for thread_stop_req
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_VOSF
|
||||
static bool use_vosf = false; // Flag: VOSF enabled
|
||||
#else
|
||||
static const bool use_vosf = false; // VOSF not possible
|
||||
#endif
|
||||
|
||||
static bool ctrl_down = false; // Flag: Ctrl key pressed
|
||||
static bool caps_on = false; // Flag: Caps Lock on
|
||||
|
@ -160,14 +148,7 @@ extern void SysMountFirstFloppy(void);
|
|||
* SDL surface locking glue
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_VOSF
|
||||
#define SDL_VIDEO_LOCK_VOSF_SURFACE(SURFACE) do { \
|
||||
if ((SURFACE)->flags & (SDL_HWSURFACE | SDL_FULLSCREEN)) \
|
||||
the_host_buffer = (uint8 *)(SURFACE)->pixels; \
|
||||
} while (0)
|
||||
#else
|
||||
#define SDL_VIDEO_LOCK_VOSF_SURFACE(SURFACE)
|
||||
#endif
|
||||
|
||||
#define SDL_VIDEO_LOCK_SURFACE(SURFACE) do { \
|
||||
if (SDL_MUSTLOCK(SURFACE)) { \
|
||||
|
@ -209,83 +190,6 @@ static inline void vm_release_framebuffer(void *fb, uint32 size)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* SheepShaver glue
|
||||
*/
|
||||
|
||||
#ifdef SHEEPSHAVER
|
||||
// Color depth modes type
|
||||
typedef int video_depth;
|
||||
|
||||
// 1, 2, 4 and 8 bit depths use a color palette
|
||||
static inline bool IsDirectMode(VIDEO_MODE const & mode)
|
||||
{
|
||||
return IsDirectMode(mode.viAppleMode);
|
||||
}
|
||||
|
||||
// Abstract base class representing one (possibly virtual) monitor
|
||||
// ("monitor" = rectangular display with a contiguous frame buffer)
|
||||
class monitor_desc {
|
||||
public:
|
||||
monitor_desc(const vector<VIDEO_MODE> &available_modes, video_depth default_depth, uint32 default_id) {}
|
||||
virtual ~monitor_desc() {}
|
||||
|
||||
// Get current Mac frame buffer base address
|
||||
uint32 get_mac_frame_base(void) const {return screen_base;}
|
||||
|
||||
// Set Mac frame buffer base address (called from switch_to_mode())
|
||||
void set_mac_frame_base(uint32 base) {screen_base = base;}
|
||||
|
||||
// Get current video mode
|
||||
const VIDEO_MODE &get_current_mode(void) const {return VModes[cur_mode];}
|
||||
|
||||
// Called by the video driver to switch the video mode on this display
|
||||
// (must call set_mac_frame_base())
|
||||
virtual void switch_to_current_mode(void) = 0;
|
||||
|
||||
// Called by the video driver to set the color palette (in indexed modes)
|
||||
// or the gamma table (in direct modes)
|
||||
virtual void set_palette(uint8 *pal, int num) = 0;
|
||||
};
|
||||
|
||||
// Vector of pointers to available monitor descriptions, filled by VideoInit()
|
||||
static vector<monitor_desc *> VideoMonitors;
|
||||
|
||||
// Find Apple mode matching best specified dimensions
|
||||
static int find_apple_resolution(int xsize, int ysize)
|
||||
{
|
||||
if (xsize == 640 && ysize == 480)
|
||||
return APPLE_640x480;
|
||||
if (xsize == 800 && ysize == 600)
|
||||
return APPLE_800x600;
|
||||
if (xsize == 1024 && ysize == 768)
|
||||
return APPLE_1024x768;
|
||||
if (xsize == 1152 && ysize == 768)
|
||||
return APPLE_1152x768;
|
||||
if (xsize == 1152 && ysize == 900)
|
||||
return APPLE_1152x900;
|
||||
if (xsize == 1280 && ysize == 1024)
|
||||
return APPLE_1280x1024;
|
||||
if (xsize == 1600 && ysize == 1200)
|
||||
return APPLE_1600x1200;
|
||||
return APPLE_CUSTOM;
|
||||
}
|
||||
|
||||
// Display error alert
|
||||
static void ErrorAlert(int error)
|
||||
{
|
||||
ErrorAlert(GetString(error));
|
||||
}
|
||||
|
||||
// Display warning alert
|
||||
static void WarningAlert(int warning)
|
||||
{
|
||||
WarningAlert(GetString(warning));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* monitor_desc subclass for SDL display
|
||||
*/
|
||||
|
@ -417,11 +321,6 @@ static inline int sdl_display_height(void)
|
|||
// Check wether specified mode is available
|
||||
static bool has_mode(int type, int width, int height, int depth)
|
||||
{
|
||||
#ifdef SHEEPSHAVER
|
||||
// Filter out Classic resolutions
|
||||
if (width == 512 && height == 384)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
// Filter out out-of-bounds resolutions
|
||||
if (width > sdl_display_width() || height > sdl_display_height())
|
||||
|
@ -442,10 +341,6 @@ static void add_mode(int type, int width, int height, int resolution_id, int byt
|
|||
|
||||
// Fill in VideoMode entry
|
||||
VIDEO_MODE mode;
|
||||
#ifdef SHEEPSHAVER
|
||||
resolution_id = find_apple_resolution(width, height);
|
||||
mode.viType = type;
|
||||
#endif
|
||||
VIDEO_MODE_X = width;
|
||||
VIDEO_MODE_Y = height;
|
||||
VIDEO_MODE_RESOLUTION = resolution_id;
|
||||
|
@ -483,50 +378,7 @@ static SDL_GrabMode set_grab_mode(SDL_GrabMode mode)
|
|||
// Migrate preferences items (XXX to be handled in MigratePrefs())
|
||||
static void migrate_screen_prefs(void)
|
||||
{
|
||||
#ifdef SHEEPSHAVER
|
||||
// Look-up priorities are: "screen", "screenmodes", "windowmodes".
|
||||
if (PrefsFindString("screen"))
|
||||
return;
|
||||
|
||||
uint32 window_modes = PrefsFindInt32("windowmodes");
|
||||
uint32 screen_modes = PrefsFindInt32("screenmodes");
|
||||
int width = 0, height = 0;
|
||||
if (screen_modes) {
|
||||
static const struct {
|
||||
int id;
|
||||
int width;
|
||||
int height;
|
||||
}
|
||||
modes[] = {
|
||||
{ 1, 640, 480 },
|
||||
{ 2, 800, 600 },
|
||||
{ 4, 1024, 768 },
|
||||
{ 64, 1152, 768 },
|
||||
{ 8, 1152, 900 },
|
||||
{ 16, 1280, 1024 },
|
||||
{ 32, 1600, 1200 },
|
||||
{ 0, }
|
||||
};
|
||||
for (int i = 0; modes[i].id != 0; i++) {
|
||||
if (screen_modes & modes[i].id) {
|
||||
if (width < modes[i].width && height < modes[i].height) {
|
||||
width = modes[i].width;
|
||||
height = modes[i].height;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (window_modes & 1)
|
||||
width = 640, height = 480;
|
||||
if (window_modes & 2)
|
||||
width = 800, height = 600;
|
||||
}
|
||||
if (width && height) {
|
||||
char str[32];
|
||||
sprintf(str, "%s/%d/%d", screen_modes ? "dga" : "win", width, height);
|
||||
PrefsReplaceString("screen", str);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -563,17 +415,10 @@ public:
|
|||
SDL_Surface *s; // The surface we draw into
|
||||
};
|
||||
|
||||
#ifdef ENABLE_VOSF
|
||||
static void update_display_window_vosf(driver_base *drv);
|
||||
#endif
|
||||
static void update_display_static(driver_base *drv);
|
||||
|
||||
static driver_base *drv = NULL; // Pointer to currently used driver object
|
||||
|
||||
#ifdef ENABLE_VOSF
|
||||
# include "video_vosf.h"
|
||||
#endif
|
||||
|
||||
driver_base::driver_base(SDL_monitor_desc &m)
|
||||
: monitor(m), mode(m.get_current_mode()), init_ok(false), s(NULL)
|
||||
{
|
||||
|
@ -587,9 +432,6 @@ void driver_base::set_video_mode(int flags)
|
|||
if ((s = SDL_SetVideoMode(VIDEO_MODE_X, VIDEO_MODE_Y, depth,
|
||||
SDL_HWSURFACE | flags)) == NULL)
|
||||
return;
|
||||
#ifdef ENABLE_VOSF
|
||||
the_host_buffer = (uint8 *)s->pixels;
|
||||
#endif
|
||||
}
|
||||
|
||||
void driver_base::init()
|
||||
|
@ -597,30 +439,6 @@ void driver_base::init()
|
|||
set_video_mode(display_type == DISPLAY_SCREEN ? SDL_FULLSCREEN : 0);
|
||||
int aligned_height = (VIDEO_MODE_Y + 15) & ~15;
|
||||
|
||||
#ifdef ENABLE_VOSF
|
||||
use_vosf = true;
|
||||
// Allocate memory for frame buffer (SIZE is extended to page-boundary)
|
||||
the_buffer_size = page_extend((aligned_height + 2) * s->pitch);
|
||||
the_buffer = (uint8 *)vm_acquire_framebuffer(the_buffer_size);
|
||||
the_buffer_copy = (uint8 *)malloc(the_buffer_size);
|
||||
D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer));
|
||||
|
||||
// Check whether we can initialize the VOSF subsystem and it's profitable
|
||||
if (!video_vosf_init(monitor)) {
|
||||
WarningAlert(STR_VOSF_INIT_ERR);
|
||||
use_vosf = false;
|
||||
}
|
||||
else if (!video_vosf_profitable()) {
|
||||
video_vosf_exit();
|
||||
printf("VOSF acceleration is not profitable on this platform, disabling it\n");
|
||||
use_vosf = false;
|
||||
}
|
||||
if (!use_vosf) {
|
||||
free(the_buffer_copy);
|
||||
vm_release(the_buffer, the_buffer_size);
|
||||
the_host_buffer = NULL;
|
||||
}
|
||||
#endif
|
||||
if (!use_vosf) {
|
||||
// Allocate memory for frame buffer
|
||||
the_buffer_size = (aligned_height + 2) * s->pitch;
|
||||
|
@ -654,18 +472,6 @@ void driver_base::adapt_to_video_mode() {
|
|||
|
||||
|
||||
bool hardware_cursor = false;
|
||||
#ifdef SHEEPSHAVER
|
||||
hardware_cursor = video_can_change_cursor();
|
||||
if (hardware_cursor) {
|
||||
// Create cursor
|
||||
if ((sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, 0, 0)) != NULL) {
|
||||
SDL_SetCursor(sdl_cursor);
|
||||
}
|
||||
}
|
||||
// Tell the video driver there's a change in cursor type
|
||||
if (private_data)
|
||||
private_data->cursorHardware = hardware_cursor;
|
||||
#endif
|
||||
// Hide cursor
|
||||
SDL_ShowCursor(hardware_cursor);
|
||||
|
||||
|
@ -698,18 +504,6 @@ driver_base::~driver_base()
|
|||
the_buffer_copy = NULL;
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_VOSF
|
||||
else {
|
||||
if (the_buffer_copy) {
|
||||
D(bug(" freeing the_buffer_copy at %p\n", the_buffer_copy));
|
||||
free(the_buffer_copy);
|
||||
the_buffer_copy = NULL;
|
||||
}
|
||||
|
||||
// Deinitialize VOSF
|
||||
video_vosf_exit();
|
||||
}
|
||||
#endif
|
||||
|
||||
SDL_ShowCursor(1);
|
||||
}
|
||||
|
@ -892,22 +686,10 @@ bool SDL_monitor_desc::video_open(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef SHEEPSHAVER
|
||||
bool VideoInit(void)
|
||||
{
|
||||
const bool classic = false;
|
||||
#else
|
||||
bool VideoInit(bool classic)
|
||||
{
|
||||
#endif
|
||||
classic_mode = classic;
|
||||
|
||||
#ifdef ENABLE_VOSF
|
||||
// Zero the mainBuffer structure
|
||||
mainBuffer.dirtyPages = NULL;
|
||||
mainBuffer.pageInfo = NULL;
|
||||
#endif
|
||||
|
||||
// Create Mutexes
|
||||
if ((sdl_events_lock = SDL_CreateMutex()) == NULL)
|
||||
return false;
|
||||
|
@ -1035,10 +817,6 @@ bool VideoInit(bool classic)
|
|||
const VIDEO_MODE & mode = (*i);
|
||||
if (VIDEO_MODE_X == default_width && VIDEO_MODE_Y == default_height && VIDEO_MODE_DEPTH == default_depth) {
|
||||
default_id = VIDEO_MODE_RESOLUTION;
|
||||
#ifdef SHEEPSHAVER
|
||||
std::vector<VIDEO_MODE>::const_iterator begin = VideoModes.begin();
|
||||
cur_mode = distance(begin, i);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1046,22 +824,8 @@ bool VideoInit(bool classic)
|
|||
const VIDEO_MODE & mode = VideoModes[0];
|
||||
default_depth = VIDEO_MODE_DEPTH;
|
||||
default_id = VIDEO_MODE_RESOLUTION;
|
||||
#ifdef SHEEPSHAVER
|
||||
cur_mode = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SHEEPSHAVER
|
||||
for (int i = 0; i < VideoModes.size(); i++)
|
||||
VModes[i] = VideoModes[i];
|
||||
VideoInfo *p = &VModes[VideoModes.size()];
|
||||
p->viType = DIS_INVALID; // End marker
|
||||
p->viRowBytes = 0;
|
||||
p->viXsize = p->viYsize = 0;
|
||||
p->viAppleMode = 0;
|
||||
p->viAppleID = 0;
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
D(bug("Available video modes:\n"));
|
||||
for (i = VideoModes.begin(); i != end; ++i) {
|
||||
|
@ -1162,9 +926,6 @@ static void do_toggle_fullscreen(void)
|
|||
drv->adapt_to_video_mode();
|
||||
|
||||
// reset the palette
|
||||
#ifdef SHEEPSHAVER
|
||||
video_set_palette();
|
||||
#endif
|
||||
drv->update_palette();
|
||||
|
||||
// restore the screen contents
|
||||
|
@ -1196,26 +957,6 @@ static void do_toggle_fullscreen(void)
|
|||
* Execute video VBL routine
|
||||
*/
|
||||
|
||||
#ifdef SHEEPSHAVER
|
||||
void VideoVBL(void)
|
||||
{
|
||||
// Emergency quit requested? Then quit
|
||||
if (emerg_quit)
|
||||
QuitEmulator();
|
||||
|
||||
if (toggle_fullscreen)
|
||||
do_toggle_fullscreen();
|
||||
|
||||
// Temporarily give up frame buffer lock (this is the point where
|
||||
// we are suspended when the user presses Ctrl-Tab)
|
||||
UNLOCK_FRAME_BUFFER;
|
||||
LOCK_FRAME_BUFFER;
|
||||
|
||||
// Execute video VBL
|
||||
if (private_data != NULL && private_data->interruptsEnabled)
|
||||
VSLDoInterruptService(private_data->vslServiceID);
|
||||
}
|
||||
#else
|
||||
void VideoInterrupt(void)
|
||||
{
|
||||
// We must fill in the events queue in the same thread that did call SDL_SetVideoMode()
|
||||
|
@ -1233,28 +974,12 @@ void VideoInterrupt(void)
|
|||
UNLOCK_FRAME_BUFFER;
|
||||
LOCK_FRAME_BUFFER;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Set palette
|
||||
*/
|
||||
|
||||
#ifdef SHEEPSHAVER
|
||||
void video_set_palette(void)
|
||||
{
|
||||
monitor_desc * monitor = VideoMonitors[0];
|
||||
int n_colors = palette_size(monitor->get_current_mode().viAppleMode);
|
||||
uint8 pal[256 * 3];
|
||||
for (int c = 0; c < n_colors; c++) {
|
||||
pal[c*3 + 0] = mac_pal[c].red;
|
||||
pal[c*3 + 1] = mac_pal[c].green;
|
||||
pal[c*3 + 2] = mac_pal[c].blue;
|
||||
}
|
||||
monitor->set_palette(pal, n_colors);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SDL_monitor_desc::set_palette(uint8 *pal, int num_in)
|
||||
{
|
||||
const VIDEO_MODE &mode = get_current_mode();
|
||||
|
@ -1284,15 +1009,6 @@ void SDL_monitor_desc::set_palette(uint8 *pal, int num_in)
|
|||
ExpandMap[i] = SDL_MapRGB(drv->s->format, pal[c*3+0], pal[c*3+1], pal[c*3+2]);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VOSF
|
||||
if (use_vosf) {
|
||||
// We have to redraw everything because the interpretation of pixel values changed
|
||||
LOCK_VOSF;
|
||||
PFLAG_SET_ALL;
|
||||
UNLOCK_VOSF;
|
||||
memset(the_buffer_copy, 0, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Tell redraw thread to change palette
|
||||
|
@ -1306,46 +1022,6 @@ void SDL_monitor_desc::set_palette(uint8 *pal, int num_in)
|
|||
* Switch video mode
|
||||
*/
|
||||
|
||||
#ifdef SHEEPSHAVER
|
||||
int16 video_mode_change(VidLocals *csSave, uint32 ParamPtr)
|
||||
{
|
||||
/* return if no mode change */
|
||||
if ((csSave->saveData == ReadMacInt32(ParamPtr + csData)) &&
|
||||
(csSave->saveMode == ReadMacInt16(ParamPtr + csMode))) return noErr;
|
||||
|
||||
/* first find video mode in table */
|
||||
for (int i=0; VModes[i].viType != DIS_INVALID; i++) {
|
||||
if ((ReadMacInt16(ParamPtr + csMode) == VModes[i].viAppleMode) &&
|
||||
(ReadMacInt32(ParamPtr + csData) == VModes[i].viAppleID)) {
|
||||
csSave->saveMode = ReadMacInt16(ParamPtr + csMode);
|
||||
csSave->saveData = ReadMacInt32(ParamPtr + csData);
|
||||
csSave->savePage = ReadMacInt16(ParamPtr + csPage);
|
||||
|
||||
// Disable interrupts and pause redraw thread
|
||||
DisableInterrupt();
|
||||
thread_stop_ack = false;
|
||||
thread_stop_req = true;
|
||||
while (!thread_stop_ack) ;
|
||||
|
||||
cur_mode = i;
|
||||
monitor_desc *monitor = VideoMonitors[0];
|
||||
monitor->switch_to_current_mode();
|
||||
|
||||
WriteMacInt32(ParamPtr + csBaseAddr, screen_base);
|
||||
csSave->saveBaseAddr=screen_base;
|
||||
csSave->saveData=VModes[cur_mode].viAppleID;/* First mode ... */
|
||||
csSave->saveMode=VModes[cur_mode].viAppleMode;
|
||||
|
||||
// Enable interrupts and resume redraw thread
|
||||
thread_stop_req = false;
|
||||
EnableInterrupt();
|
||||
return noErr;
|
||||
}
|
||||
}
|
||||
return paramErr;
|
||||
}
|
||||
#endif
|
||||
|
||||
void SDL_monitor_desc::switch_to_current_mode(void)
|
||||
{
|
||||
// Close and reopen display
|
||||
|
@ -1360,77 +1036,6 @@ void SDL_monitor_desc::switch_to_current_mode(void)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Can we set the MacOS cursor image into the window?
|
||||
*/
|
||||
|
||||
#ifdef SHEEPSHAVER
|
||||
bool video_can_change_cursor(void)
|
||||
{
|
||||
if (display_type != DISPLAY_WINDOW)
|
||||
return false;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
static char driver[] = "Quartz?";
|
||||
static int quartzok = -1;
|
||||
|
||||
if (quartzok < 0) {
|
||||
if (SDL_VideoDriverName(driver, sizeof driver) == NULL || strncmp(driver, "Quartz", sizeof driver))
|
||||
quartzok = true;
|
||||
else {
|
||||
// Quartz driver bug prevents cursor changing in SDL 1.2.11 to 1.2.14.
|
||||
const SDL_version *vp = SDL_Linked_Version();
|
||||
int version = SDL_VERSIONNUM(vp->major, vp->minor, vp->patch);
|
||||
quartzok = (version <= SDL_VERSIONNUM(1, 2, 10) || version >= SDL_VERSIONNUM(1, 2, 15));
|
||||
}
|
||||
}
|
||||
|
||||
return quartzok;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Set cursor image for window
|
||||
*/
|
||||
|
||||
#ifdef SHEEPSHAVER
|
||||
void video_set_cursor(void)
|
||||
{
|
||||
// Set new cursor image if it was changed
|
||||
if (sdl_cursor) {
|
||||
SDL_FreeCursor(sdl_cursor);
|
||||
sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, MacCursor[2], MacCursor[3]);
|
||||
if (sdl_cursor) {
|
||||
SDL_ShowCursor(private_data == NULL || private_data->cursorVisible);
|
||||
SDL_SetCursor(sdl_cursor);
|
||||
|
||||
// XXX Windows apparently needs an extra mouse event to
|
||||
// make the new cursor image visible.
|
||||
// On Mac, if mouse is grabbed, SDL_ShowCursor() recenters the
|
||||
// mouse, we have to put it back.
|
||||
bool move = false;
|
||||
#if defined(__APPLE__)
|
||||
move = mouse_grabbed;
|
||||
#endif
|
||||
if (move) {
|
||||
int visible = SDL_ShowCursor(-1);
|
||||
if (visible) {
|
||||
int x, y;
|
||||
SDL_GetMouseState(&x, &y);
|
||||
SDL_WarpMouse(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Keyboard-related utilify functions
|
||||
*/
|
||||
|
@ -1609,13 +1214,6 @@ static int event2keycode(SDL_KeyboardEvent const &ev, bool key_down)
|
|||
static void force_complete_window_refresh()
|
||||
{
|
||||
if (display_type == DISPLAY_WINDOW) {
|
||||
#ifdef ENABLE_VOSF
|
||||
if (use_vosf) { // VOSF refresh
|
||||
LOCK_VOSF;
|
||||
PFLAG_SET_ALL;
|
||||
UNLOCK_VOSF;
|
||||
}
|
||||
#endif
|
||||
// Ensure each byte of the_buffer_copy differs from the_buffer to force a full update.
|
||||
const VIDEO_MODE &mode = VideoMonitors[0]->get_current_mode();
|
||||
const int len = VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y;
|
||||
|
@ -2017,43 +1615,6 @@ static void video_refresh_dga(void)
|
|||
video_refresh_window_static();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VOSF
|
||||
#if DIRECT_ADDRESSING
|
||||
static void video_refresh_dga_vosf(void)
|
||||
{
|
||||
// Quit DGA mode if requested
|
||||
possibly_quit_dga_mode();
|
||||
|
||||
// Update display (VOSF variant)
|
||||
static uint32 tick_counter = 0;
|
||||
if (++tick_counter >= frame_skip) {
|
||||
tick_counter = 0;
|
||||
if (mainBuffer.dirty) {
|
||||
LOCK_VOSF;
|
||||
update_display_dga_vosf(drv);
|
||||
UNLOCK_VOSF;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void video_refresh_window_vosf(void)
|
||||
{
|
||||
// Ungrab mouse if requested
|
||||
possibly_ungrab_mouse();
|
||||
|
||||
// Update display (VOSF variant)
|
||||
static uint32 tick_counter = 0;
|
||||
if (++tick_counter >= frame_skip) {
|
||||
tick_counter = 0;
|
||||
if (mainBuffer.dirty) {
|
||||
LOCK_VOSF;
|
||||
update_display_window_vosf(drv);
|
||||
UNLOCK_VOSF;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // def ENABLE_VOSF
|
||||
|
||||
static void video_refresh_window_static(void)
|
||||
{
|
||||
|
@ -2081,20 +1642,10 @@ static void VideoRefreshInit(void)
|
|||
{
|
||||
// TODO: set up specialised 8bpp VideoRefresh handlers ?
|
||||
if (display_type == DISPLAY_SCREEN) {
|
||||
#if ENABLE_VOSF && (DIRECT_ADDRESSING)
|
||||
if (use_vosf)
|
||||
video_refresh = video_refresh_dga_vosf;
|
||||
else
|
||||
#endif
|
||||
video_refresh = video_refresh_dga;
|
||||
video_refresh = video_refresh_dga;
|
||||
}
|
||||
else {
|
||||
#ifdef ENABLE_VOSF
|
||||
if (use_vosf)
|
||||
video_refresh = video_refresh_window_vosf;
|
||||
else
|
||||
#endif
|
||||
video_refresh = video_refresh_window_static;
|
||||
video_refresh = video_refresh_window_static;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2159,27 +1710,3 @@ static int redraw_func(void *arg)
|
|||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Record dirty area from NQD
|
||||
*/
|
||||
|
||||
#ifdef SHEEPSHAVER
|
||||
void video_set_dirty_area(int x, int y, int w, int h)
|
||||
{
|
||||
#ifdef ENABLE_VOSF
|
||||
const VIDEO_MODE &mode = drv->mode;
|
||||
const unsigned screen_width = VIDEO_MODE_X;
|
||||
const unsigned screen_height = VIDEO_MODE_Y;
|
||||
const unsigned bytes_per_row = VIDEO_MODE_ROW_BYTES;
|
||||
|
||||
if (use_vosf) {
|
||||
vosf_set_dirty_area(x, y, w, h, screen_width, screen_height, bytes_per_row);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// XXX handle dirty bounding boxes for non-VOSF modes
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,7 @@ project(BasiliskII)
|
|||
find_package(SDL REQUIRED)
|
||||
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
|
||||
find_library(IOKIT_LIBRARY IOKit)
|
||||
include_directories(../include . ../CrossPlatform ../uae_cpu ${SDL_INCLUDE_DIR})
|
||||
include_directories(../include . ../CrossPlatform ../uae_cpu ${SDL_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(build68k ../uae_cpu/build68k.c)
|
||||
|
||||
|
@ -15,7 +15,12 @@ add_custom_command(OUTPUT cpudefs.cpp
|
|||
|
||||
add_executable(gencpu ../uae_cpu/gencpu.c ../uae_cpu/readcpu.cpp cpudefs.cpp)
|
||||
|
||||
add_custom_command(OUTPUT cpuemu.cpp cpustbl.cpp cpufunctbl.cpp COMMAND gencpu DEPENDS gencpu)
|
||||
#add_custom_command(OUTPUT cpuemu.cpp cpustbl.cpp cpufunctbl.cpp COMMAND gencpu DEPENDS gencpu)
|
||||
add_custom_command(OUTPUT cpuemu.cpp cpuemu_nf.cpp cpustbl.cpp cpustbl_nf.cpp COMMAND gencpu DEPENDS gencpu)
|
||||
|
||||
add_executable(gencomp ../uae_cpu/compiler/gencomp.c ../uae_cpu/readcpu.cpp cpudefs.cpp)
|
||||
|
||||
add_custom_command(OUTPUT compemu.cpp compstbl.cpp comptbl.h COMMAND gencomp DEPENDS gencomp)
|
||||
|
||||
set(BasiliskII_SRCS
|
||||
../main.cpp
|
||||
|
@ -76,11 +81,16 @@ set(BasiliskII_SRCS
|
|||
../uae_cpu/basilisk_glue.cpp
|
||||
../uae_cpu/newcpu.cpp
|
||||
../uae_cpu/readcpu.cpp
|
||||
../uae_cpu/fpu/fpu_uae.cpp
|
||||
../uae_cpu/fpu/fpu_ieee.cpp
|
||||
cpustbl.cpp
|
||||
cpudefs.cpp
|
||||
cpuemu.cpp
|
||||
cpufunctbl.cpp
|
||||
compemu.cpp
|
||||
compstbl.cpp
|
||||
../uae_cpu/compiler/compemu_support.cpp
|
||||
../uae_cpu/compiler/compemu_fpp.cpp
|
||||
cpustbl_nf.cpp
|
||||
cpuemu_nf.cpp
|
||||
#addressing mode =direct -DDIRECT_ADDRESSING
|
||||
#includes
|
||||
)
|
||||
|
@ -88,10 +98,15 @@ set(BasiliskII_SRCS
|
|||
add_executable(BasiliskII ${BasiliskII_SRCS})
|
||||
|
||||
set_source_files_properties(${BasiliskII_SRCS}
|
||||
PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DFPU_UAE -DDATADIR=\\\".\\\"")
|
||||
PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DCPU_x86_64 -DFIXED_ADDRESSING -DCPU_64_BIT -DNOFLAGS_SUPPORT -DFPU_IEEE -DUSE_JIT -DJIT -DX86_64_ASSEMBLY -DOPTIMIZED_FLAGS -DWINUAE_ARANYM -DUSE_JIT_FPU -DUSE_INLINING -DDATADIR=\\\".\\\"")
|
||||
|
||||
# set_property(SOURCE compemu_support.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -O0 ")
|
||||
|
||||
target_link_libraries(BasiliskII ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${SDL_LIBRARY})
|
||||
|
||||
SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pagezero_size 0x2000" )
|
||||
|
||||
add_definitions(-march=native)
|
||||
|
||||
|
||||
#keycodes -> ../SDL/keycodes
|
||||
|
|
|
@ -57,6 +57,10 @@ using std::string;
|
|||
#include "sigsegv.h"
|
||||
#include "rpc.h"
|
||||
|
||||
#if USE_JIT
|
||||
extern void flush_icache_range(uint8 *start, uint32 size); // from compemu_support.cpp
|
||||
#endif
|
||||
|
||||
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
@ -166,12 +170,6 @@ static int vm_acquire_mac_fixed(void *addr, size_t size)
|
|||
static sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip)
|
||||
{
|
||||
const uintptr fault_address = (uintptr)sigsegv_get_fault_address(sip);
|
||||
#if ENABLE_VOSF
|
||||
// Handle screen fault
|
||||
extern bool Screen_fault_handler(sigsegv_info_t *sip);
|
||||
if (Screen_fault_handler(sip))
|
||||
return SIGSEGV_RETURN_SUCCESS;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION
|
||||
// Ignore writes to ROM
|
||||
|
@ -199,10 +197,13 @@ static void sigsegv_dump_state(sigsegv_info_t *sip)
|
|||
fprintf(stderr, " [IP=%p]", fault_instruction);
|
||||
fprintf(stderr, "\n");
|
||||
#if EMULATED_68K
|
||||
extern void m68k_dumpstate (FILE *, uaecptr *);
|
||||
m68k_dumpstate(stderr, 0);
|
||||
extern void m68k_dumpstate (uaecptr *);
|
||||
m68k_dumpstate(0);
|
||||
#endif
|
||||
#if USE_JIT && JIT_DEBUG
|
||||
extern void compiler_dumpstate(void);
|
||||
compiler_dumpstate();
|
||||
#endif
|
||||
|
||||
VideoQuitFullScreen();
|
||||
|
||||
QuitEmulator();
|
||||
|
@ -652,7 +653,10 @@ void QuitEmulator(void)
|
|||
|
||||
void FlushCodeCache(void *start, uint32 size)
|
||||
{
|
||||
|
||||
#if USE_JIT
|
||||
if (UseJIT)
|
||||
flush_icache_range((uint8 *)start, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
#ifndef SYSDEPS_H
|
||||
#define SYSDEPS_H
|
||||
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) ((void)x)
|
||||
#endif
|
||||
|
||||
|
||||
#if 1
|
||||
|
@ -35,9 +37,6 @@
|
|||
/* Define if your system supports TUN/TAP devices. */
|
||||
/* #undef ENABLE_TUNTAP */
|
||||
|
||||
/* Define if using video enabled on SEGV signals. */
|
||||
#define ENABLE_VOSF 1
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#define HAVE_ARPA_INET_H 1
|
||||
|
||||
|
|
|
@ -31,6 +31,13 @@ extern int FPUType;
|
|||
// Flag: 24-bit-addressing?
|
||||
extern bool TwentyFourBitAddressing;
|
||||
|
||||
// 68k register structure (for Execute68k())
|
||||
struct M68kRegisters {
|
||||
uint32 d[8];
|
||||
uint32 a[8];
|
||||
uint16 sr;
|
||||
};
|
||||
|
||||
// General functions
|
||||
extern bool InitAll(const char *vmdir);
|
||||
extern void ExitAll(void);
|
||||
|
|
|
@ -53,12 +53,6 @@ extern int32 PrefsFindInt32(const char *name);
|
|||
|
||||
extern void PrefsRemoveItem(const char *name, int index = 0);
|
||||
|
||||
#ifdef SHEEPSHAVER
|
||||
// Platform specific functions:
|
||||
extern void prefs_init();
|
||||
extern void prefs_exit();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Definition of preferences items
|
||||
*/
|
||||
|
|
|
@ -121,11 +121,6 @@ void PrefsInit(const char *vmdir, int &argc, char **&argv)
|
|||
argc -= k;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SHEEPSHAVER
|
||||
// System specific initialization
|
||||
prefs_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -135,11 +130,6 @@ void PrefsInit(const char *vmdir, int &argc, char **&argv)
|
|||
|
||||
void PrefsExit(void)
|
||||
{
|
||||
#ifdef SHEEPSHAVER
|
||||
// System specific deinitialization
|
||||
prefs_exit();
|
||||
#endif
|
||||
|
||||
// Free prefs list
|
||||
prefs_node *p = the_prefs, *next;
|
||||
while (p) {
|
||||
|
|
|
@ -92,7 +92,17 @@ void AddPrefsDefaults(void)
|
|||
PrefsAddBool("noclipconversion", false);
|
||||
PrefsAddBool("nogui", false);
|
||||
|
||||
#if USE_JIT
|
||||
// JIT compiler specific options
|
||||
PrefsAddBool("jit", true);
|
||||
PrefsAddBool("jitfpu", true);
|
||||
PrefsAddBool("jitdebug", false);
|
||||
PrefsAddInt32("jitcachesize", 8192);
|
||||
PrefsAddBool("jitlazyflush", true);
|
||||
PrefsAddBool("jitinline", true);
|
||||
#else
|
||||
PrefsAddBool("jit", false);
|
||||
#endif
|
||||
|
||||
PrefsAddInt32("keyboardtype", 5);
|
||||
}
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
#
|
||||
# Note: this Makefile only contains rules for the source
|
||||
# generator tools.
|
||||
#
|
||||
|
||||
#
|
||||
# suppress warnings about overriding LDFLAGS and CPPFLAGS
|
||||
#
|
||||
AUTOMAKE_OPTIONS = -Wno-gnu
|
||||
|
||||
AM_CPPFLAGS = $(DEFINES) \
|
||||
"-I$(srcdir)/../include" \
|
||||
"-I$(srcdir)/../Unix" \
|
||||
"-I$(builddir)/.." \
|
||||
"-I$(builddir)" \
|
||||
"-I$(srcdir)"
|
||||
|
||||
CC = $(CC_FOR_BUILD)
|
||||
CXX = $(CXX_FOR_BUILD)
|
||||
|
||||
LDFLAGS = $(LDFLAGS_FOR_BUILD)
|
||||
CPPFLAGS = $(CPPFLAGS_FOR_BUILD)
|
||||
CFLAGS = $(CFLAGS_FOR_BUILD)
|
||||
CXXFLAGS = $(CXXFLAGS_FOR_BUILD)
|
||||
LIBS=-lm
|
||||
|
||||
CFLAGS_NOWARN = $(DBGSP)
|
||||
AM_CFLAGS = $(CFLAGS_NOWARN) $(WFLAGS)
|
||||
AM_CXXFLAGS = $(CFLAGS_NOWARN) $(WFLAGS)
|
||||
|
||||
noinst_PROGRAMS = build68k gencpu
|
||||
if USE_JIT
|
||||
noinst_PROGRAMS += gencomp
|
||||
endif
|
||||
|
||||
BUILT_SOURCES = \
|
||||
cpudefs.cpp \
|
||||
cpuemu.cpp \
|
||||
cpustbl.cpp \
|
||||
cpufunctbl.cpp \
|
||||
cputbl.h \
|
||||
$(empty)
|
||||
|
||||
build68k_SOURCES = build68k.c
|
||||
gencpu_SOURCES = gencpu.c m68k.h readcpu.cpp readcpu.h cpudefs.cpp
|
||||
gencomp_SOURCES =
|
||||
if GENCOMP_ARCH_X86
|
||||
gencomp_SOURCES += compiler/gencomp.c
|
||||
endif
|
||||
if GENCOMP_ARCH_ARM
|
||||
gencomp_SOURCES += compiler/gencomp_arm.c
|
||||
endif
|
||||
gencomp_SOURCES += readcpu.cpp cpudefs.cpp
|
||||
|
||||
if USE_JIT
|
||||
BUILT_SOURCES += compemu.cpp compstbl.cpp comptbl.h
|
||||
endif
|
||||
|
||||
|
||||
cpudefs.cpp: build68k$(EXEEXT) $(srcdir)/table68k
|
||||
./build68k <$(srcdir)/table68k > $@
|
||||
cpuemu.cpp: gencpu$(EXEEXT)
|
||||
./gencpu$(EXEEXT)
|
||||
cpustbl.cpp cpufunctbl.cpp cputbl.h: cpuemu.cpp
|
||||
compemu.cpp: gencomp$(EXEEXT)
|
||||
./gencomp$(EXEEXT)
|
||||
compstbl.cpp comptbl.h: compemu.cpp
|
||||
|
||||
CLEANFILES = $(BUILT_SOURCES)
|
||||
|
||||
EXTRA_DIST = \
|
||||
table68k \
|
||||
compiler/codegen_arm.cpp compiler/codegen_arm.h \
|
||||
compiler/compemu_midfunc_arm.cpp compiler/compemu_midfunc_arm.h \
|
||||
compiler/compemu_midfunc_arm2.cpp compiler/compemu_midfunc_arm2.h \
|
||||
compiler/test_codegen_arm.c \
|
||||
compiler/codegen_x86.cpp compiler/codegen_x86.h \
|
||||
compiler/compemu_midfunc_x86.cpp compiler/compemu_midfunc_x86.h \
|
||||
compiler/test_codegen_x86.cpp \
|
||||
$(empty)
|
|
@ -1,327 +0,0 @@
|
|||
/*
|
||||
* aranym_glue.cpp - CPU interface
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include "cpu_emulation.h"
|
||||
#include "newcpu.h"
|
||||
#include "hardware.h"
|
||||
#include "input.h"
|
||||
#ifdef USE_JIT
|
||||
# include "compiler/compemu.h"
|
||||
#endif
|
||||
#include "nf_objs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
// RAM and ROM pointers
|
||||
memptr RAMBase = 0; // RAM base (Atari address space) gb-- init is important
|
||||
uint8 *RAMBaseHost; // RAM base (host address space)
|
||||
uint32 RAMSize = 0x00e00000; // Size of RAM
|
||||
|
||||
memptr ROMBase = 0x00e00000; // ROM base (Atari address space)
|
||||
uint8 *ROMBaseHost; // ROM base (host address space)
|
||||
uint32 ROMSize = 0x00100000; // Size of ROM
|
||||
|
||||
uint32 RealROMSize; // Real size of ROM
|
||||
|
||||
memptr HWBase = 0x00f00000; // HW base (Atari address space)
|
||||
uint8 *HWBaseHost; // HW base (host address space)
|
||||
uint32 HWSize = 0x00100000; // Size of HW space
|
||||
|
||||
memptr FastRAMBase = 0x01000000; // Fast-RAM base (Atari address space)
|
||||
uint8 *FastRAMBaseHost; // Fast-RAM base (host address space)
|
||||
|
||||
#ifdef HW_SIGSEGV
|
||||
uint8 *FakeIOBaseHost;
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_VIDEORAM
|
||||
memptr VideoRAMBase = ARANYMVRAMSTART; // VideoRAM base (Atari address space)
|
||||
#else
|
||||
memptr VideoRAMBase; // VideoRAM base (Atari address space)
|
||||
#endif
|
||||
uint8 *VideoRAMBaseHost;// VideoRAM base (host address space)
|
||||
//uint32 VideoRAMSize; // Size of VideoRAM
|
||||
|
||||
#ifndef NOT_MALLOC
|
||||
uintptr MEMBaseDiff; // Global offset between a Atari address and its Host equivalent
|
||||
uintptr ROMBaseDiff;
|
||||
uintptr FastRAMBaseDiff;
|
||||
#endif
|
||||
|
||||
uintptr VMEMBaseDiff; // Global offset between a Atari VideoRAM address and /dev/fb0 mmap
|
||||
|
||||
// From newcpu.cpp
|
||||
extern int quit_program;
|
||||
|
||||
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
|
||||
SDL_mutex *spcflags_lock;
|
||||
#endif
|
||||
#if defined(ENABLE_REALSTOP)
|
||||
SDL_cond *stop_condition;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Initialize 680x0 emulation
|
||||
*/
|
||||
|
||||
bool InitMEM() {
|
||||
InitMEMBaseDiff(RAMBaseHost, RAMBase);
|
||||
InitROMBaseDiff(ROMBaseHost, ROMBase);
|
||||
InitFastRAMBaseDiff(FastRAMBaseHost, FastRAMBase);
|
||||
InitVMEMBaseDiff(VideoRAMBaseHost, VideoRAMBase);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Init680x0(void)
|
||||
{
|
||||
init_m68k();
|
||||
|
||||
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
|
||||
if ((spcflags_lock = SDL_CreateMutex()) == NULL) {
|
||||
panicbug("Error by SDL_CreateMutex()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_REALSTOP
|
||||
if ((stop_condition = SDL_CreateCond()) == NULL) {
|
||||
panicbug("Error by SDL_CreateCond()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_JIT
|
||||
if (bx_options.jit.jit) compiler_init();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Instr. RESET
|
||||
*/
|
||||
|
||||
void AtariReset(void)
|
||||
{
|
||||
// reset Atari hardware here
|
||||
HWReset();
|
||||
// reset NatFeats here
|
||||
NFReset();
|
||||
// reset the input devices (input.cpp)
|
||||
InputReset();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset CPU
|
||||
*/
|
||||
|
||||
void Reset680x0(void)
|
||||
{
|
||||
m68k_reset();
|
||||
}
|
||||
|
||||
/*
|
||||
* Deinitialize 680x0 emulation
|
||||
*/
|
||||
|
||||
void Exit680x0(void)
|
||||
{
|
||||
#ifdef USE_JIT
|
||||
if (bx_options.jit.jit) compiler_exit();
|
||||
#endif
|
||||
exit_m68k();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reset and start 680x0 emulation
|
||||
*/
|
||||
|
||||
void Start680x0(void)
|
||||
{
|
||||
m68k_reset();
|
||||
#ifdef USE_JIT
|
||||
if (bx_options.jit.jit) {
|
||||
m68k_compile_execute();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
m68k_execute();
|
||||
}
|
||||
|
||||
/*
|
||||
* Restart running 680x0 emulation safely from different thread
|
||||
*/
|
||||
void Restart680x0(void)
|
||||
{
|
||||
quit_program = 2;
|
||||
TriggerNMI();
|
||||
}
|
||||
|
||||
/*
|
||||
* Quit 680x0 emulation safely from different thread
|
||||
*/
|
||||
void Quit680x0(void)
|
||||
{
|
||||
quit_program = 1;
|
||||
TriggerNMI();
|
||||
}
|
||||
|
||||
|
||||
int MFPdoInterrupt(void)
|
||||
{
|
||||
return getMFP()->doInterrupt();
|
||||
}
|
||||
|
||||
int SCCdoInterrupt(void)
|
||||
{
|
||||
return getSCC()->doInterrupt();
|
||||
}
|
||||
|
||||
/*
|
||||
* Trigger interrupts
|
||||
*/
|
||||
void TriggerInternalIRQ(void)
|
||||
{
|
||||
SPCFLAGS_SET( SPCFLAG_INTERNAL_IRQ );
|
||||
}
|
||||
|
||||
void TriggerInt3(void)
|
||||
{
|
||||
SPCFLAGS_SET( SPCFLAG_INT3 );
|
||||
}
|
||||
|
||||
void TriggerVBL(void)
|
||||
{
|
||||
SPCFLAGS_SET( SPCFLAG_VBL );
|
||||
}
|
||||
|
||||
void TriggerInt5(void)
|
||||
{
|
||||
SPCFLAGS_SET( SPCFLAG_INT5 );
|
||||
}
|
||||
|
||||
void TriggerSCC(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
SPCFLAGS_SET( SPCFLAG_SCC );
|
||||
else
|
||||
SPCFLAGS_CLEAR( SPCFLAG_SCC );
|
||||
}
|
||||
|
||||
void TriggerMFP(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
SPCFLAGS_SET( SPCFLAG_MFP );
|
||||
else
|
||||
SPCFLAGS_CLEAR( SPCFLAG_MFP );
|
||||
}
|
||||
|
||||
void TriggerNMI(void)
|
||||
{
|
||||
SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI
|
||||
}
|
||||
|
||||
#ifndef REBOOT_OR_HALT
|
||||
#define REBOOT_OR_HALT 0 // halt by default
|
||||
#endif
|
||||
|
||||
#if REBOOT_OR_HALT == 1
|
||||
# define CPU_MSG "CPU: Rebooting"
|
||||
# define CPU_ACTION Restart680x0()
|
||||
#else
|
||||
# define CPU_MSG "CPU: Halting"
|
||||
# define CPU_ACTION Quit680x0()
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_EPSLIMITER
|
||||
|
||||
#ifndef EPS_LIMIT
|
||||
# define EPS_LIMIT 10000 /* this might be too high if ARAnyM is slowed down by printing the bus errors on console */
|
||||
#endif
|
||||
|
||||
void check_eps_limit(uaecptr pc)
|
||||
{
|
||||
static long last_exception_time=-1;
|
||||
static long exception_per_sec=0;
|
||||
static long exception_per_sec_pc=0;
|
||||
static uaecptr prevpc = 0;
|
||||
|
||||
if (bx_options.cpu.eps_enabled) {
|
||||
if (last_exception_time == -1) {
|
||||
last_exception_time = SDL_GetTicks();
|
||||
}
|
||||
|
||||
exception_per_sec++;
|
||||
|
||||
if (pc == prevpc) {
|
||||
/* BUS ERRORs occur at the same PC - watch out! */
|
||||
exception_per_sec_pc++;
|
||||
}
|
||||
else {
|
||||
exception_per_sec_pc = 0;
|
||||
prevpc = pc;
|
||||
}
|
||||
|
||||
if (SDL_GetTicks() - last_exception_time > 1000) {
|
||||
last_exception_time = SDL_GetTicks();
|
||||
if (exception_per_sec_pc > bx_options.cpu.eps_max ||
|
||||
exception_per_sec > EPS_LIMIT /* make it configurable */) {
|
||||
panicbug("CPU: Exception per second limit reached: %ld/%ld",
|
||||
exception_per_sec_pc, exception_per_sec);
|
||||
/* would be cool to open SDL dialog here: */
|
||||
/* [Exception per seconds limit reached. XXXXX exception
|
||||
occured in the last second. The limit is set to YYYYY
|
||||
in your config file. Do you want to continue emulation,
|
||||
reset ARAnyM or quit ?][Continue] [Reset] [Quit]
|
||||
*/
|
||||
panicbug(CPU_MSG);
|
||||
CPU_ACTION;
|
||||
}
|
||||
exception_per_sec = 0;
|
||||
exception_per_sec_pc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void report_double_bus_error()
|
||||
{
|
||||
panicbug("CPU: Double bus fault detected !");
|
||||
/* would be cool to open SDL dialog here: */
|
||||
/* [Double bus fault detected. The emulated system crashed badly.
|
||||
Do you want to reset ARAnyM or quit ?] [Reset] [Quit]"
|
||||
*/
|
||||
panicbug(CPU_MSG);
|
||||
CPU_ACTION;
|
||||
}
|
||||
|
||||
#ifdef FLIGHT_RECORDER
|
||||
extern bool cpu_flight_recorder_active;
|
||||
void cpu_flight_recorder(int activate) { cpu_flight_recorder_active = activate; }
|
||||
#endif
|
|
@ -264,5 +264,3 @@ void Execute68k(uint32 addr, struct M68kRegisters *r)
|
|||
r->a[i] = m68k_areg(regs, i);
|
||||
quit_program = false;
|
||||
}
|
||||
|
||||
void report_double_bus_error() {}
|
||||
|
|
|
@ -1,43 +1,31 @@
|
|||
/*
|
||||
* build68k.c - m68k CPU builder
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Read 68000 CPU specs from file "table68k" and build table68k.c
|
||||
*
|
||||
* Copyright 1995,1996 Bernd Schmidt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "readcpu.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#undef abort
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "readcpu.h"
|
||||
|
||||
static FILE *tablef;
|
||||
static int nextch = 0;
|
||||
|
@ -77,15 +65,15 @@ static int nextchtohex(void)
|
|||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int no_insns = 0;
|
||||
|
||||
printf ("#include \"sysdeps.h\"\n");
|
||||
printf ("#include \"readcpu.h\"\n");
|
||||
printf ("struct instr_def defs68k[] = {\n");
|
||||
#if 0
|
||||
tablef = fopen("table68k","r");
|
||||
#ifdef WIN32
|
||||
tablef = fopen(argc > 1 ? argv[1] : "table68k","r");
|
||||
if (tablef == NULL) {
|
||||
fprintf(stderr, "table68k not found\n");
|
||||
exit(1);
|
||||
|
@ -134,8 +122,8 @@ int main()
|
|||
case 'r': currbit = bitr; break;
|
||||
case 'R': currbit = bitR; break;
|
||||
case 'z': currbit = bitz; break;
|
||||
case 'E': currbit = bitE; break;
|
||||
case 'p': currbit = bitp; break;
|
||||
case 'E': currbit = bitE; break;
|
||||
case 'p': currbit = bitp; break;
|
||||
default: abort();
|
||||
}
|
||||
if (!(bitmask & 1)) {
|
||||
|
@ -150,7 +138,6 @@ int main()
|
|||
patbits[i] = nextch;
|
||||
getnextch();
|
||||
}
|
||||
(void) patbits;
|
||||
|
||||
while (isspace(nextch) || nextch == ':') /* Get CPU and privilege level */
|
||||
getnextch();
|
||||
|
@ -185,8 +172,6 @@ int main()
|
|||
getnextch();
|
||||
switch(nextch){
|
||||
case '-': flagset[i] = fa_unset; break;
|
||||
case '/': flagset[i] = fa_isjmp; break;
|
||||
case '+': flagset[i] = fa_isbranch; break;
|
||||
case '0': flagset[i] = fa_zero; break;
|
||||
case '1': flagset[i] = fa_one; break;
|
||||
case 'x': flagset[i] = fa_dontcare; break;
|
||||
|
@ -206,8 +191,6 @@ int main()
|
|||
getnextch();
|
||||
switch(nextch){
|
||||
case '-': flaguse[i] = fu_unused; break;
|
||||
case '/': flaguse[i] = fu_isjmp; break;
|
||||
case '+': flaguse[i] = fu_maybecc; break;
|
||||
case '?': flaguse[i] = fu_unknown; break;
|
||||
default: flaguse[i] = fu_used; break;
|
||||
}
|
||||
|
@ -252,7 +235,7 @@ int main()
|
|||
if (nextch != ':')
|
||||
abort();
|
||||
|
||||
assert(fgets(opcstr, 250, tablef) != NULL);
|
||||
fgets(opcstr, 250, tablef);
|
||||
getnextch();
|
||||
{
|
||||
int j;
|
||||
|
@ -260,12 +243,12 @@ int main()
|
|||
char *opstrp = opcstr, *osendp;
|
||||
int slen = 0;
|
||||
|
||||
while (isspace((int)*opstrp))
|
||||
while (isspace(*opstrp))
|
||||
opstrp++;
|
||||
|
||||
osendp = opstrp;
|
||||
while (*osendp) {
|
||||
if (!isspace ((int)*osendp))
|
||||
if (!isspace (*osendp))
|
||||
slen = osendp - opstrp + 1;
|
||||
osendp++;
|
||||
}
|
||||
|
@ -288,5 +271,6 @@ int main()
|
|||
}
|
||||
}
|
||||
printf("};\nint n_defs68k = %d;\n", no_insns);
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3629,7 +3629,7 @@ enum {
|
|||
X86_PROCESSOR_max
|
||||
};
|
||||
|
||||
#if defined(UAE) || (defined(DEBUG) && DEBUG)
|
||||
// #if defined(UAE) || (defined(DEBUG) && DEBUG)
|
||||
static const char * x86_processor_string_table[X86_PROCESSOR_max] = {
|
||||
"80386",
|
||||
"80486",
|
||||
|
@ -3640,7 +3640,7 @@ static const char * x86_processor_string_table[X86_PROCESSOR_max] = {
|
|||
"Pentium4",
|
||||
"x86-64"
|
||||
};
|
||||
#endif
|
||||
// #endif
|
||||
|
||||
static struct ptt {
|
||||
const int align_loop;
|
||||
|
@ -3890,7 +3890,7 @@ raw_init_cpu(void)
|
|||
}
|
||||
|
||||
#ifndef UAE
|
||||
static void __attribute_noinline__ prevent_redzone_use(void) {}
|
||||
static void inline prevent_redzone_use(void) {}
|
||||
|
||||
static bool target_check_bsf(void)
|
||||
{
|
||||
|
|
|
@ -42,7 +42,7 @@ typedef uae_u64 uintptr;
|
|||
typedef uae_u32 uintptr;
|
||||
#endif
|
||||
/* FIXME: cpummu.cpp also checks for USE_JIT, possibly others */
|
||||
// #define USE_JIT
|
||||
#define USE_JIT
|
||||
#endif
|
||||
|
||||
#ifdef USE_JIT
|
||||
|
@ -515,7 +515,7 @@ void jit_abort(const TCHAR *format, ...);
|
|||
#else
|
||||
|
||||
#ifdef WINUAE_ARANYM
|
||||
#define jit_log(format, ...) D(bug(format, ##__VA_ARGS__))
|
||||
#define jit_log(format, ...) write_log(format"\n", ##__VA_ARGS__)
|
||||
#define jit_log2(format, ...) D2(bug(format, ##__VA_ARGS__))
|
||||
void jit_abort(const char *format,...) __attribute__((format(printf, 1, 2))) __attribute__((__noreturn__));
|
||||
#else
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
/* kludge for Brian, so he can compile under MSVC++ */
|
||||
#define USE_NORMAL_CALLING_CONVENTION 0
|
||||
|
||||
#include "sysconfig.h"
|
||||
// #include "sysconfig.h"
|
||||
#include "sysdeps.h"
|
||||
|
||||
#ifdef JIT
|
||||
|
@ -71,6 +71,7 @@
|
|||
#else
|
||||
#include "cpu_emulation.h"
|
||||
#include "main.h"
|
||||
#include "prefs.h"
|
||||
#include "vm_alloc.h"
|
||||
|
||||
#include "m68k.h"
|
||||
|
@ -85,9 +86,14 @@
|
|||
#include "compiler/compemu.h"
|
||||
#include "fpu/fpu.h"
|
||||
#include "fpu/flags.h"
|
||||
#include "parameters.h"
|
||||
// #include "parameters.h"
|
||||
#endif
|
||||
#include "verify.h"
|
||||
// #include "verify.h"
|
||||
|
||||
// #define jit_log(format, ...) \
|
||||
// uae_log("JIT: " format "\n", ##__VA_ARGS__);
|
||||
#define D2 D
|
||||
|
||||
|
||||
#ifdef UAE
|
||||
#include "uae/log.h"
|
||||
|
@ -174,7 +180,7 @@ void jit_abort(const char *format, ...)
|
|||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
ndebug::pdbvprintf(format, args);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
abort();
|
||||
}
|
||||
|
@ -254,6 +260,8 @@ extern int quit_program;
|
|||
// gb-- Extra data for Basilisk II/JIT
|
||||
#ifdef JIT_DEBUG
|
||||
static bool JITDebug = false; // Enable runtime disassemblers through mon?
|
||||
#else
|
||||
const bool JITDebug = false;
|
||||
#endif
|
||||
#if USE_INLINING
|
||||
#ifdef UAE
|
||||
|
@ -504,7 +512,7 @@ static inline blockinfo* get_blockinfo_addr(void* addr)
|
|||
#if defined(CPU_arm)
|
||||
#define TARGET_NATIVE TARGET_ARM
|
||||
#endif
|
||||
#include "disasm-glue.h"
|
||||
// #include "disasm-glue.h"
|
||||
|
||||
#ifdef JIT_DEBUG
|
||||
static void disasm_block(int disasm_target, const uint8 *start, size_t length)
|
||||
|
@ -2642,13 +2650,13 @@ void compiler_init(void)
|
|||
#else
|
||||
#ifdef JIT_DEBUG
|
||||
// JIT debug mode ?
|
||||
JITDebug = bx_options.jit.jitdebug;
|
||||
JITDebug = PrefsFindBool("jitdebug");
|
||||
#endif
|
||||
jit_log("<JIT compiler> : enable runtime disassemblers : %s", JITDebug ? "yes" : "no");
|
||||
|
||||
#ifdef USE_JIT_FPU
|
||||
// Use JIT compiler for FPU instructions ?
|
||||
avoid_fpu = !bx_options.jit.jitfpu;
|
||||
avoid_fpu = !PrefsFindBool("jitfpu");
|
||||
#else
|
||||
// JIT FPU is always disabled
|
||||
avoid_fpu = true;
|
||||
|
@ -2656,7 +2664,7 @@ void compiler_init(void)
|
|||
jit_log("<JIT compiler> : compile FPU instructions : %s", !avoid_fpu ? "yes" : "no");
|
||||
|
||||
// Get size of the translation cache (in KB)
|
||||
cache_size = bx_options.jit.jitcachesize;
|
||||
cache_size = PrefsFindInt32("jitcachesize");
|
||||
jit_log("<JIT compiler> : requested translation cache size : %d KB", cache_size);
|
||||
|
||||
// Initialize target CPU (check for features, e.g. CMOV, rat stalls)
|
||||
|
@ -2671,7 +2679,7 @@ void compiler_init(void)
|
|||
#endif
|
||||
|
||||
// Translation cache flush mechanism
|
||||
lazy_flush = (bx_options.jit.jitlazyflush == 0) ? false : true;
|
||||
lazy_flush = PrefsFindBool("jitlazyflush");
|
||||
jit_log("<JIT compiler> : lazy translation cache invalidation : %s", str_on_off(lazy_flush));
|
||||
flush_icache = lazy_flush ? flush_icache_lazy : flush_icache_hard;
|
||||
|
||||
|
@ -2680,7 +2688,7 @@ void compiler_init(void)
|
|||
jit_log("<JIT compiler> : FP register aliasing : %s", str_on_off(USE_F_ALIAS));
|
||||
jit_log("<JIT compiler> : lazy constant offsetting : %s", str_on_off(USE_OFFSET));
|
||||
#if USE_INLINING
|
||||
follow_const_jumps = bx_options.jit.jitinline;
|
||||
follow_const_jumps = PrefsFindBool("jitinline");
|
||||
#endif
|
||||
jit_log("<JIT compiler> : block inlining : %s", str_on_off(follow_const_jumps));
|
||||
jit_log("<JIT compiler> : separate blockinfo allocation : %s", str_on_off(USE_SEPARATE_BIA));
|
||||
|
@ -2786,12 +2794,12 @@ void compiler_exit(void)
|
|||
bool compiler_use_jit(void)
|
||||
{
|
||||
// Check for the "jit" prefs item
|
||||
if (!bx_options.jit.jit)
|
||||
if (!PrefsFindBool("jit"))
|
||||
return false;
|
||||
|
||||
// Don't use JIT if translation cache size is less then MIN_CACHE_SIZE KB
|
||||
if (bx_options.jit.jitcachesize < MIN_CACHE_SIZE) {
|
||||
panicbug("<JIT compiler> : translation cache size is less than %d KB. Disabling JIT.\n", MIN_CACHE_SIZE);
|
||||
if (PrefsFindInt32("jitcachesize") < MIN_CACHE_SIZE) {
|
||||
write_log("<JIT compiler> : translation cache size is less than %d KB. Disabling JIT.\n", MIN_CACHE_SIZE);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3579,6 +3587,8 @@ void alloc_cache(void)
|
|||
}
|
||||
}
|
||||
|
||||
extern void op_illg_1 (uae_u32 opcode) REGPARAM;
|
||||
|
||||
static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2)
|
||||
{
|
||||
uae_u32 k1 = 0;
|
||||
|
@ -3869,7 +3879,7 @@ static inline void create_popalls(void)
|
|||
r=REG_PC_TMP;
|
||||
compemu_raw_mov_l_rm(r, uae_p32(®s.pc_p));
|
||||
compemu_raw_and_l_ri(r,TAGMASK);
|
||||
verify(sizeof(cache_tags[0]) == sizeof(void *));
|
||||
assert(sizeof(cache_tags[0]) == sizeof(void *));
|
||||
compemu_raw_jmp_m_indexed(uae_p32(cache_tags), r, sizeof(void *));
|
||||
|
||||
/* now the exit points */
|
||||
|
@ -4009,7 +4019,7 @@ static bool merge_blacklist()
|
|||
#ifdef UAE
|
||||
const char *blacklist = "";
|
||||
#else
|
||||
const char *blacklist = bx_options.jit.jitblacklist;
|
||||
const char *blacklist = PrefsFindString("jitblacklist");
|
||||
#endif
|
||||
if (blacklist[0] != '\0') {
|
||||
const char *p = blacklist;
|
||||
|
@ -4346,38 +4356,86 @@ void flush_icache(int n)
|
|||
#ifdef UAE
|
||||
static
|
||||
#endif
|
||||
void flush_icache_range(uae_u32 start, uae_u32 length)
|
||||
// void flush_icache_range(uae_u32 start, uae_u32 length)
|
||||
// {
|
||||
// if (!active)
|
||||
// return;
|
||||
|
||||
// #if LAZY_FLUSH_ICACHE_RANGE
|
||||
// uae_u8 *start_p = get_real_address(start);
|
||||
// blockinfo *bi = active;
|
||||
// while (bi) {
|
||||
// #if USE_CHECKSUM_INFO
|
||||
// bool invalidate = false;
|
||||
// for (checksum_info *csi = bi->csi; csi && !invalidate; csi = csi->next)
|
||||
// invalidate = (((start_p - csi->start_p) < csi->length) ||
|
||||
// ((csi->start_p - start_p) < length));
|
||||
// #else
|
||||
// // Assume system is consistent and would invalidate the right range
|
||||
// const bool invalidate = (bi->pc_p - start_p) < length;
|
||||
// #endif
|
||||
// if (invalidate) {
|
||||
// uae_u32 cl = cacheline(bi->pc_p);
|
||||
// if (bi == cache_tags[cl + 1].bi)
|
||||
// cache_tags[cl].handler = (cpuop_func *)popall_execute_normal;
|
||||
// bi->handler_to_use = (cpuop_func *)popall_execute_normal;
|
||||
// set_dhtu(bi, bi->direct_pen);
|
||||
// bi->status = BI_NEED_RECOMP;
|
||||
// }
|
||||
// bi = bi->next;
|
||||
// }
|
||||
// return;
|
||||
// #else
|
||||
// UNUSED(start);
|
||||
// UNUSED(length);
|
||||
// #endif
|
||||
// flush_icache(-1);
|
||||
// }
|
||||
|
||||
void flush_icache_range(uae_u8 *start_p, uae_u32 length)
|
||||
{
|
||||
if (!active)
|
||||
return;
|
||||
|
||||
#if LAZY_FLUSH_ICACHE_RANGE
|
||||
uae_u8 *start_p = get_real_address(start);
|
||||
blockinfo *bi = active;
|
||||
while (bi) {
|
||||
#if USE_CHECKSUM_INFO
|
||||
bool invalidate = false;
|
||||
for (checksum_info *csi = bi->csi; csi && !invalidate; csi = csi->next)
|
||||
invalidate = (((start_p - csi->start_p) < csi->length) ||
|
||||
((csi->start_p - start_p) < length));
|
||||
bool candidate = false;
|
||||
for (checksum_info *csi = bi->csi; csi; csi = csi->next) {
|
||||
if (((start_p - csi->start_p) < csi->length) ||
|
||||
((csi->start_p - start_p) < length)) {
|
||||
candidate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Assume system is consistent and would invalidate the right range
|
||||
const bool invalidate = (bi->pc_p - start_p) < length;
|
||||
const bool candidate = (bi->pc_p - start_p) < length;
|
||||
#endif
|
||||
if (invalidate) {
|
||||
uae_u32 cl = cacheline(bi->pc_p);
|
||||
if (bi == cache_tags[cl + 1].bi)
|
||||
cache_tags[cl].handler = (cpuop_func *)popall_execute_normal;
|
||||
bi->handler_to_use = (cpuop_func *)popall_execute_normal;
|
||||
set_dhtu(bi, bi->direct_pen);
|
||||
bi->status = BI_NEED_RECOMP;
|
||||
}
|
||||
blockinfo *dbi = bi;
|
||||
bi = bi->next;
|
||||
if (candidate) {
|
||||
uae_u32 cl = cacheline(dbi->pc_p);
|
||||
if (dbi->status == BI_INVALID || dbi->status == BI_NEED_RECOMP) {
|
||||
if (dbi == cache_tags[cl+1].bi)
|
||||
cache_tags[cl].handler = (cpuop_func *)popall_execute_normal;
|
||||
dbi->handler_to_use = (cpuop_func *)popall_execute_normal;
|
||||
set_dhtu(dbi, dbi->direct_pen);
|
||||
dbi->status = BI_INVALID;
|
||||
}
|
||||
else {
|
||||
if (dbi == cache_tags[cl+1].bi)
|
||||
cache_tags[cl].handler = (cpuop_func *)popall_check_checksum;
|
||||
dbi->handler_to_use = (cpuop_func *)popall_check_checksum;
|
||||
set_dhtu(dbi, dbi->direct_pcc);
|
||||
dbi->status = BI_NEED_CHECK;
|
||||
}
|
||||
remove_from_list(dbi);
|
||||
add_to_dormant(dbi);
|
||||
}
|
||||
}
|
||||
return;
|
||||
#else
|
||||
UNUSED(start);
|
||||
UNUSED(length);
|
||||
#endif
|
||||
flush_icache(-1);
|
||||
}
|
||||
|
@ -4631,7 +4689,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen)
|
|||
comptbl=compfunctbl;
|
||||
}
|
||||
|
||||
#ifdef FLIGHT_RECORDER
|
||||
#if FLIGHT_RECORDER
|
||||
{
|
||||
/* store also opcode to second register */
|
||||
clobber_flags();
|
||||
|
@ -5008,7 +5066,7 @@ void exec_nostats(void)
|
|||
{
|
||||
for (;;) {
|
||||
uae_u32 opcode = GET_OPCODE;
|
||||
#ifdef FLIGHT_RECORDER
|
||||
#if FLIGHT_RECORDER
|
||||
m68k_record_step(m68k_getpc(), opcode);
|
||||
#endif
|
||||
(*cpufunctbl[opcode])(opcode);
|
||||
|
@ -5038,7 +5096,7 @@ void execute_normal(void)
|
|||
for (;;) { /* Take note: This is the do-it-normal loop */
|
||||
pc_hist[blocklen++].location = (uae_u16 *)regs.pc_p;
|
||||
uae_u32 opcode = GET_OPCODE;
|
||||
#ifdef FLIGHT_RECORDER
|
||||
#if FLIGHT_RECORDER
|
||||
m68k_record_step(m68k_getpc(), opcode);
|
||||
#endif
|
||||
(*cpufunctbl[opcode])(opcode);
|
||||
|
@ -5082,7 +5140,7 @@ setjmpagain:
|
|||
for (;;) {
|
||||
if (quit_program > 0) {
|
||||
if (quit_program == 1) {
|
||||
#ifdef FLIGHT_RECORDER
|
||||
#if FLIGHT_RECORDER
|
||||
dump_flight_recorder();
|
||||
#endif
|
||||
break;
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
*/
|
||||
|
||||
#define CC_FOR_BUILD 1
|
||||
#include "sysconfig.h"
|
||||
// #include "sysconfig.h"
|
||||
#define WINUAE_ARANYM
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "readcpu.h"
|
||||
|
@ -3101,10 +3102,10 @@ gen_opcode (unsigned int opcode)
|
|||
failure;
|
||||
break;
|
||||
|
||||
case i_NATFEAT_ID:
|
||||
case i_NATFEAT_CALL:
|
||||
failure;
|
||||
break;
|
||||
// case i_NATFEAT_ID:
|
||||
// case i_NATFEAT_CALL:
|
||||
// failure;
|
||||
// break;
|
||||
|
||||
case i_MMUOP:
|
||||
isjump;
|
||||
|
@ -3127,7 +3128,7 @@ gen_opcode (unsigned int opcode)
|
|||
static void
|
||||
generate_includes (FILE * f)
|
||||
{
|
||||
fprintf (f, "#include \"sysconfig.h\"\n");
|
||||
// fprintf (f, "#include \"sysconfig.h\"\n");
|
||||
fprintf (f, "#if defined(JIT)\n");
|
||||
fprintf (f, "#include \"sysdeps.h\"\n");
|
||||
#ifdef UAE
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
*/
|
||||
|
||||
#define CC_FOR_BUILD 1
|
||||
#include "sysconfig.h"
|
||||
// #include "sysconfig.h"
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "readcpu.h"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.8 version)
|
||||
* cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.10 version)
|
||||
*
|
||||
* Basilisk II (C) 1997-1999 Christian Bauer
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -21,6 +21,8 @@
|
|||
#ifndef CPU_EMULATION_H
|
||||
#define CPU_EMULATION_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*
|
||||
* Memory system
|
||||
|
@ -35,15 +37,15 @@ extern uint32 ROMBaseMac; // ROM base (Mac address space)
|
|||
extern uint8 *ROMBaseHost; // ROM base (host address space)
|
||||
extern uint32 ROMSize; // Size of ROM
|
||||
|
||||
#if !REAL_ADDRESSING
|
||||
// If we are not using real addressing, the Mac frame buffer gets mapped to this location
|
||||
// The memory must be allocated by VideoInit(). If multiple monitors are used, they must
|
||||
// share the frame buffer
|
||||
#if !REAL_ADDRESSING && !DIRECT_ADDRESSING
|
||||
// If we are not using real or direct addressing, the Mac frame buffer gets
|
||||
// mapped to this location. The memory must be allocated by VideoInit().
|
||||
// If multiple monitors are used, they must share the frame buffer
|
||||
const uint32 MacFrameBaseMac = 0xa0000000;
|
||||
extern uint8 *MacFrameBaseHost; // Frame buffer base (host address space)
|
||||
extern uint32 MacFrameSize; // Size of frame buffer
|
||||
extern int MacFrameLayout; // Frame buffer layout (see defines below)
|
||||
#endif
|
||||
extern int MacFrameLayout; // Frame buffer layout (see defines below)
|
||||
|
||||
// Possible frame buffer layouts
|
||||
enum {
|
||||
|
@ -78,15 +80,17 @@ static inline void *Mac2Mac_memcpy(uint32 dest, uint32 src, size_t n) {return me
|
|||
// Initialization
|
||||
extern bool Init680x0(void); // This routine may want to look at CPUType/FPUType to set up the apropriate emulation
|
||||
extern void Exit680x0(void);
|
||||
extern void InitFrameBufferMapping(void);
|
||||
|
||||
// 680x0 dynamic recompilation activation flag
|
||||
#if USE_JIT
|
||||
extern bool UseJIT;
|
||||
#else
|
||||
const bool UseJIT = false;
|
||||
#endif
|
||||
|
||||
// 680x0 emulation functions
|
||||
struct M68kRegisters {
|
||||
uint32 d[8];
|
||||
memptr a[8];
|
||||
uint16 sr;
|
||||
memptr usp, isp, msp;
|
||||
memptr pc;
|
||||
};
|
||||
struct M68kRegisters;
|
||||
extern void Start680x0(void); // Reset and start 680x0
|
||||
extern "C" void Execute68k(uint32 addr, M68kRegisters *r); // Execute 68k code from EMUL_OP routine
|
||||
extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS 68k trap from EMUL_OP routine
|
||||
|
@ -95,12 +99,4 @@ extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS
|
|||
extern void TriggerInterrupt(void); // Trigger interrupt level 1 (InterruptFlag must be set first)
|
||||
extern void TriggerNMI(void); // Trigger interrupt level 7
|
||||
|
||||
// CPU looping handlers
|
||||
void check_eps_limit(uaecptr);
|
||||
void report_double_bus_error(void);
|
||||
|
||||
extern int intlev(void);
|
||||
|
||||
static inline void AtariReset(void) {}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
/*
|
||||
* cpudefs.cpp must be compiled twice, once for the generator program
|
||||
* and once for the actual executable
|
||||
*/
|
||||
#include "cpudefs.cpp"
|
|
@ -1,2 +0,0 @@
|
|||
#define PART_1
|
||||
#include "cpuemu.cpp"
|
|
@ -1,3 +0,0 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_1
|
||||
#include "cpuemu.cpp"
|
|
@ -1,2 +0,0 @@
|
|||
#define PART_2
|
||||
#include "cpuemu.cpp"
|
|
@ -1,3 +0,0 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_2
|
||||
#include "cpuemu.cpp"
|
|
@ -1,2 +0,0 @@
|
|||
#define PART_3
|
||||
#include "cpuemu.cpp"
|
|
@ -1,3 +0,0 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_3
|
||||
#include "cpuemu.cpp"
|
|
@ -1,2 +0,0 @@
|
|||
#define PART_4
|
||||
#include "cpuemu.cpp"
|
|
@ -1,3 +0,0 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_4
|
||||
#include "cpuemu.cpp"
|
|
@ -1,2 +0,0 @@
|
|||
#define PART_5
|
||||
#include "cpuemu.cpp"
|
|
@ -1,4 +0,0 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_5
|
||||
#include "cpuemu.cpp"
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#define PART_6
|
||||
#include "cpuemu.cpp"
|
|
@ -1,3 +0,0 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_6
|
||||
#include "cpuemu.cpp"
|
|
@ -1,2 +0,0 @@
|
|||
#define PART_7
|
||||
#include "cpuemu.cpp"
|
|
@ -1,3 +0,0 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_7
|
||||
#include "cpuemu.cpp"
|
|
@ -1,2 +0,0 @@
|
|||
#define PART_8
|
||||
#include "cpuemu.cpp"
|
|
@ -1,3 +0,0 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_8
|
||||
#include "cpuemu.cpp"
|
|
@ -1,5 +0,0 @@
|
|||
/*
|
||||
* cpufunctbl.cpp must be compiled twice, once for the generator program
|
||||
* and once for the actual executable
|
||||
*/
|
||||
#include "cpufunctbl.cpp"
|
File diff suppressed because it is too large
Load Diff
|
@ -1,267 +0,0 @@
|
|||
/*
|
||||
* cpummu.h - MMU emulation
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by UAE MMU patch
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef CPUMMU_H
|
||||
#define CPUMMU_H
|
||||
|
||||
#include "registers.h"
|
||||
|
||||
# include <cstdlib>
|
||||
|
||||
#define MMU_TEST_PTEST 1
|
||||
#define MMU_TEST_VERBOSE 2
|
||||
#define MMU_TEST_FORCE_TABLE_SEARCH 4
|
||||
#define MMU_TEST_NO_BUSERR 8
|
||||
|
||||
extern void mmu_dump_tables(void);
|
||||
|
||||
#define MMU_TTR_LOGICAL_BASE 0xff000000
|
||||
#define MMU_TTR_LOGICAL_MASK 0x00ff0000
|
||||
#define MMU_TTR_BIT_ENABLED (1 << 15)
|
||||
#define MMU_TTR_BIT_SFIELD_ENABLED (1 << 14)
|
||||
#define MMU_TTR_BIT_SFIELD_SUPER (1 << 13)
|
||||
#define MMU_TTR_SFIELD_SHIFT 13
|
||||
#define MMU_TTR_UX_MASK ((1 << 9) | (1 << 8))
|
||||
#define MMU_TTR_UX_SHIFT 8
|
||||
#define MMU_TTR_CACHE_MASK ((1 << 6) | (1 << 5))
|
||||
#define MMU_TTR_CACHE_SHIFT 5
|
||||
#define MMU_TTR_BIT_WRITE_PROTECT (1 << 2)
|
||||
|
||||
#define MMU_UDT_MASK 3
|
||||
#define MMU_PDT_MASK 3
|
||||
|
||||
#define MMU_DES_WP 4
|
||||
#define MMU_DES_USED 8
|
||||
|
||||
/* page descriptors only */
|
||||
#define MMU_DES_MODIFIED 16
|
||||
#define MMU_DES_SUPER (1 << 7)
|
||||
#define MMU_DES_GLOBAL (1 << 10)
|
||||
|
||||
#define MMU_ROOT_PTR_ADDR_MASK 0xfffffe00
|
||||
#define MMU_PTR_PAGE_ADDR_MASK_8 0xffffff80
|
||||
#define MMU_PTR_PAGE_ADDR_MASK_4 0xffffff00
|
||||
|
||||
#define MMU_PAGE_INDIRECT_MASK 0xfffffffc
|
||||
#define MMU_PAGE_ADDR_MASK_8 0xffffe000
|
||||
#define MMU_PAGE_ADDR_MASK_4 0xfffff000
|
||||
#define MMU_PAGE_UR_MASK_8 ((1 << 12) | (1 << 11))
|
||||
#define MMU_PAGE_UR_MASK_4 (1 << 11)
|
||||
#define MMU_PAGE_UR_SHIFT 11
|
||||
|
||||
#define MMU_MMUSR_ADDR_MASK 0xfffff000
|
||||
#define MMU_MMUSR_B (1 << 11)
|
||||
#define MMU_MMUSR_G (1 << 10)
|
||||
#define MMU_MMUSR_U1 (1 << 9)
|
||||
#define MMU_MMUSR_U0 (1 << 8)
|
||||
#define MMU_MMUSR_Ux (MMU_MMUSR_U1 | MMU_MMUSR_U0)
|
||||
#define MMU_MMUSR_S (1 << 7)
|
||||
#define MMU_MMUSR_CM ((1 << 6) | ( 1 << 5))
|
||||
#define MMU_MMUSR_M (1 << 4)
|
||||
#define MMU_MMUSR_W (1 << 2)
|
||||
#define MMU_MMUSR_T (1 << 1)
|
||||
#define MMU_MMUSR_R (1 << 0)
|
||||
|
||||
/* special status word (access error stack frame) */
|
||||
#define MMU_SSW_TM 0x0007
|
||||
#define MMU_SSW_TT 0x0018
|
||||
#define MMU_SSW_SIZE 0x0060
|
||||
#define MMU_SSW_SIZE_B 0x0020
|
||||
#define MMU_SSW_SIZE_W 0x0040
|
||||
#define MMU_SSW_SIZE_L 0x0000
|
||||
#define MMU_SSW_RW 0x0100
|
||||
#define MMU_SSW_LK 0x0200
|
||||
#define MMU_SSW_ATC 0x0400
|
||||
#define MMU_SSW_MA 0x0800
|
||||
|
||||
#define TTR_I0 4
|
||||
#define TTR_I1 5
|
||||
#define TTR_D0 6
|
||||
#define TTR_D1 7
|
||||
|
||||
#define TTR_NO_MATCH 0
|
||||
#define TTR_NO_WRITE 1
|
||||
#define TTR_OK_MATCH 2
|
||||
|
||||
struct mmu_atc_line {
|
||||
uae_u16 tag;
|
||||
unsigned tt : 1;
|
||||
unsigned valid_data : 1;
|
||||
unsigned valid_inst : 1;
|
||||
unsigned global : 1;
|
||||
unsigned modified : 1;
|
||||
unsigned write_protect : 1;
|
||||
unsigned hw : 1;
|
||||
unsigned bus_fault : 1;
|
||||
uaecptr phys;
|
||||
};
|
||||
|
||||
/*
|
||||
* We don't need to store the whole logical address in the atc cache, as part of
|
||||
* it is encoded as index into the cache. 14 bits of the address are stored in
|
||||
* the tag, this means at least 6 bits must go into the index. The upper two
|
||||
* bits of the tag define the type of data in the atc line:
|
||||
* - 00: a normal memory address
|
||||
* - 11: invalid memory address or hardware access
|
||||
* (generated via ~ATC_TAG(addr) in the slow path)
|
||||
* - 10: empty atc line
|
||||
*/
|
||||
|
||||
#define ATC_TAG_SHIFT 18
|
||||
#define ATC_TAG(addr) ((uae_u32)(addr) >> ATC_TAG_SHIFT)
|
||||
|
||||
|
||||
#define ATC_L1_SIZE_LOG 8
|
||||
#define ATC_L1_SIZE (1 << ATC_L1_SIZE_LOG)
|
||||
|
||||
#define ATC_L1_INDEX(addr) (((addr) >> 12) % ATC_L1_SIZE)
|
||||
|
||||
/*
|
||||
* first level atc cache
|
||||
* indexed by [super][data][rw][idx]
|
||||
*/
|
||||
|
||||
typedef struct mmu_atc_line mmu_atc_l1_array[2][2][ATC_L1_SIZE];
|
||||
extern mmu_atc_l1_array atc_l1[2];
|
||||
extern mmu_atc_l1_array *current_atc;
|
||||
|
||||
#define ATC_L2_SIZE_LOG 12
|
||||
#define ATC_L2_SIZE (1 << ATC_L2_SIZE_LOG)
|
||||
|
||||
#define ATC_L2_INDEX(addr) ((((addr) >> 12) ^ ((addr) >> (32 - ATC_L2_SIZE_LOG))) % ATC_L2_SIZE)
|
||||
|
||||
extern struct mmu_atc_line atc_l2[2][ATC_L2_SIZE];
|
||||
|
||||
/*
|
||||
* lookup address in the level 1 atc cache,
|
||||
* the data and write arguments are constant in the common,
|
||||
* thus allows gcc to generate a constant offset.
|
||||
*/
|
||||
static ALWAYS_INLINE int mmu_lookup(uaecptr addr, bool data, bool write,
|
||||
struct mmu_atc_line **cl)
|
||||
{
|
||||
addr >>= 12;
|
||||
*cl = &(*current_atc)[data][write][addr % ATC_L1_SIZE];
|
||||
return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12);
|
||||
}
|
||||
|
||||
/*
|
||||
* similiar to mmu_user_lookup, but for the use of the moves instruction
|
||||
*/
|
||||
static ALWAYS_INLINE int mmu_user_lookup(uaecptr addr, bool super, bool data,
|
||||
bool write, struct mmu_atc_line **cl)
|
||||
{
|
||||
addr >>= 12;
|
||||
*cl = &atc_l1[super][data][write][addr % ATC_L1_SIZE];
|
||||
return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12);
|
||||
}
|
||||
|
||||
extern REGPARAM2 uae_u16 mmu_get_word_unaligned(uaecptr addr, int data);
|
||||
extern REGPARAM2 uae_u32 mmu_get_long_unaligned(uaecptr addr, int data);
|
||||
|
||||
extern REGPARAM2 uae_u8 mmu_get_byte_slow(uaecptr addr, int super, int data,
|
||||
int size, struct mmu_atc_line *cl);
|
||||
extern REGPARAM2 uae_u16 mmu_get_word_slow(uaecptr addr, int super, int data,
|
||||
int size, struct mmu_atc_line *cl);
|
||||
extern REGPARAM2 uae_u32 mmu_get_long_slow(uaecptr addr, int super, int data,
|
||||
int size, struct mmu_atc_line *cl);
|
||||
extern REGPARAM2 uae_u64 mmu_get_quad_slow(uaecptr addr, int super, int data,
|
||||
struct mmu_atc_line *cl);
|
||||
|
||||
extern REGPARAM2 void mmu_put_word_unaligned(uaecptr addr, uae_u16 val, int data);
|
||||
extern REGPARAM2 void mmu_put_long_unaligned(uaecptr addr, uae_u32 val, int data);
|
||||
|
||||
extern REGPARAM2 void mmu_put_byte_slow(uaecptr addr, uae_u8 val, int super, int data,
|
||||
int size, struct mmu_atc_line *cl);
|
||||
extern REGPARAM2 void mmu_put_word_slow(uaecptr addr, uae_u16 val, int super, int data,
|
||||
int size, struct mmu_atc_line *cl);
|
||||
extern REGPARAM2 void mmu_put_long_slow(uaecptr addr, uae_u32 val, int super, int data,
|
||||
int size, struct mmu_atc_line *cl);
|
||||
extern REGPARAM2 void mmu_put_quad_slow(uaecptr addr, uae_u64 val, int super, int data,
|
||||
struct mmu_atc_line *cl);
|
||||
|
||||
extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode);
|
||||
|
||||
static inline void mmu_set_ttr(int regno, uae_u32 val)
|
||||
{
|
||||
uae_u32 * ttr;
|
||||
switch(regno) {
|
||||
case TTR_I0: ttr = ®s.itt0; break;
|
||||
case TTR_I1: ttr = ®s.itt1; break;
|
||||
case TTR_D0: ttr = ®s.dtt0; break;
|
||||
case TTR_D1: ttr = ®s.dtt1; break;
|
||||
default: abort();
|
||||
}
|
||||
*ttr = val;
|
||||
}
|
||||
|
||||
static inline void mmu_set_mmusr(uae_u32 val)
|
||||
{
|
||||
regs.mmusr = val;
|
||||
}
|
||||
|
||||
#define FC_DATA (regs.s ? 5 : 1)
|
||||
#define FC_INST (regs.s ? 6 : 2)
|
||||
|
||||
extern uaecptr REGPARAM2 mmu_translate(uaecptr addr, int super, int data, int write);
|
||||
|
||||
extern uae_u32 REGPARAM2 sfc_get_long(uaecptr addr);
|
||||
extern uae_u16 REGPARAM2 sfc_get_word(uaecptr addr);
|
||||
extern uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr);
|
||||
extern void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val);
|
||||
extern void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val);
|
||||
extern void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val);
|
||||
|
||||
|
||||
extern void REGPARAM2 mmu_flush_atc(uaecptr addr, bool super, bool global);
|
||||
extern void REGPARAM2 mmu_flush_atc_all(bool global);
|
||||
extern void REGPARAM2 mmu_op(uae_u32 opcode, uae_u16 extra);
|
||||
|
||||
#ifdef FULLMMU
|
||||
|
||||
extern void REGPARAM2 mmu_reset(void);
|
||||
extern void REGPARAM2 mmu_set_tc(uae_u16 tc);
|
||||
extern void REGPARAM2 mmu_set_super(bool super);
|
||||
|
||||
#else
|
||||
|
||||
static inline void mmu_reset(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void mmu_set_tc(uae_u16 /*tc*/)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void mmu_set_super(bool /*super*/)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CPUMMU_H */
|
||||
/*
|
||||
vim:ts=4:sw=4:
|
||||
*/
|
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* cpuopti.c - Small optimizer for cpu*.s files
|
||||
* Based on work by Tauno Taipaleenmaki
|
||||
*
|
||||
* Copyright 1996 Bernd Schmidt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
struct line {
|
||||
struct line *next, *prev;
|
||||
int delet;
|
||||
char *data;
|
||||
};
|
||||
|
||||
struct func {
|
||||
struct line *first_line, *last_line;
|
||||
int initial_offset;
|
||||
};
|
||||
|
||||
static void oops(void)
|
||||
{
|
||||
fprintf(stderr, "Don't know how to optimize this file.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static char * match(struct line *l, const char *m)
|
||||
{
|
||||
char *str = l->data;
|
||||
int len = strlen(m);
|
||||
while (isspace(*str))
|
||||
str++;
|
||||
|
||||
if (strncmp(str, m, len) != 0)
|
||||
return NULL;
|
||||
return str + len;
|
||||
}
|
||||
|
||||
static int insn_references_reg (struct line *l, char *reg)
|
||||
{
|
||||
if (reg[0] != 'e') {
|
||||
fprintf(stderr, "Unknown register?!?\n");
|
||||
exit(1);
|
||||
}
|
||||
if (strstr (l->data, reg) != 0)
|
||||
return 1;
|
||||
if (strstr (l->data, reg+1) != 0)
|
||||
return 1;
|
||||
if (strcmp (reg, "eax") == 0
|
||||
&& (strstr (l->data, "%al") != 0 || strstr (l->data, "%ah") != 0))
|
||||
return 1;
|
||||
if (strcmp (reg, "ebx") == 0
|
||||
&& (strstr (l->data, "%bl") != 0 || strstr (l->data, "%bh") != 0))
|
||||
return 1;
|
||||
if (strcmp (reg, "ecx") == 0
|
||||
&& (strstr (l->data, "%cl") != 0 || strstr (l->data, "%ch") != 0))
|
||||
return 1;
|
||||
if (strcmp (reg, "edx") == 0
|
||||
&& (strstr (l->data, "%dl") != 0 || strstr (l->data, "%dh") != 0))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void do_function(struct func *f)
|
||||
{
|
||||
int v;
|
||||
int pops_at_end = 0;
|
||||
struct line *l, *l1, *fl, *l2;
|
||||
char *s, *s2;
|
||||
int in_pop_area = 1;
|
||||
|
||||
f->initial_offset = 0;
|
||||
|
||||
l = f->last_line;
|
||||
fl = f->first_line;
|
||||
|
||||
if (match(l,".LFE"))
|
||||
l = l->prev;
|
||||
if (!match(l,"ret"))
|
||||
oops();
|
||||
|
||||
while (!match(fl, "op_"))
|
||||
fl = fl->next;
|
||||
fl = fl->next;
|
||||
|
||||
/* Try reordering the insns at the end of the function so that the
|
||||
* pops are all at the end. */
|
||||
l2 = l->prev;
|
||||
/* Tolerate one stack adjustment */
|
||||
if (match (l2, "addl $") && strstr(l2->data, "esp") != 0)
|
||||
l2 = l2->prev;
|
||||
for (;;) {
|
||||
char *forbidden_reg;
|
||||
struct line *l3, *l4;
|
||||
|
||||
while (match (l2, "popl %"))
|
||||
l2 = l2->prev;
|
||||
|
||||
l3 = l2;
|
||||
for (;;) {
|
||||
forbidden_reg = match (l3, "popl %");
|
||||
if (forbidden_reg)
|
||||
break;
|
||||
if (l3 == fl)
|
||||
goto reordered;
|
||||
/* Jumps and labels put an end to our attempts... */
|
||||
if (strstr (l3->data, ".L") != 0)
|
||||
goto reordered;
|
||||
/* Likewise accesses to the stack pointer... */
|
||||
if (strstr (l3->data, "esp") != 0)
|
||||
goto reordered;
|
||||
/* Function calls... */
|
||||
if (strstr (l3->data, "call") != 0)
|
||||
goto reordered;
|
||||
l3 = l3->prev;
|
||||
}
|
||||
if (l3 == l2)
|
||||
exit(1);
|
||||
for (l4 = l2; l4 != l3; l4 = l4->prev) {
|
||||
/* The register may not be referenced by any of the insns that we
|
||||
* move the popl past */
|
||||
if (insn_references_reg (l4, forbidden_reg))
|
||||
goto reordered;
|
||||
}
|
||||
l3->prev->next = l3->next;
|
||||
l3->next->prev = l3->prev;
|
||||
l2->next->prev = l3;
|
||||
l3->next = l2->next;
|
||||
l2->next = l3;
|
||||
l3->prev = l2;
|
||||
}
|
||||
reordered:
|
||||
|
||||
l = l->prev;
|
||||
|
||||
s = match (l, "addl $");
|
||||
s2 = match (fl, "subl $");
|
||||
|
||||
l1 = l;
|
||||
if (s == 0) {
|
||||
char *t = match (l, "popl %");
|
||||
if (t != 0 && (strcmp (t, "ecx") == 0 || strcmp (t, "edx") == 0)) {
|
||||
s = "4,%esp";
|
||||
l = l->prev;
|
||||
t = match (l, "popl %");
|
||||
if (t != 0 && (strcmp (t, "ecx") == 0 || strcmp (t, "edx") == 0)) {
|
||||
s = "8,%esp";
|
||||
l = l->prev;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
l = l->prev;
|
||||
}
|
||||
|
||||
if (s && s2) {
|
||||
int v = 0;
|
||||
if (strcmp (s, s2) != 0) {
|
||||
fprintf (stderr, "Stack adjustment not matching.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (isdigit(*s)) {
|
||||
v = v * 10 + (*s) - '0';
|
||||
s++;
|
||||
}
|
||||
|
||||
if (strcmp (s, ",%esp") != 0) {
|
||||
fprintf (stderr, "Not adjusting the stack pointer.\n");
|
||||
return;
|
||||
}
|
||||
f->initial_offset = v;
|
||||
fl->delet = 3;
|
||||
fl = fl->next;
|
||||
l1->delet = 2;
|
||||
l1 = l1->prev;
|
||||
while (l1 != l) {
|
||||
l1->delet = 1;
|
||||
l1 = l1->prev;
|
||||
}
|
||||
}
|
||||
|
||||
while (in_pop_area) {
|
||||
char *popm, *pushm;
|
||||
popm = match (l, "popl %");
|
||||
pushm = match (fl, "pushl %");
|
||||
if (popm && pushm && strcmp(pushm, popm) == 0) {
|
||||
pops_at_end++;
|
||||
fl->delet = l->delet = 1;
|
||||
} else
|
||||
in_pop_area = 0;
|
||||
l = l->prev;
|
||||
fl = fl->next;
|
||||
}
|
||||
if (f->initial_offset)
|
||||
f->initial_offset += 4 * pops_at_end;
|
||||
}
|
||||
|
||||
static void output_function(struct func *f)
|
||||
{
|
||||
struct line *l = f->first_line;
|
||||
|
||||
while (l) {
|
||||
switch (l->delet) {
|
||||
case 1:
|
||||
break;
|
||||
case 0:
|
||||
printf("%s\n", l->data);
|
||||
break;
|
||||
case 2:
|
||||
if (f->initial_offset)
|
||||
printf("\taddl $%d,%%esp\n", f->initial_offset);
|
||||
break;
|
||||
case 3:
|
||||
if (f->initial_offset)
|
||||
printf("\tsubl $%d,%%esp\n", f->initial_offset);
|
||||
break;
|
||||
}
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *infile = stdin;
|
||||
char tmp[4096];
|
||||
|
||||
#ifdef __mc68000__
|
||||
if(system("perl machdep/cpuopti")==-1) {
|
||||
perror("perl machdep/cpuopti");
|
||||
return 10;
|
||||
} else return 0;
|
||||
#endif
|
||||
|
||||
/* For debugging... */
|
||||
if (argc == 2)
|
||||
infile = fopen (argv[1], "r");
|
||||
|
||||
for(;;) {
|
||||
char *s;
|
||||
|
||||
if ((fgets(tmp, 4095, infile)) == NULL)
|
||||
break;
|
||||
|
||||
s = strchr (tmp, '\n');
|
||||
if (s != NULL)
|
||||
*s = 0;
|
||||
|
||||
if (strncmp(tmp, ".globl op_", 10) == 0) {
|
||||
struct line *first_line = NULL, *prev = NULL;
|
||||
struct line **nextp = &first_line;
|
||||
struct func f;
|
||||
int nr_rets = 0;
|
||||
int can_opt = 1;
|
||||
|
||||
do {
|
||||
struct line *current;
|
||||
|
||||
if (strcmp (tmp, "#APP") != 0 && strcmp (tmp, "#NO_APP") != 0) {
|
||||
current = *nextp = (struct line *)malloc(sizeof (struct line));
|
||||
nextp = ¤t->next;
|
||||
current->prev = prev; prev = current;
|
||||
current->next = NULL;
|
||||
current->delet = 0;
|
||||
current->data = strdup (tmp);
|
||||
if (match (current, "movl %esp,%ebp") || match (current, "enter")) {
|
||||
fprintf (stderr, "GCC failed to eliminate fp: %s\n", first_line->data);
|
||||
can_opt = 0;
|
||||
}
|
||||
|
||||
if (match (current, "ret"))
|
||||
nr_rets++;
|
||||
}
|
||||
if ((fgets(tmp, 4095, infile)) == NULL)
|
||||
oops();
|
||||
s = strchr (tmp, '\n');
|
||||
if (s != NULL)
|
||||
*s = 0;
|
||||
} while (strncmp (tmp,".Lfe", 4) != 0);
|
||||
|
||||
f.first_line = first_line;
|
||||
f.last_line = prev;
|
||||
|
||||
if (nr_rets == 1 && can_opt)
|
||||
do_function(&f);
|
||||
/*else
|
||||
fprintf(stderr, "Too many RET instructions: %s\n", first_line->data);*/
|
||||
output_function(&f);
|
||||
}
|
||||
printf("%s\n", tmp);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
#define NOFLAGS 1
|
||||
#include "cpustbl.cpp"
|
|
@ -1,5 +0,0 @@
|
|||
/*
|
||||
* cpustbl.cpp must be compiled twice, once for the generator program
|
||||
* and once for the actual executable
|
||||
*/
|
||||
#include "cpustbl.cpp"
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* debug.cpp - CPU debugger
|
||||
*
|
||||
* Copyright (c) 2001-2010 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Bernd Schmidt's UAE
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Debugger
|
||||
*
|
||||
* (c) 1995 Bernd Schmidt
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include "memory.h"
|
||||
#include "newcpu.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "input.h"
|
||||
#include "cpu_emulation.h"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
static int debugger_active = 0;
|
||||
int debugging = 0;
|
||||
int irqindebug = 0;
|
||||
|
||||
int ignore_irq = 0;
|
||||
|
||||
|
||||
void activate_debugger (void)
|
||||
{
|
||||
#ifdef DEBUGGER
|
||||
ndebug::do_skip = false;
|
||||
#endif
|
||||
debugger_active = 1;
|
||||
SPCFLAGS_SET( SPCFLAG_BRK );
|
||||
debugging = 1;
|
||||
/* use_debugger = 1; */
|
||||
}
|
||||
|
||||
void deactivate_debugger(void)
|
||||
{
|
||||
debugging = 0;
|
||||
debugger_active = 0;
|
||||
}
|
||||
|
||||
void debug (void)
|
||||
{
|
||||
if (ignore_irq && regs.s && !regs.m ) {
|
||||
SPCFLAGS_SET( SPCFLAG_BRK );
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUGGER
|
||||
ndebug::run();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
vim:ts=4:sw=4:
|
||||
*/
|
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/core.h - base fpu context definition
|
||||
* fpu/core.h - base fpu context definition
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_CORE_H
|
||||
|
@ -39,15 +34,11 @@
|
|||
/* Always use x87 FPU stack on IA-32. */
|
||||
#if defined(X86_ASSEMBLY)
|
||||
#define USE_X87_ASSEMBLY 1
|
||||
#ifndef USE_JIT_FPU
|
||||
#define ACCURATE_SIN_COS_TAN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Only use x87 FPU on x86-64 if long double precision is requested. */
|
||||
#if defined(X86_64_ASSEMBLY) && defined(USE_LONG_DOUBLE)
|
||||
#if defined(X86_64_ASSEMBLY) && USE_LONG_DOUBLE
|
||||
#define USE_X87_ASSEMBLY 1
|
||||
#define ACCURATE_SIN_COS_TAN 1
|
||||
#endif
|
||||
|
||||
/* ========================================================================== */
|
||||
|
@ -116,7 +107,7 @@ struct fpu_t {
|
|||
|
||||
/* Floating-Point Condition Code Byte */
|
||||
uae_u32 condition_codes;
|
||||
#define FPSR_CCB 0x0f000000
|
||||
#define FPSR_CCB 0xff000000
|
||||
#define FPSR_CCB_NEGATIVE 0x08000000
|
||||
#define FPSR_CCB_ZERO 0x04000000
|
||||
#define FPSR_CCB_INFINITY 0x02000000
|
||||
|
@ -228,7 +219,7 @@ struct fpu_t {
|
|||
extern fpu_t fpu;
|
||||
|
||||
/* Return the address of a particular register */
|
||||
inline fpu_register * fpu_register_address(int i)
|
||||
inline fpu_register * const fpu_register_address(int i)
|
||||
{ return &fpu.registers[i]; }
|
||||
|
||||
/* Dump functions for m68k_dumpstate */
|
||||
|
@ -236,16 +227,16 @@ extern void fpu_dump_registers(void);
|
|||
extern void fpu_dump_flags(void);
|
||||
|
||||
/* Accessors to FPU Control Register */
|
||||
//static inline uae_u32 get_fpcr(void);
|
||||
//static inline void set_fpcr(uae_u32 new_fpcr);
|
||||
static inline uae_u32 get_fpcr(void);
|
||||
static inline void set_fpcr(uae_u32 new_fpcr);
|
||||
|
||||
/* Accessors to FPU Status Register */
|
||||
//static inline uae_u32 get_fpsr(void);
|
||||
//static inline void set_fpsr(uae_u32 new_fpsr);
|
||||
static inline uae_u32 get_fpsr(void);
|
||||
static inline void set_fpsr(uae_u32 new_fpsr);
|
||||
|
||||
/* Accessors to FPU Instruction Address Register */
|
||||
//static inline uae_u32 get_fpiar();
|
||||
//static inline void set_fpiar(uae_u32 new_fpiar);
|
||||
static inline uae_u32 get_fpiar();
|
||||
static inline void set_fpiar(uae_u32 new_fpiar);
|
||||
|
||||
/* Initialization / Finalization */
|
||||
extern void fpu_init(bool integral_68040);
|
||||
|
@ -263,6 +254,6 @@ void fpuop_scc(uae_u32 opcode, uae_u32 extra) REGPARAM;
|
|||
/* Floating-point system control operations */
|
||||
void fpuop_save(uae_u32 opcode) REGPARAM;
|
||||
void fpuop_restore(uae_u32 opcode) REGPARAM;
|
||||
void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) REGPARAM;
|
||||
void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) REGPARAM;
|
||||
|
||||
#endif /* FPU_CORE_H */
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/exceptions.cpp - system-dependant FPU exceptions management
|
||||
* fpu/exceptions.cpp - system-dependant FPU exceptions management
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#undef PRIVATE
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/exceptions.h - system-dependant FPU exceptions management
|
||||
* fpu/exceptions.h - system-dependant FPU exceptions management
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_EXCEPTIONS_H
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/flags.cpp - Floating-point flags
|
||||
* fpu/flags.cpp - Floating-point flags
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/flags.h - Floating-point flags
|
||||
* fpu/flags.h - Floating-point flags
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_FLAGS_H
|
||||
|
@ -117,7 +112,7 @@ PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
|
|||
|
||||
/* Make FPSR according to the value passed in argument */
|
||||
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
|
||||
{ uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=a" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; }
|
||||
{ uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=r" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; }
|
||||
|
||||
/* Return the corresponding ID of the current floating-point condition codes */
|
||||
/* NOTE: only valid for evaluation of a condition */
|
||||
|
@ -222,7 +217,7 @@ PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
|
|||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* Return the address of the floating-point condition codes register */
|
||||
static inline uae_u32 * FFPU address_of_fpccr(void)
|
||||
static inline uae_u32 * const FFPU address_of_fpccr(void)
|
||||
{ return ((uae_u32 *)& FPU fpsr.condition_codes); }
|
||||
|
||||
#endif /* FPU_FLAGS_H */
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/fpu.h - public header
|
||||
* fpu/fpu.h - public header
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_PUBLIC_HEADER_H
|
||||
|
@ -51,9 +46,4 @@
|
|||
#include "fpu/types.h"
|
||||
#include "fpu/core.h"
|
||||
|
||||
void fpu_set_fpsr(uae_u32 new_fpsr);
|
||||
uae_u32 fpu_get_fpsr(void);
|
||||
void fpu_set_fpcr(uae_u32 new_fpcr);
|
||||
uae_u32 fpu_get_fpcr(void);
|
||||
|
||||
#endif /* FPU_PUBLIC_HEADER_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/fpu_ieee.h - Extra Definitions for the IEEE FPU core
|
||||
* fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_IEEE_H
|
||||
|
@ -65,7 +60,7 @@ PRIVATE inline void FFPU make_zero_negative(fpu_register & r);
|
|||
PRIVATE inline void FFPU make_inf_positive(fpu_register & r);
|
||||
PRIVATE inline void FFPU make_inf_negative(fpu_register & r);
|
||||
|
||||
// MJ PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
|
||||
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
|
||||
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r);
|
||||
|
||||
// May be optimized for particular processors
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,42 +1,31 @@
|
|||
/*
|
||||
* fpu/fpu_uae.cpp - the old UAE FPU
|
||||
* fpu/fpu_uae.cpp
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* MC68881 emulation
|
||||
*
|
||||
* Copyright 1996 Herman ten Brugge
|
||||
*
|
||||
*
|
||||
* Following fixes by Lauri Pesonen, July 1999:
|
||||
*
|
||||
* FMOVEM list handling:
|
||||
|
@ -97,8 +86,9 @@
|
|||
* - Precision rounding single/double
|
||||
*/
|
||||
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "memory.h"
|
||||
#include "readcpu.h"
|
||||
#include "newcpu.h"
|
||||
|
@ -107,17 +97,6 @@
|
|||
#include "fpu/fpu.h"
|
||||
#include "fpu/fpu_uae.h"
|
||||
|
||||
#ifdef HAVE_NEW_HEADERS
|
||||
#define _GLIBCPP_USE_C99 1
|
||||
# include <cmath>
|
||||
# include <cstdio>
|
||||
using namespace __gnu_cxx;
|
||||
#undef _GLIBCPP_USE_C99
|
||||
#else
|
||||
# include <math.h>
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
/* Global FPU context */
|
||||
fpu_t fpu;
|
||||
|
||||
|
@ -187,8 +166,8 @@ PUBLIC void FFPU dump_registers(const char * str)
|
|||
|
||||
sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n",
|
||||
str,
|
||||
fpu_get_register(0), fpu_get_register(1), fpu_get_register(2), fpu_get_register(3),
|
||||
fpu_get_register(4), fpu_get_register(5), fpu_get_register(6), fpu_get_register(7) );
|
||||
get_register(0), get_register(1), get_register(2), get_register(3),
|
||||
get_register(4), get_register(5), get_register(6), get_register(7) );
|
||||
|
||||
fpu_debug((temp_str));
|
||||
}
|
||||
|
@ -216,7 +195,9 @@ PUBLIC void FFPU dump_registers(const char *)
|
|||
{
|
||||
}
|
||||
|
||||
#define dump_first_bytes(a,b)
|
||||
PUBLIC void FFPU dump_first_bytes(uae_u8 *, uae_s32)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -238,10 +219,10 @@ PRIVATE inline fpu_register FFPU round_to_nearest(fpu_register const & x)
|
|||
|
||||
PRIVATE inline bool FFPU do_isnan(fpu_register const & r)
|
||||
{
|
||||
fpu_register_parts const p = { r };
|
||||
if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000) {
|
||||
uae_u32 * p = (uae_u32 *)&r;
|
||||
if ((p[FHI] & 0x7FF00000) == 0x7FF00000) {
|
||||
// logical or is faster here.
|
||||
if ((p.parts[FHI] & 0x000FFFFF) || p.parts[FLO]) {
|
||||
if ((p[FHI] & 0x000FFFFF) || p[FLO]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -254,8 +235,8 @@ PRIVATE inline bool FFPU do_isnan(fpu_register const & r)
|
|||
|
||||
PRIVATE inline bool FFPU do_isinf(fpu_register const & r)
|
||||
{
|
||||
fpu_register_parts const p = { r };
|
||||
if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000 && p.parts[FLO] == 0) {
|
||||
uae_u32 * p = (uae_u32 *)&r;
|
||||
if (((p[FHI] & 0x7FF00000) == 0x7FF00000) && p[FLO] == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -267,8 +248,8 @@ PRIVATE inline bool FFPU do_isinf(fpu_register const & r)
|
|||
|
||||
PRIVATE inline bool FFPU do_isneg(fpu_register const & r)
|
||||
{
|
||||
fpu_register_parts const p = { r };
|
||||
return ((p.parts[FHI] & 0x80000000) != 0);
|
||||
uae_u32 * p = (uae_u32 *)&r;
|
||||
return ((p[FHI] & 0x80000000) != 0);
|
||||
}
|
||||
|
||||
#ifndef HAVE_ISZERO
|
||||
|
@ -277,8 +258,8 @@ PRIVATE inline bool FFPU do_isneg(fpu_register const & r)
|
|||
|
||||
PRIVATE inline bool FFPU do_iszero(fpu_register const & r)
|
||||
{
|
||||
fpu_register_parts const p = { r };
|
||||
return (((p.parts[FHI] & 0x7FF00000) == 0) && p.parts[FLO] == 0);
|
||||
uae_u32 * p = (uae_u32 *)&r;
|
||||
return (((p[FHI] & 0x7FF00000) == 0) && p[FLO] == 0);
|
||||
}
|
||||
|
||||
// May be optimized for particular processors
|
||||
|
@ -314,83 +295,75 @@ PRIVATE inline void FFPU get_source_flags(fpu_register const & r)
|
|||
|
||||
PRIVATE inline void FFPU make_nan(fpu_register & r)
|
||||
{
|
||||
fpu_register_parts p;
|
||||
p.parts[FLO] = 0xffffffff;
|
||||
p.parts[FHI] = 0x7fffffff;
|
||||
r = p.val;
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
p[FLO] = 0xffffffff;
|
||||
p[FHI] = 0x7fffffff;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU make_zero_positive(fpu_register & r)
|
||||
{
|
||||
fpu_register_parts p;
|
||||
p.parts[FLO] = p.parts[FHI] = 0;
|
||||
r = p.val;
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
p[FLO] = p[FHI] = 0;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU make_zero_negative(fpu_register & r)
|
||||
{
|
||||
fpu_register_parts p;
|
||||
p.parts[FLO] = 0;
|
||||
p.parts[FHI] = 0x80000000;
|
||||
r = p.val;
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
p[FLO] = 0;
|
||||
p[FHI] = 0x80000000;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU make_inf_positive(fpu_register & r)
|
||||
{
|
||||
fpu_register_parts p;
|
||||
p.parts[FLO] = 0;
|
||||
p.parts[FHI] = 0x7FF00000;
|
||||
r = p.val;
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
p[FLO] = 0;
|
||||
p[FHI] = 0x7FF00000;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU make_inf_negative(fpu_register & r)
|
||||
{
|
||||
fpu_register_parts p;
|
||||
p.parts[FLO] = 0;
|
||||
p.parts[FHI] = 0xFFF00000;
|
||||
r = p.val;
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
p[FLO] = 0;
|
||||
p[FHI] = 0xFFF00000;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add)
|
||||
{
|
||||
fpu_register_parts p = { r };
|
||||
int exp = (p.parts[FHI] & 0x7FF00000) >> 20;
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
int exp = (p[FHI] & 0x7FF00000) >> 20;
|
||||
// TODO: overflow flags
|
||||
exp += add;
|
||||
if(exp >= 2047) {
|
||||
make_inf_positive(r);
|
||||
return;
|
||||
} else if(exp < 0) {
|
||||
// keep sign (+/- 0)
|
||||
p.parts[FHI] &= 0x80000000;
|
||||
p[FHI] &= 0x80000000;
|
||||
} else {
|
||||
p.parts[FHI] = (p.parts[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20);
|
||||
p[FHI] = (p[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20);
|
||||
}
|
||||
r = p.val;
|
||||
}
|
||||
|
||||
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r)
|
||||
{
|
||||
fpu_register_parts const p = { r };
|
||||
int exp = (p.parts[FHI] & 0x7FF00000) >> 20;
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
int exp = (p[FHI] & 0x7FF00000) >> 20;
|
||||
return( exp - 1023 );
|
||||
}
|
||||
|
||||
// Normalize to range 1..2
|
||||
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r)
|
||||
{
|
||||
fpu_register_parts p = { r };
|
||||
p.parts[FHI] = (p.parts[FHI] & 0x800FFFFF) | 0x3FF00000;
|
||||
r = p.val;
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
p[FHI] = (p[FHI] & 0x800FFFFF) | 0x3FF00000;
|
||||
}
|
||||
|
||||
// The sign of the quotient is the exclusive-OR of the sign bits
|
||||
// of the source and destination operands.
|
||||
PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb)
|
||||
{
|
||||
fpu_register_parts const a = { ra };
|
||||
fpu_register_parts const b = { rb };
|
||||
return (((a.parts[FHI] ^ b.parts[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0);
|
||||
uae_u32 * const a = (uae_u32 *)&ra;
|
||||
uae_u32 * const b = (uae_u32 *)&rb;
|
||||
return (((a[FHI] ^ b[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0);
|
||||
}
|
||||
|
||||
// Quotient Byte is loaded with the sign and least significant
|
||||
|
@ -408,15 +381,13 @@ PRIVATE inline fpu_register FFPU make_single(uae_u32 value)
|
|||
return (0.0);
|
||||
|
||||
fpu_register result;
|
||||
fpu_register_parts p;
|
||||
uae_u32 * p = (uae_u32 *)&result;
|
||||
|
||||
uae_u32 sign = (value & 0x80000000);
|
||||
uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127;
|
||||
|
||||
p.parts[FLO] = value << 29;
|
||||
p.parts[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3);
|
||||
|
||||
result = p.val;
|
||||
p[FLO] = value << 29;
|
||||
p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3);
|
||||
|
||||
fpu_debug(("make_single (%X) = %.04f\n",value,(double)result));
|
||||
|
||||
|
@ -430,10 +401,10 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src)
|
|||
return 0;
|
||||
|
||||
uae_u32 result;
|
||||
fpu_register_parts const p = { src };
|
||||
uae_u32 *p = (uae_u32 *)&src;
|
||||
|
||||
uae_u32 sign = (p.parts[FHI] & 0x80000000);
|
||||
uae_u32 exp = (p.parts[FHI] & 0x7FF00000) >> 20;
|
||||
uae_u32 sign = (p[FHI] & 0x80000000);
|
||||
uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20;
|
||||
|
||||
if(exp + 127 < 1023) {
|
||||
exp = 0;
|
||||
|
@ -443,7 +414,7 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src)
|
|||
exp = exp + 127 - 1023;
|
||||
}
|
||||
|
||||
result = sign | (exp << 23) | ((p.parts[FHI] & 0x000FFFFF) << 3) | (p.parts[FLO] >> 29);
|
||||
result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29);
|
||||
|
||||
fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result));
|
||||
|
||||
|
@ -457,8 +428,8 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u
|
|||
return 0.0;
|
||||
|
||||
fpu_register result;
|
||||
fpu_register_parts p;
|
||||
|
||||
uae_u32 *p = (uae_u32 *)&result;
|
||||
|
||||
uae_u32 sign = wrd1 & 0x80000000;
|
||||
uae_u32 exp = (wrd1 >> 16) & 0x7fff;
|
||||
|
||||
|
@ -495,10 +466,8 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u
|
|||
}
|
||||
|
||||
// drop the explicit integer bit.
|
||||
p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
||||
p.parts[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
|
||||
|
||||
result = p.val;
|
||||
p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
||||
p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
|
||||
|
||||
fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
|
||||
|
||||
|
@ -542,13 +511,11 @@ PRIVATE inline void FFPU make_extended_no_normalize(
|
|||
}
|
||||
|
||||
// drop the explicit integer bit.
|
||||
fpu_register_parts p;
|
||||
p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
||||
p.parts[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
|
||||
uae_u32 *p = (uae_u32 *)&result;
|
||||
p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
||||
p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
|
||||
|
||||
result = p.val;
|
||||
|
||||
fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
|
||||
fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(float)(*(double *)p)));
|
||||
}
|
||||
|
||||
// from_exten
|
||||
|
@ -560,14 +527,14 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src,
|
|||
*wrd1 = *wrd2 = *wrd3 = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
fpu_register_parts const p = { src };
|
||||
|
||||
fpu_debug(("extract_extended (%X,%X)\n",p.parts[FLO],p.parts[FHI]));
|
||||
uae_u32 *p = (uae_u32 *)&src;
|
||||
|
||||
fpu_debug(("extract_extended (%X,%X)\n",p[FLO],p[FHI]));
|
||||
|
||||
uae_u32 sign = p.parts[FHI] & 0x80000000;
|
||||
uae_u32 sign = p[FHI] & 0x80000000;
|
||||
|
||||
uae_u32 exp = ((p.parts[FHI] >> 20) & 0x7ff);
|
||||
uae_u32 exp = ((p[FHI] >> 20) & 0x7ff);
|
||||
// Check for maximum
|
||||
if(exp == 0x7FF) {
|
||||
exp = 0x7FFF;
|
||||
|
@ -577,8 +544,8 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src,
|
|||
|
||||
*wrd1 = sign | (exp << 16);
|
||||
// always set the explicit integer bit.
|
||||
*wrd2 = 0x80000000 | ((p.parts[FHI] & 0x000FFFFF) << 11) | ((p.parts[FLO] & 0xFFE00000) >> 21);
|
||||
*wrd3 = p.parts[FLO] << 11;
|
||||
*wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21);
|
||||
*wrd3 = p[FLO] << 11;
|
||||
|
||||
fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3));
|
||||
}
|
||||
|
@ -590,11 +557,9 @@ PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2)
|
|||
return 0.0;
|
||||
|
||||
fpu_register result;
|
||||
fpu_register_parts p;
|
||||
p.parts[FLO] = wrd2;
|
||||
p.parts[FHI] = wrd1;
|
||||
|
||||
result = p.val;
|
||||
uae_u32 *p = (uae_u32 *)&result;
|
||||
p[FLO] = wrd2;
|
||||
p[FHI] = wrd1;
|
||||
|
||||
fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,(double)result));
|
||||
|
||||
|
@ -612,9 +577,9 @@ PRIVATE inline void FFPU extract_double(fpu_register const & src,
|
|||
return;
|
||||
}
|
||||
*/
|
||||
fpu_register_parts const p = { src };
|
||||
*wrd2 = p.parts[FLO];
|
||||
*wrd1 = p.parts[FHI];
|
||||
uae_u32 *p = (uae_u32 *)&src;
|
||||
*wrd2 = p[FLO];
|
||||
*wrd1 = p[FHI];
|
||||
|
||||
fpu_debug(("extract_double (%.04f) = %X,%X\n",(double)src,*wrd1,*wrd2));
|
||||
}
|
||||
|
@ -657,25 +622,25 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src)
|
|||
fpu_register src0 = src;
|
||||
#endif
|
||||
|
||||
if (src == 0.0)
|
||||
if (src == 0.0)
|
||||
return 0;
|
||||
if (src < 0) {
|
||||
if (src < 0) {
|
||||
tmp = 0x80000000;
|
||||
src = -src;
|
||||
} else {
|
||||
} else {
|
||||
tmp = 0;
|
||||
}
|
||||
frac = frexp (src, &expon);
|
||||
frac += 0.5 / 16777216.0;
|
||||
if (frac >= 1.0) {
|
||||
}
|
||||
frac = frexp (src, &expon);
|
||||
frac += 0.5 / 16777216.0;
|
||||
if (frac >= 1.0) {
|
||||
frac /= 2.0;
|
||||
expon++;
|
||||
}
|
||||
}
|
||||
result = tmp | (((expon + 127 - 1) & 0xff) << 23) | (((int) (frac * 16777216.0)) & 0x7fffff);
|
||||
|
||||
// fpu_debug(("extract_single (%.04f) = %X\n",(float)src0,result));
|
||||
|
||||
return (result);
|
||||
return (result);
|
||||
}
|
||||
|
||||
// to exten
|
||||
|
@ -930,9 +895,11 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe
|
|||
break;
|
||||
case 3:
|
||||
ad = m68k_areg (regs, reg);
|
||||
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
|
||||
break;
|
||||
case 4:
|
||||
ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]);
|
||||
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
|
||||
ad = m68k_areg (regs, reg);
|
||||
break;
|
||||
case 5:
|
||||
ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
|
||||
|
@ -973,8 +940,8 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe
|
|||
fpu_debug(("get_fp_value m68k_getpc()=%X\n",m68k_getpc()));
|
||||
fpu_debug(("get_fp_value ad=%X\n",ad));
|
||||
fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (ad)));
|
||||
dump_first_bytes( get_real_address(ad, 0, 0)-64, 64 );
|
||||
dump_first_bytes( get_real_address(ad, 0, 0), 64 );
|
||||
dump_first_bytes( get_real_address(ad)-64, 64 );
|
||||
dump_first_bytes( get_real_address(ad), 64 );
|
||||
|
||||
switch (size) {
|
||||
case 0:
|
||||
|
@ -1021,15 +988,6 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe
|
|||
return 0;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 3:
|
||||
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
|
||||
break;
|
||||
case 4:
|
||||
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
|
||||
break;
|
||||
}
|
||||
|
||||
// fpu_debug(("get_fp_value result = %.04f\n",(float)src));
|
||||
return 1;
|
||||
}
|
||||
|
@ -1246,7 +1204,7 @@ PRIVATE inline int FFPU fpp_cond(int condition)
|
|||
#if 0
|
||||
return fpcctrue(condition);
|
||||
#else
|
||||
switch (condition & 0x1f) {
|
||||
switch (condition) {
|
||||
case 0x00: CONDRET("False",0);
|
||||
case 0x01: CONDRET("Equal",Z);
|
||||
case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N));
|
||||
|
@ -1341,11 +1299,11 @@ void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra)
|
|||
put_byte(ad, cc ? 0xff : 0x00);
|
||||
}
|
||||
|
||||
void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra)
|
||||
void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc)
|
||||
{
|
||||
fpu_debug(("ftrapcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
|
||||
fpu_debug(("ftrapcc_opp %X at %08lx\n", (uae_u32)opcode, m68k_getpc ()));
|
||||
|
||||
int cc = fpp_cond(extra & 0x3f);
|
||||
int cc = fpp_cond(opcode & 0x3f);
|
||||
if (cc == -1) {
|
||||
m68k_setpc (oldpc);
|
||||
op_illg (opcode);
|
||||
|
@ -1948,8 +1906,6 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
FPU registers[reg] = 1.0e256;
|
||||
fpu_debug(("FP const: 1.0e256\n"));
|
||||
break;
|
||||
|
||||
// Valid for 64 bits only (see fpu.cpp)
|
||||
#if 0
|
||||
case 0x3c:
|
||||
FPU registers[reg] = 1.0e512;
|
||||
|
@ -1986,126 +1942,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
return;
|
||||
}
|
||||
fpu_debug(("returned from get_fp_value m68k_getpc()=%X\n",m68k_getpc()));
|
||||
#if 0 // MJ added, not tested now
|
||||
if (FPU is_integral) {
|
||||
// 68040-specific operations
|
||||
switch (extra & 0x7f) {
|
||||
case 0x40: /* FSMOVE */
|
||||
fpu_debug(("FSMOVE %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)src;
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x44: /* FDMOVE */
|
||||
fpu_debug(("FDMOVE %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)src;
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x41: /* FSSQRT */
|
||||
fpu_debug(("FSQRT %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)sqrt (src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x45: /* FDSQRT */
|
||||
fpu_debug(("FSQRT %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)sqrt (src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x58: /* FSABS */
|
||||
fpu_debug(("FSABS %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)fabs(src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x5c: /* FDABS */
|
||||
fpu_debug(("FDABS %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)fabs(src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x5a: /* FSNEG */
|
||||
fpu_debug(("FSNEG %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)-src;
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x5e: /* FDNEG */
|
||||
fpu_debug(("FDNEG %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)-src;
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x60: /* FSDIV */
|
||||
fpu_debug(("FSDIV %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)(FPU registers[reg] / src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x64: /* FDDIV */
|
||||
fpu_debug(("FDDIV %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)(FPU registers[reg] / src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x62: /* FSADD */
|
||||
fpu_debug(("FSADD %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)(FPU registers[reg] + src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x66: /* FDADD */
|
||||
fpu_debug(("FDADD %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)(FPU registers[reg] + src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x68: /* FSSUB */
|
||||
fpu_debug(("FSSUB %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)(FPU registers[reg] - src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x6c: /* FDSUB */
|
||||
fpu_debug(("FDSUB %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)(FPU registers[reg] - src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x63: /* FSMUL */
|
||||
case 0x67: /* FDMUL */
|
||||
get_dest_flags(FPU registers[reg]);
|
||||
get_source_flags(src);
|
||||
if(fl_dest.in_range && fl_source.in_range) {
|
||||
if ((extra & 0x7f) == 0x63)
|
||||
FPU registers[reg] = (float)(FPU registers[reg] * src);
|
||||
else
|
||||
FPU registers[reg] = (double)(FPU registers[reg] * src);
|
||||
}
|
||||
else if (fl_dest.nan || fl_source.nan ||
|
||||
fl_dest.zero && fl_source.infinity ||
|
||||
fl_dest.infinity && fl_source.zero ) {
|
||||
make_nan( FPU registers[reg] );
|
||||
}
|
||||
else if (fl_dest.zero || fl_source.zero ) {
|
||||
if (fl_dest.negative && !fl_source.negative ||
|
||||
!fl_dest.negative && fl_source.negative) {
|
||||
make_zero_negative(FPU registers[reg]);
|
||||
}
|
||||
else {
|
||||
make_zero_positive(FPU registers[reg]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if( fl_dest.negative && !fl_source.negative ||
|
||||
!fl_dest.negative && fl_source.negative) {
|
||||
make_inf_negative(FPU registers[reg]);
|
||||
}
|
||||
else {
|
||||
make_inf_positive(FPU registers[reg]);
|
||||
}
|
||||
}
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
default:
|
||||
// Continue decode-execute 6888x instructions below
|
||||
goto process_6888x_instructions;
|
||||
}
|
||||
fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc()));
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
|
||||
process_6888x_instructions:
|
||||
#endif
|
||||
switch (extra & 0x7f) {
|
||||
case 0x00: /* FMOVE */
|
||||
fpu_debug(("FMOVE %.04f\n",(double)src));
|
||||
|
@ -2329,13 +2166,13 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
FPU registers[reg] *= src;
|
||||
}
|
||||
else if (fl_dest.nan || fl_source.nan ||
|
||||
(fl_dest.zero && fl_source.infinity) ||
|
||||
(fl_dest.infinity && fl_source.zero) ) {
|
||||
fl_dest.zero && fl_source.infinity ||
|
||||
fl_dest.infinity && fl_source.zero ) {
|
||||
make_nan( FPU registers[reg] );
|
||||
}
|
||||
else if (fl_dest.zero || fl_source.zero ) {
|
||||
if (( fl_dest.negative && !fl_source.negative) ||
|
||||
(!fl_dest.negative && fl_source.negative)) {
|
||||
if (fl_dest.negative && !fl_source.negative ||
|
||||
!fl_dest.negative && fl_source.negative) {
|
||||
make_zero_negative(FPU registers[reg]);
|
||||
}
|
||||
else {
|
||||
|
@ -2343,8 +2180,8 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
}
|
||||
}
|
||||
else {
|
||||
if(( fl_dest.negative && !fl_source.negative) ||
|
||||
(!fl_dest.negative && fl_source.negative)) {
|
||||
if( fl_dest.negative && !fl_source.negative ||
|
||||
!fl_dest.negative && fl_source.negative) {
|
||||
make_inf_negative(FPU registers[reg]);
|
||||
}
|
||||
else {
|
||||
|
@ -2499,27 +2336,6 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
|
||||
void fpu_set_fpsr(uae_u32 new_fpsr)
|
||||
{
|
||||
set_fpsr(new_fpsr);
|
||||
}
|
||||
|
||||
uae_u32 fpu_get_fpsr(void)
|
||||
{
|
||||
return get_fpsr();
|
||||
}
|
||||
|
||||
void fpu_set_fpcr(uae_u32 new_fpcr)
|
||||
{
|
||||
set_fpcr(new_fpcr);
|
||||
}
|
||||
|
||||
uae_u32 fpu_get_fpcr(void)
|
||||
{
|
||||
return get_fpcr();
|
||||
}
|
||||
|
||||
/* -------------------------- Initialization -------------------------- */
|
||||
|
||||
void FFPU fpu_init (bool integral_68040)
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core
|
||||
* fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_UAE_H
|
||||
|
|
|
@ -1,33 +1,27 @@
|
|||
/*
|
||||
* fpu/fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86.
|
||||
* fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86.
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* Based on UAE FPU, original copyright 1996 Herman ten Brugge,
|
||||
* rewritten for x86 by Lauri Pesonen 1999-2000,
|
||||
* accomodated to GCC's Extended Asm syntax by Gwenole Beauchesne 2000.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*
|
||||
* Interface
|
||||
|
@ -140,8 +134,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
# include <cmath>
|
||||
# include <cstdio>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "memory.h"
|
||||
|
@ -242,6 +238,8 @@ PUBLIC void FFPU fpu_dump_flags(void)
|
|||
#include "debug.h"
|
||||
|
||||
#if FPU_DEBUG
|
||||
#undef __inline__
|
||||
#define __inline__
|
||||
|
||||
PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual)
|
||||
{
|
||||
|
@ -392,7 +390,7 @@ PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *)
|
|||
|
||||
/* ---------------------------- Status functions ---------------------------- */
|
||||
|
||||
PRIVATE void inline FFPU SET_BSUN_ON_NAN ()
|
||||
PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN ()
|
||||
{
|
||||
if( (x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN ) {
|
||||
x86_status_word |= SW_FAKE_BSUN;
|
||||
|
@ -400,7 +398,7 @@ PRIVATE void inline FFPU SET_BSUN_ON_NAN ()
|
|||
}
|
||||
}
|
||||
|
||||
PRIVATE void inline FFPU build_ex_status ()
|
||||
PRIVATE void __inline__ FFPU build_ex_status ()
|
||||
{
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
|
@ -417,7 +415,7 @@ When the FPU creates a NAN, the NAN always contains the same bit pattern
|
|||
in the mantissa. All bits of the mantissa are ones for any precision.
|
||||
When the user creates a NAN, any nonzero bit pattern can be stored in the mantissa.
|
||||
*/
|
||||
PRIVATE inline void FFPU MAKE_NAN (fpu_register & f)
|
||||
PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f)
|
||||
{
|
||||
// Make it non-signaling.
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
|
@ -427,10 +425,10 @@ PRIVATE inline void FFPU MAKE_NAN (fpu_register & f)
|
|||
|
||||
/*
|
||||
For single- and double-precision infinities the fraction is a zero.
|
||||
For extended-precision infinities, the mantissa<EFBFBD>s MSB, the explicit
|
||||
For extended-precision infinities, the mantissa’s MSB, the explicit
|
||||
integer bit, can be either one or zero.
|
||||
*/
|
||||
PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f)
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f)
|
||||
{
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) {
|
||||
|
@ -441,7 +439,7 @@ PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f)
|
|||
return(0);
|
||||
}
|
||||
|
||||
PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f)
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f)
|
||||
{
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) {
|
||||
|
@ -452,7 +450,7 @@ PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f)
|
|||
return(0);
|
||||
}
|
||||
|
||||
PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f)
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f)
|
||||
{
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
return *((uae_u32 *)p) == 0 &&
|
||||
|
@ -460,34 +458,34 @@ PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f)
|
|||
( *((uae_u16 *)&p[8]) & 0x7FFF ) == 0;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU MAKE_INF_POSITIVE (fpu_register & f)
|
||||
PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f)
|
||||
{
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
memset( p, 0, sizeof(fpu_register)-2 );
|
||||
*((uae_u16 *)&p[8]) = 0x7FFF;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU MAKE_INF_NEGATIVE (fpu_register & f)
|
||||
PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f)
|
||||
{
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
memset( p, 0, sizeof(fpu_register)-2 );
|
||||
*((uae_u16 *)&p[8]) = 0xFFFF;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU MAKE_ZERO_POSITIVE (fpu_register & f)
|
||||
PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f)
|
||||
{
|
||||
uae_u32 * const p = (uae_u32 *) &f;
|
||||
memset( p, 0, sizeof(fpu_register) );
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f)
|
||||
PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f)
|
||||
{
|
||||
uae_u32 * const p = (uae_u32 *) &f;
|
||||
memset( p, 0, sizeof(fpu_register) );
|
||||
*((uae_u32 *)&p[4]) = 0x80000000;
|
||||
}
|
||||
|
||||
PRIVATE inline uae_u32 FFPU IS_NEGATIVE (fpu_register const & f)
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f)
|
||||
{
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
return( (p[9] & 0x80) != 0 );
|
||||
|
@ -902,34 +900,6 @@ PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fmove");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsmove ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fsmove");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdmove ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdmove");
|
||||
}
|
||||
|
||||
/*
|
||||
PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
|
@ -1053,50 +1023,6 @@ PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fsqrt");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fssqrt ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fsqrt \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE);
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fssqrt");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdsqrt ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fsqrt \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE);
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdsqrt");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_ftst ( fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
|
@ -1385,48 +1311,6 @@ PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fabs");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsabs ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fabs \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
// x86 fabs should not rise any exceptions (except stack underflow)
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~SW_EXCEPTION_MASK;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fsabs");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdabs ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fabs \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
// x86 fabs should not rise any exceptions (except stack underflow)
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~SW_EXCEPTION_MASK;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdabs");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
|
@ -1457,48 +1341,6 @@ PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fneg");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsneg ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fchs \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
// x86 fchs should not rise any exceptions (except stack underflow)
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~SW_EXCEPTION_MASK;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fsneg");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdneg ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fchs \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
// x86 fchs should not rise any exceptions (except stack underflow)
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~SW_EXCEPTION_MASK;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdneg");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
|
@ -1624,50 +1466,6 @@ PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fdiv");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsdiv ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fdiv %%st(1), %%st(0)\n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
"fstp %%st(0)\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fsdiv");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fddiv ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fdiv %%st(1), %%st(0)\n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
"fstp %%st(0)\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fddiv");
|
||||
}
|
||||
|
||||
// The sign of the quotient is the exclusive-OR of the sign bits
|
||||
// of the source and destination operands.
|
||||
// Quotient Byte is loaded with the sign and least significant
|
||||
|
@ -2053,48 +1851,6 @@ PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fadd");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsadd ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fadd \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fsadd");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdadd ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fadd \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdadd");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
|
@ -2126,48 +1882,6 @@ PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fmul");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsmul ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fmul \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fsmul");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdmul ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fmul \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdmul");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
|
@ -2326,52 +2040,6 @@ PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fsub");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fssub ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fsub %%st(1), %%st(0)\n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
"fstp %%st(0)\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fssub");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdsub ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fsub %%st(1), %%st(0)\n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
"fstp %%st(0)\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdsub");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
|
@ -2616,9 +2284,11 @@ PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src
|
|||
break;
|
||||
case 3:
|
||||
ad = m68k_areg (regs, reg);
|
||||
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
|
||||
break;
|
||||
case 4:
|
||||
ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]);
|
||||
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
|
||||
ad = m68k_areg (regs, reg);
|
||||
break;
|
||||
case 5:
|
||||
ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
|
||||
|
@ -2717,15 +2387,6 @@ PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src
|
|||
return 0;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 3:
|
||||
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
|
||||
break;
|
||||
case 4:
|
||||
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
|
||||
break;
|
||||
}
|
||||
|
||||
// D(bug("get_fp_value result = %.04f\r\n",(float)src));
|
||||
|
||||
return 1;
|
||||
|
@ -2951,7 +2612,7 @@ PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition)
|
|||
#define I ((x86_status_word & (SW_Z_I_NAN_MASK)) == (SW_I))
|
||||
#define NotANumber ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN)
|
||||
|
||||
switch (condition & 0x1f) {
|
||||
switch (condition) {
|
||||
// Common Tests, no BSUN
|
||||
case 0x01:
|
||||
CONDRET("Equal",Z);
|
||||
|
@ -3096,11 +2757,11 @@ PUBLIC void REGPARAM2 FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra)
|
|||
}
|
||||
}
|
||||
|
||||
PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra)
|
||||
PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc)
|
||||
{
|
||||
int cc;
|
||||
|
||||
D(bug("ftrapcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
|
||||
D(bug("ftrapcc_opp %X at %08lx\r\n", (uae_u32)opcode, m68k_getpc ()));
|
||||
|
||||
#if I3_ON_FTRAPCC
|
||||
#error "FIXME: _asm int 3"
|
||||
|
@ -3108,7 +2769,7 @@ PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 e
|
|||
#endif
|
||||
|
||||
// This must be broken.
|
||||
cc = fpp_cond(opcode, extra & 0x3f);
|
||||
cc = fpp_cond(opcode, opcode & 0x3f);
|
||||
|
||||
if (cc < 0) {
|
||||
m68k_setpc (oldpc);
|
||||
|
@ -4985,249 +4646,6 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32
|
|||
}
|
||||
|
||||
|
||||
/* -------------------------- 040 ALU -------------------------- */
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsmove( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSMOVE %s\r\n",etos(src)));
|
||||
do_fsmove( FPU registers[reg], src );
|
||||
build_ex_status();
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdmove( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDMOVE %s\r\n",etos(src)));
|
||||
do_fdmove( FPU registers[reg], src );
|
||||
build_ex_status();
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fssqrt( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSSQRT %s\r\n",etos(src)));
|
||||
do_fssqrt( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdsqrt( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDSQRT %s\r\n",etos(src)));
|
||||
do_fdsqrt( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsabs( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSABS %s\r\n",etos(src)));
|
||||
do_fsabs( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdabs( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDABS %s\r\n",etos(src)));
|
||||
do_fdabs( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsneg( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSNEG %s\r\n",etos(src)));
|
||||
do_fsneg( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdneg( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDNEG %s\r\n",etos(src)));
|
||||
do_fdneg( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsdiv( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSDIV %s\r\n",etos(src)));
|
||||
do_fsdiv( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fddiv( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDDIV %s\r\n",etos(src)));
|
||||
do_fddiv( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsadd( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSADD %s\r\n",etos(src)));
|
||||
do_fsadd( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdadd( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDADD %s\r\n",etos(src)));
|
||||
do_fdadd( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fssub( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSSUB %s\r\n",etos(src)));
|
||||
do_fssub( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdsub( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDSUB %s\r\n",etos(src)));
|
||||
do_fdsub( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsmul( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSMUL %s\r\n",etos(src)));
|
||||
do_fsmul( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdmul( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSMUL %s\r\n",etos(src)));
|
||||
do_fsmul( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
/* ---------------------------- ALU ---------------------------- */
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra )
|
||||
|
@ -6326,61 +5744,6 @@ PRIVATE void FFPU build_fpp_opp_lookup_table ()
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (FPU is_integral) {
|
||||
switch (extra & 0x7f) {
|
||||
case 0x40:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fsmove;
|
||||
break;
|
||||
case 0x44:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdmove;
|
||||
break;
|
||||
case 0x41:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fssqrt;
|
||||
break;
|
||||
case 0x45:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdsqrt;
|
||||
break;
|
||||
case 0x58:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fsabs;
|
||||
break;
|
||||
case 0x5c:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdabs;
|
||||
break;
|
||||
case 0x5a:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fsneg;
|
||||
break;
|
||||
case 0x5e:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdneg;
|
||||
break;
|
||||
case 0x60:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fsdiv;
|
||||
break;
|
||||
case 0x64:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fddiv;
|
||||
break;
|
||||
case 0x62:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fsadd;
|
||||
break;
|
||||
case 0x66:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdadd;
|
||||
break;
|
||||
case 0x68:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fssub;
|
||||
break;
|
||||
case 0x6c:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdsub;
|
||||
break;
|
||||
case 0x63:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fsmul;
|
||||
break;
|
||||
case 0x67:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdmul;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (extra & 0x7f) {
|
||||
case 0x00:
|
||||
|
@ -6670,26 +6033,6 @@ PRIVATE void FFPU do_fld1 ( fpu_register & dest )
|
|||
}
|
||||
|
||||
|
||||
void fpu_set_fpsr(uae_u32 new_fpsr)
|
||||
{
|
||||
set_fpsr(new_fpsr);
|
||||
}
|
||||
|
||||
uae_u32 fpu_get_fpsr(void)
|
||||
{
|
||||
return get_fpsr();
|
||||
}
|
||||
|
||||
void fpu_set_fpcr(uae_u32 new_fpcr)
|
||||
{
|
||||
set_fpcr(new_fpcr);
|
||||
}
|
||||
|
||||
uae_u32 fpu_get_fpcr(void)
|
||||
{
|
||||
return get_fpcr();
|
||||
}
|
||||
|
||||
/* ---------------------------- MAIN INIT ---------------------------- */
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
|
@ -6741,10 +6084,6 @@ PUBLIC void FFPU fpu_init( bool integral_68040 )
|
|||
|
||||
build_fpp_opp_lookup_table();
|
||||
|
||||
/* _asm {
|
||||
FNINIT
|
||||
FLDCW x86_control_word
|
||||
} */
|
||||
__asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word));
|
||||
|
||||
do_fldpi( const_pi );
|
||||
|
@ -6772,10 +6111,6 @@ PUBLIC void FFPU fpu_init( bool integral_68040 )
|
|||
set_constant( const_1e4096, "1.0e4096", 1.0e256, 10000 );
|
||||
|
||||
// Just in case.
|
||||
/* _asm {
|
||||
FNINIT
|
||||
FLDCW x86_control_word
|
||||
} */
|
||||
__asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core
|
||||
* fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_X86_H
|
||||
|
@ -99,17 +94,17 @@ PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void);
|
|||
PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name);
|
||||
|
||||
// Get special floating-point value class
|
||||
PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f);
|
||||
PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f);
|
||||
PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f);
|
||||
PRIVATE inline uae_u32 FFPU IS_NEGATIVE (fpu_register const & f);
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f);
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f);
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f);
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f);
|
||||
|
||||
// Make a special floating-point value
|
||||
PRIVATE inline void FFPU MAKE_NAN (fpu_register & f);
|
||||
PRIVATE inline void FFPU MAKE_INF_POSITIVE (fpu_register & f);
|
||||
PRIVATE inline void FFPU MAKE_INF_NEGATIVE (fpu_register & f);
|
||||
PRIVATE inline void FFPU MAKE_ZERO_POSITIVE (fpu_register & f);
|
||||
PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f);
|
||||
PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f);
|
||||
PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f);
|
||||
PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f);
|
||||
PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f);
|
||||
PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f);
|
||||
|
||||
// Conversion from extended floating-point values
|
||||
PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) REGPARAM;
|
||||
|
@ -347,24 +342,6 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fsincos( uae_u32 opcode, uae_u32 extra );
|
|||
PRIVATE void REGPARAM2 FFPU fpuop_do_fcmp( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( uae_u32 opcode, uae_u32 extra );
|
||||
|
||||
// 040
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsmove( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdmove( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fssqrt( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdsqrt( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsabs( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdabs( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsneg( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdneg( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsdiv( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fddiv( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsadd( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdadd( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fssub( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdsub( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsmul( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdmul( uae_u32 opcode, uae_u32 extra );
|
||||
|
||||
// Get & Put floating-point values
|
||||
PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) REGPARAM;
|
||||
PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra) REGPARAM;
|
||||
|
@ -374,9 +351,9 @@ PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) REGPARAM;
|
|||
PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) REGPARAM;
|
||||
|
||||
// Misc functions
|
||||
PRIVATE void inline FFPU set_host_fpu_control_word ();
|
||||
PRIVATE void inline FFPU SET_BSUN_ON_NAN ();
|
||||
PRIVATE void inline FFPU build_ex_status ();
|
||||
PRIVATE void __inline__ FFPU set_host_fpu_control_word ();
|
||||
PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN ();
|
||||
PRIVATE void __inline__ FFPU build_ex_status ();
|
||||
PRIVATE void FFPU do_null_frestore ();
|
||||
PRIVATE void FFPU build_fpp_opp_lookup_table ();
|
||||
PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult );
|
||||
|
|
|
@ -1,35 +1,3 @@
|
|||
/*
|
||||
* fpu/fpu_x86_asm.h - Extra Definitions for the X86 assembly FPU core
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define DEFINE_X86_MACRO(name, value) \
|
||||
asm(".local " #name "\n\t" #name " = " #value)
|
||||
|
||||
|
|
|
@ -1,38 +1,28 @@
|
|||
/*
|
||||
* fpu/impl.h - extra functions and inline implementations
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_IMPL_H
|
||||
|
@ -113,8 +103,7 @@ static inline uae_u32 FFPU get_fpcr(void)
|
|||
{
|
||||
uae_u32 rounding_precision = get_rounding_precision();
|
||||
uae_u32 rounding_mode = get_rounding_mode();
|
||||
uae_u32 exception_enable = FPU fpcr.exception_enable;
|
||||
return (rounding_precision | rounding_mode | exception_enable);
|
||||
return (rounding_precision | rounding_mode);
|
||||
}
|
||||
|
||||
/* Set the floating-point control register from an m68k format */
|
||||
|
@ -123,7 +112,6 @@ static inline void FFPU set_fpcr(uae_u32 new_fpcr)
|
|||
set_rounding_precision ( new_fpcr & FPCR_ROUNDING_PRECISION);
|
||||
set_rounding_mode ( new_fpcr & FPCR_ROUNDING_MODE );
|
||||
set_host_control_word();
|
||||
FPU fpcr.exception_enable = new_fpcr & FPCR_EXCEPTION_ENABLE;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/mathlib.cpp - Floating-point math support library
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/mathlib.h - Floating-point math support library
|
||||
* fpu/mathlib.h - Floating-point math support library
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_MATHLIB_H
|
||||
|
@ -56,16 +51,20 @@
|
|||
|
||||
// NOTE: this is irrelevant on Win32 platforms since the MS libraries
|
||||
// don't support extended-precision floating-point computations
|
||||
#ifdef WIN32
|
||||
#if defined(WIN32) && USE_LONG_DOUBLE
|
||||
#undef FPU_USE_ISO_C99
|
||||
#endif
|
||||
|
||||
// Use faster implementation of math functions, but this could cause
|
||||
// some incorrect results (?)
|
||||
// TODO: actually implement the slower but safer versions
|
||||
#ifdef _MSC_VER
|
||||
// MSVC uses intrinsics for all of the math functions, so it should still be fast
|
||||
#define FPU_FAST_MATH 0
|
||||
#else
|
||||
#define FPU_FAST_MATH 1
|
||||
#endif
|
||||
|
||||
#if defined(FPU_USE_ISO_C99)
|
||||
#if FPU_USE_ISO_C99
|
||||
// NOTE: no prior <math.h> shall be included at this point
|
||||
#define __USE_ISOC99 1 // for glibc 2.2.X and newer
|
||||
#define __USE_ISOC9X 1 // for glibc 2.1.X
|
||||
|
@ -148,7 +147,7 @@ union fpu_double_shape {
|
|||
unsigned int mantissa0:20;
|
||||
unsigned int mantissa1:32;
|
||||
#else
|
||||
# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
# if HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
unsigned int mantissa0:20;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
|
@ -173,7 +172,7 @@ union fpu_double_shape {
|
|||
unsigned int mantissa0:19;
|
||||
unsigned int mantissa1:32;
|
||||
#else
|
||||
# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
# if HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
unsigned int mantissa0:19;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int exponent:11;
|
||||
|
@ -192,7 +191,7 @@ union fpu_double_shape {
|
|||
|
||||
/* This format is used to extract the sign_exponent and mantissa parts only */
|
||||
struct {
|
||||
#if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
#if HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
unsigned int msw:32;
|
||||
unsigned int lsw:32;
|
||||
#else
|
||||
|
@ -216,7 +215,7 @@ union fpu_extended_shape {
|
|||
unsigned int mantissa0:32;
|
||||
unsigned int mantissa1:32;
|
||||
#else
|
||||
# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
# if HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
unsigned int exponent:15;
|
||||
unsigned int negative:1;
|
||||
unsigned int empty:16;
|
||||
|
@ -243,7 +242,7 @@ union fpu_extended_shape {
|
|||
unsigned int mantissa0:30;
|
||||
unsigned int mantissa1:32;
|
||||
#else
|
||||
# if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
# if HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
unsigned int exponent:15;
|
||||
unsigned int negative:1;
|
||||
unsigned int empty:16;
|
||||
|
@ -265,7 +264,7 @@ union fpu_extended_shape {
|
|||
|
||||
/* This format is used to extract the sign_exponent and mantissa parts only */
|
||||
struct {
|
||||
#if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
#if HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
unsigned int sign_exponent:16;
|
||||
unsigned int empty:16;
|
||||
unsigned int msw:32;
|
||||
|
@ -311,7 +310,7 @@ union fpu_extended_shape {
|
|||
unsigned int exponent:15;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int mantissa0:15;
|
||||
unsigned int mantissa1:32;
|
||||
unsigned int mantissa1:30;
|
||||
unsigned int mantissa2:32;
|
||||
unsigned int mantissa3:32;
|
||||
#else
|
||||
|
@ -326,7 +325,7 @@ union fpu_extended_shape {
|
|||
} ieee_nan;
|
||||
|
||||
/* This format is used to extract the sign_exponent and mantissa parts only */
|
||||
#if defined(HOST_FLOAT_WORDS_BIG_ENDIAN) && HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
#if HOST_FLOAT_WORDS_BIG_ENDIAN
|
||||
struct {
|
||||
uae_u64 msw;
|
||||
uae_u64 lsw;
|
||||
|
@ -352,9 +351,9 @@ union fpu_extended_shape {
|
|||
};
|
||||
#endif
|
||||
|
||||
// Declare a shape of the requested FP type
|
||||
#define fp_declare_init_shape(psvar, ftype) \
|
||||
fpu_ ## ftype ## _shape psvar
|
||||
// Declare and initialize a pointer to a shape of the requested FP type
|
||||
#define fp_declare_init_shape(psvar, rfvar, ftype) \
|
||||
fpu_ ## ftype ## _shape * psvar = (fpu_ ## ftype ## _shape *)( &rfvar )
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- Extra Math Functions --- */
|
||||
|
@ -371,51 +370,47 @@ union fpu_extended_shape {
|
|||
PRIVATE inline bool FFPU fp_do_isnan(fpu_register const & r)
|
||||
{
|
||||
#ifdef BRANCHES_ARE_EXPENSIVE
|
||||
#if !defined(USE_LONG_DOUBLE)
|
||||
fp_declare_init_shape(sxp, double);
|
||||
sxp.value = r;
|
||||
uae_s32 hx = sxp.parts.msw;
|
||||
uae_s32 lx = sxp.parts.lsw;
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
uae_s32 hx = sxp->parts.msw;
|
||||
uae_s32 lx = sxp->parts.lsw;
|
||||
hx &= 0x7fffffff;
|
||||
hx |= (uae_u32)(lx | (-lx)) >> 31;
|
||||
hx = 0x7ff00000 - hx;
|
||||
return (int)(((uae_u32)hx) >> 31);
|
||||
#elif defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
sxp.value = r;
|
||||
uae_s64 hx = sxp.parts64.msw;
|
||||
uae_s64 lx = sxp.parts64.lsw;
|
||||
return (((uae_u32)hx) >> 31) != 0;
|
||||
#elif USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
uae_s64 hx = sxp->parts64.msw;
|
||||
uae_s64 lx = sxp->parts64.lsw;
|
||||
hx &= 0x7fffffffffffffffLL;
|
||||
hx |= (uae_u64)(lx | (-lx)) >> 63;
|
||||
hx = 0x7fff000000000000LL - hx;
|
||||
return (int)((uae_u64)hx >> 63);
|
||||
return ((uae_u64)hx >> 63) != 0;
|
||||
#else
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
sxp.value = r;
|
||||
uae_s32 se = sxp.parts.sign_exponent;
|
||||
uae_s32 hx = sxp.parts.msw;
|
||||
uae_s32 lx = sxp.parts.lsw;
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
uae_s32 se = sxp->parts.sign_exponent;
|
||||
uae_s32 hx = sxp->parts.msw;
|
||||
uae_s32 lx = sxp->parts.lsw;
|
||||
se = (se & 0x7fff) << 1;
|
||||
lx |= hx & 0x7fffffff;
|
||||
se |= (uae_u32)(lx | (-lx)) >> 31;
|
||||
se = 0xfffe - se;
|
||||
return (int)(((uae_u32)(se)) >> 31);
|
||||
// TODO: check whether rshift count is 16 or 31
|
||||
return (((uae_u32)(se)) >> 16) != 0;
|
||||
#endif
|
||||
#else
|
||||
#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
sxp.value = r;
|
||||
return (sxp.ieee_nan.exponent == FP_EXTENDED_EXP_MAX)
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
return (sxp->ieee_nan.exponent == FP_EXTENDED_EXP_MAX)
|
||||
#else
|
||||
fp_declare_init_shape(sxp, double);
|
||||
sxp.value = r;
|
||||
return (sxp.ieee_nan.exponent == FP_DOUBLE_EXP_MAX)
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
return (sxp->ieee_nan.exponent == FP_DOUBLE_EXP_MAX)
|
||||
#endif
|
||||
&& (sxp.ieee_nan.mantissa0 != 0)
|
||||
&& (sxp.ieee_nan.mantissa1 != 0)
|
||||
&& (sxp->ieee_nan.mantissa0 != 0)
|
||||
&& (sxp->ieee_nan.mantissa1 != 0)
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
&& (sxp.ieee_nan.mantissa2 != 0)
|
||||
&& (sxp.ieee_nan.mantissa3 != 0)
|
||||
&& (sxp->ieee_nan.mantissa2 != 0)
|
||||
&& (sxp->ieee_nan.mantissa3 != 0)
|
||||
#endif
|
||||
;
|
||||
#endif
|
||||
|
@ -431,55 +426,50 @@ PRIVATE inline bool FFPU fp_do_isnan(fpu_register const & r)
|
|||
PRIVATE inline bool FFPU fp_do_isinf(fpu_register const & r)
|
||||
{
|
||||
#ifdef BRANCHES_ARE_EXPENSIVE
|
||||
#if !defined(USE_LONG_DOUBLE)
|
||||
fp_declare_init_shape(sxp, double);
|
||||
sxp.value = r;
|
||||
uae_s32 hx = sxp.parts.msw;
|
||||
uae_s32 lx = sxp.parts.lsw;
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
uae_s32 hx = sxp->parts.msw;
|
||||
uae_s32 lx = sxp->parts.lsw;
|
||||
lx |= (hx & 0x7fffffff) ^ 0x7ff00000;
|
||||
lx |= -lx;
|
||||
return ~(lx >> 31) & (hx >> 30);
|
||||
#elif defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
sxp.value = r;
|
||||
uae_s64 hx = sxp.parts64.msw;
|
||||
uae_s64 lx = sxp.parts64.lsw;
|
||||
return (~(lx >> 31) & (hx >> 30)) != 0;
|
||||
#elif USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
uae_s64 hx = sxp->parts64.msw;
|
||||
uae_s64 lx = sxp->parts64.lsw;
|
||||
lx |= (hx & 0x7fffffffffffffffLL) ^ 0x7fff000000000000LL;
|
||||
lx |= -lx;
|
||||
return ~(lx >> 63) & (hx >> 62);
|
||||
return (~(lx >> 63) & (hx >> 62)) != 0;
|
||||
#else
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
sxp.value = r;
|
||||
uae_s32 se = sxp.parts.sign_exponent;
|
||||
uae_s32 hx = sxp.parts.msw;
|
||||
uae_s32 lx = sxp.parts.lsw;
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
uae_s32 se = sxp->parts.sign_exponent;
|
||||
uae_s32 hx = sxp->parts.msw;
|
||||
uae_s32 lx = sxp->parts.lsw;
|
||||
/* This additional ^ 0x80000000 is necessary because in Intel's
|
||||
internal representation of the implicit one is explicit.
|
||||
NOTE: anyway, this is equivalent to & 0x7fffffff in that case. */
|
||||
#ifdef CPU_i386
|
||||
#ifdef __i386__
|
||||
lx |= (hx ^ 0x80000000) | ((se & 0x7fff) ^ 0x7fff);
|
||||
#else
|
||||
lx |= (hx & 0x7fffffff) | ((se & 0x7fff) ^ 0x7fff);
|
||||
#endif
|
||||
lx |= -lx;
|
||||
se &= 0x8000;
|
||||
return ~(lx >> 31) & (1 - (se >> 14));
|
||||
return (~(lx >> 31) & (1 - (se >> 14))) != 0;
|
||||
#endif
|
||||
#else
|
||||
#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
sxp.value = r;
|
||||
return (sxp.ieee_nan.exponent == FP_EXTENDED_EXP_MAX)
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
return (sxp->ieee_nan.exponent == FP_EXTENDED_EXP_MAX)
|
||||
#else
|
||||
fp_declare_init_shape(sxp, double);
|
||||
sxp.value = r;
|
||||
return (sxp.ieee_nan.exponent == FP_DOUBLE_EXP_MAX)
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
return (sxp->ieee_nan.exponent == FP_DOUBLE_EXP_MAX)
|
||||
#endif
|
||||
&& (sxp.ieee_nan.mantissa0 == 0)
|
||||
&& (sxp.ieee_nan.mantissa1 == 0)
|
||||
&& (sxp->ieee_nan.mantissa0 == 0)
|
||||
&& (sxp->ieee_nan.mantissa1 == 0)
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
&& (sxp.ieee_nan.mantissa2 == 0)
|
||||
&& (sxp.ieee_nan.mantissa3 == 0)
|
||||
&& (sxp->ieee_nan.mantissa2 == 0)
|
||||
&& (sxp->ieee_nan.mantissa3 == 0)
|
||||
#endif
|
||||
;
|
||||
#endif
|
||||
|
@ -490,13 +480,12 @@ PRIVATE inline bool FFPU fp_do_isinf(fpu_register const & r)
|
|||
|
||||
PRIVATE inline bool FFPU fp_do_isneg(fpu_register const & r)
|
||||
{
|
||||
#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
#else
|
||||
fp_declare_init_shape(sxp, double);
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
#endif
|
||||
sxp.value = r;
|
||||
return sxp.ieee.negative;
|
||||
return sxp->ieee.negative;
|
||||
}
|
||||
|
||||
#undef iszero
|
||||
|
@ -505,18 +494,17 @@ PRIVATE inline bool FFPU fp_do_isneg(fpu_register const & r)
|
|||
PRIVATE inline bool FFPU fp_do_iszero(fpu_register const & r)
|
||||
{
|
||||
// TODO: BRANCHES_ARE_EXPENSIVE
|
||||
#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
#else
|
||||
fp_declare_init_shape(sxp, double);
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
#endif
|
||||
sxp.value = r;
|
||||
return (sxp.ieee.exponent == 0)
|
||||
&& (sxp.ieee.mantissa0 == 0)
|
||||
&& (sxp.ieee.mantissa1 == 0)
|
||||
return (sxp->ieee.exponent == 0)
|
||||
&& (sxp->ieee.mantissa0 == 0)
|
||||
&& (sxp->ieee.mantissa1 == 0)
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
&& (sxp.ieee.mantissa2 == 0)
|
||||
&& (sxp.ieee.mantissa3 == 0)
|
||||
&& (sxp->ieee.mantissa2 == 0)
|
||||
&& (sxp->ieee.mantissa3 == 0)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
@ -541,21 +529,21 @@ PRIVATE inline void FFPU get_source_flags(fpu_register const & r)
|
|||
|
||||
PRIVATE inline void FFPU make_nan(fpu_register & r)
|
||||
{
|
||||
#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
sxp.ieee.exponent = FP_EXTENDED_EXP_MAX;
|
||||
sxp.ieee.mantissa0 = 0xffffffff;
|
||||
// FIXME: is that correct ?
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
sxp->ieee.exponent = FP_EXTENDED_EXP_MAX;
|
||||
sxp->ieee.mantissa0 = 0xffffffff;
|
||||
#else
|
||||
fp_declare_init_shape(sxp, double);
|
||||
sxp.ieee.exponent = FP_DOUBLE_EXP_MAX;
|
||||
sxp.ieee.mantissa0 = 0xfffff;
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
sxp->ieee.exponent = FP_DOUBLE_EXP_MAX;
|
||||
sxp->ieee.mantissa0 = 0xfffff;
|
||||
#endif
|
||||
sxp.ieee.mantissa1 = 0xffffffff;
|
||||
sxp->ieee.mantissa1 = 0xffffffff;
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
sxp.ieee.mantissa2 = 0xffffffff;
|
||||
sxp.ieee.mantissa3 = 0xffffffff;
|
||||
sxp->ieee.mantissa2 = 0xffffffff;
|
||||
sxp->ieee.mantissa3 = 0xffffffff;
|
||||
#endif
|
||||
r = sxp.value;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU make_zero_positive(fpu_register & r)
|
||||
|
@ -563,20 +551,19 @@ PRIVATE inline void FFPU make_zero_positive(fpu_register & r)
|
|||
#if 1
|
||||
r = +0.0;
|
||||
#else
|
||||
#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
#else
|
||||
fp_declare_init_shape(sxp, double);
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
#endif
|
||||
sxp.ieee.negative = 0;
|
||||
sxp.ieee.exponent = 0;
|
||||
sxp.ieee.mantissa0 = 0;
|
||||
sxp.ieee.mantissa1 = 0;
|
||||
sxp->ieee.negative = 0;
|
||||
sxp->ieee.exponent = 0;
|
||||
sxp->ieee.mantissa0 = 0;
|
||||
sxp->ieee.mantissa1 = 0;
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
sxp.ieee.mantissa2 = 0;
|
||||
sxp.ieee.mantissa3 = 0;
|
||||
sxp->ieee.mantissa2 = 0;
|
||||
sxp->ieee.mantissa3 = 0;
|
||||
#endif
|
||||
r = sxp.value;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -585,110 +572,101 @@ PRIVATE inline void FFPU make_zero_negative(fpu_register & r)
|
|||
#if 1
|
||||
r = -0.0;
|
||||
#else
|
||||
#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
#else
|
||||
fp_declare_init_shape(sxp, double);
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
#endif
|
||||
sxp.ieee.negative = 1;
|
||||
sxp.ieee.exponent = 0;
|
||||
sxp.ieee.mantissa0 = 0;
|
||||
sxp.ieee.mantissa1 = 0;
|
||||
sxp->ieee.negative = 1;
|
||||
sxp->ieee.exponent = 0;
|
||||
sxp->ieee.mantissa0 = 0;
|
||||
sxp->ieee.mantissa1 = 0;
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
sxp.ieee.mantissa2 = 0;
|
||||
sxp.ieee.mantissa3 = 0;
|
||||
sxp->ieee.mantissa2 = 0;
|
||||
sxp->ieee.mantissa3 = 0;
|
||||
#endif
|
||||
r = sxp.value;
|
||||
#endif
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU make_inf_positive(fpu_register & r)
|
||||
{
|
||||
#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
sxp.ieee_nan.exponent = FP_EXTENDED_EXP_MAX;
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX;
|
||||
#else
|
||||
fp_declare_init_shape(sxp, double);
|
||||
sxp.ieee_nan.exponent = FP_DOUBLE_EXP_MAX;
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX;
|
||||
#endif
|
||||
sxp.ieee_nan.negative = 0;
|
||||
sxp.ieee_nan.mantissa0 = 0;
|
||||
sxp.ieee_nan.mantissa1 = 0;
|
||||
sxp->ieee_nan.negative = 0;
|
||||
sxp->ieee_nan.mantissa0 = 0;
|
||||
sxp->ieee_nan.mantissa1 = 0;
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
sxp.ieee_nan.mantissa2 = 0;
|
||||
sxp.ieee_nan.mantissa3 = 0;
|
||||
sxp->ieee_nan.mantissa2 = 0;
|
||||
sxp->ieee_nan.mantissa3 = 0;
|
||||
#endif
|
||||
r = sxp.value;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU make_inf_negative(fpu_register & r)
|
||||
{
|
||||
#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
sxp.ieee_nan.exponent = FP_EXTENDED_EXP_MAX;
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX;
|
||||
#else
|
||||
fp_declare_init_shape(sxp, double);
|
||||
sxp.ieee_nan.exponent = FP_DOUBLE_EXP_MAX;
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX;
|
||||
#endif
|
||||
sxp.ieee_nan.negative = 1;
|
||||
sxp.ieee_nan.mantissa0 = 0;
|
||||
sxp.ieee_nan.mantissa1 = 0;
|
||||
sxp->ieee_nan.negative = 1;
|
||||
sxp->ieee_nan.mantissa0 = 0;
|
||||
sxp->ieee_nan.mantissa1 = 0;
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
sxp.ieee_nan.mantissa2 = 0;
|
||||
sxp.ieee_nan.mantissa3 = 0;
|
||||
sxp->ieee_nan.mantissa2 = 0;
|
||||
sxp->ieee_nan.mantissa3 = 0;
|
||||
#endif
|
||||
r = sxp.value;
|
||||
}
|
||||
|
||||
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r)
|
||||
{
|
||||
#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
sxp.value = r;
|
||||
return ((int) sxp.ieee.exponent - FP_EXTENDED_EXP_BIAS);
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
return (sxp->ieee.exponent - FP_EXTENDED_EXP_BIAS);
|
||||
#else
|
||||
fp_declare_init_shape(sxp, double);
|
||||
sxp.value = r;
|
||||
return ((int) sxp.ieee.exponent - FP_DOUBLE_EXP_BIAS);
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
return (sxp->ieee.exponent - FP_DOUBLE_EXP_BIAS);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Normalize to range 1..2
|
||||
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r)
|
||||
{
|
||||
#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
sxp.value = r;
|
||||
sxp.ieee.exponent = FP_EXTENDED_EXP_BIAS;
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
sxp->ieee.exponent = FP_EXTENDED_EXP_BIAS;
|
||||
#else
|
||||
fp_declare_init_shape(sxp, double);
|
||||
sxp.value = r;
|
||||
sxp.ieee.exponent = FP_DOUBLE_EXP_BIAS;
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
sxp->ieee.exponent = FP_DOUBLE_EXP_BIAS;
|
||||
#endif
|
||||
r = sxp.value;
|
||||
}
|
||||
|
||||
// The sign of the quotient is the exclusive-OR of the sign bits
|
||||
// of the source and destination operands.
|
||||
PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb)
|
||||
{
|
||||
#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sap, extended);
|
||||
fp_declare_init_shape(sbp, extended);
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sap, ra, extended);
|
||||
fp_declare_init_shape(sbp, rb, extended);
|
||||
#else
|
||||
fp_declare_init_shape(sap, double);
|
||||
fp_declare_init_shape(sbp, double);
|
||||
fp_declare_init_shape(sap, ra, double);
|
||||
fp_declare_init_shape(sbp, rb, double);
|
||||
#endif
|
||||
sap.value = ra;
|
||||
sbp.value = rb;
|
||||
return ((sap.ieee.negative ^ sbp.ieee.negative) ? FPSR_QUOTIENT_SIGN : 0);
|
||||
return ((sap->ieee.negative ^ sbp->ieee.negative) ? FPSR_QUOTIENT_SIGN : 0);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- Math functions --- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#if defined(FPU_USE_ISO_C99) && (defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE))
|
||||
#if FPU_USE_ISO_C99
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
# ifdef HAVE_LOGL
|
||||
# define fp_log logl
|
||||
# endif
|
||||
|
@ -812,14 +790,13 @@ PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_regis
|
|||
# define fp_ceil ceil
|
||||
#endif
|
||||
|
||||
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)
|
||||
#elif defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)
|
||||
// Assembly optimized support functions. Taken from glibc 2.2.2
|
||||
|
||||
#undef fp_log
|
||||
#define fp_log fp_do_log
|
||||
|
||||
#ifndef FPU_FAST_MATH
|
||||
// FIXME: unimplemented
|
||||
#if !FPU_FAST_MATH
|
||||
PRIVATE fpu_extended fp_do_log(fpu_extended x);
|
||||
#else
|
||||
PRIVATE inline fpu_extended fp_do_log(fpu_extended x)
|
||||
|
@ -833,7 +810,7 @@ PRIVATE inline fpu_extended fp_do_log(fpu_extended x)
|
|||
#undef fp_log10
|
||||
#define fp_log10 fp_do_log10
|
||||
|
||||
#ifndef FPU_FAST_MATH
|
||||
#if !FPU_FAST_MATH
|
||||
// FIXME: unimplemented
|
||||
PRIVATE fpu_extended fp_do_log10(fpu_extended x);
|
||||
#else
|
||||
|
@ -848,20 +825,13 @@ PRIVATE inline fpu_extended fp_do_log10(fpu_extended x)
|
|||
#undef fp_exp
|
||||
#define fp_exp fp_do_exp
|
||||
|
||||
#ifndef FPU_FAST_MATH
|
||||
#if !FPU_FAST_MATH
|
||||
// FIXME: unimplemented
|
||||
PRIVATE fpu_extended fp_do_exp(fpu_extended x);
|
||||
#else
|
||||
PRIVATE inline fpu_extended fp_do_exp(fpu_extended x)
|
||||
{
|
||||
fpu_extended value, exponent;
|
||||
if (isinf(x))
|
||||
{
|
||||
if(isneg(x))
|
||||
return 0.;
|
||||
else
|
||||
return x;
|
||||
}
|
||||
__asm__ __volatile__("fldl2e # e^x = 2^(x * log2(e))\n\t"
|
||||
"fmul %%st(1) # x * log2(e)\n\t"
|
||||
"fst %%st(1)\n\t"
|
||||
|
@ -901,7 +871,6 @@ PRIVATE inline fpu_extended fp_do_sqrt(fpu_extended x)
|
|||
return value;
|
||||
}
|
||||
|
||||
#ifndef ACCURATE_SIN_COS_TAN
|
||||
#undef fp_sin
|
||||
#define fp_sin fp_do_sin
|
||||
|
||||
|
@ -927,11 +896,10 @@ PRIVATE inline fpu_extended fp_do_cos(fpu_extended x)
|
|||
|
||||
PRIVATE inline fpu_extended fp_do_tan(fpu_extended x)
|
||||
{
|
||||
fpu_extended value, value2;
|
||||
__asm__ __volatile__("fptan" : "=t" (value2), "=u" (value) : "0" (x));
|
||||
fpu_extended value;
|
||||
__asm__ __volatile__("fptan" : "=t" (value) : "0" (x));
|
||||
return value;
|
||||
}
|
||||
#endif /* ACCURATE_SIN_COS_TAN */
|
||||
|
||||
#undef fp_expm1
|
||||
#define fp_expm1 fp_do_expm1
|
||||
|
@ -939,14 +907,7 @@ PRIVATE inline fpu_extended fp_do_tan(fpu_extended x)
|
|||
// Returns: exp(X) - 1.0
|
||||
PRIVATE inline fpu_extended fp_do_expm1(fpu_extended x)
|
||||
{
|
||||
fpu_extended value, exponent, temp, temp2;
|
||||
if (isinf(x))
|
||||
{
|
||||
if(isneg(x))
|
||||
return -1.;
|
||||
else
|
||||
return x;
|
||||
}
|
||||
fpu_extended value, exponent, temp;
|
||||
__asm__ __volatile__("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t"
|
||||
"fmul %%st(1) # x * log2(e)\n\t"
|
||||
"fst %%st(1)\n\t"
|
||||
|
@ -956,9 +917,7 @@ PRIVATE inline fpu_extended fp_do_expm1(fpu_extended x)
|
|||
"f2xm1 # 2^(fract(x * log2(e))) - 1\n\t"
|
||||
"fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t"
|
||||
: "=t" (value), "=u" (exponent) : "0" (x));
|
||||
__asm__ __volatile__("fld1 \n\t"
|
||||
"fscale \n\t"
|
||||
: "=t" (temp), "=u" (temp2) : "0" (exponent));
|
||||
__asm__ __volatile__("fscale" : "=t" (temp) : "0" (1.0), "u" (exponent));
|
||||
temp -= 1.0;
|
||||
return temp + value ? temp + value : x;
|
||||
}
|
||||
|
@ -968,33 +927,29 @@ PRIVATE inline fpu_extended fp_do_expm1(fpu_extended x)
|
|||
|
||||
PRIVATE inline fpu_extended fp_do_sgn1(fpu_extended x)
|
||||
{
|
||||
#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE)
|
||||
fp_declare_init_shape(sxp, extended);
|
||||
sxp.value = x;
|
||||
sxp.ieee_nan.exponent = FP_EXTENDED_EXP_MAX>>1;
|
||||
sxp.ieee_nan.one = 1;
|
||||
#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, x, extended);
|
||||
sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX;
|
||||
sxp->ieee_nan.one = 1;
|
||||
#else
|
||||
fp_declare_init_shape(sxp, double);
|
||||
sxp.value = x;
|
||||
sxp.ieee_nan.exponent = FP_DOUBLE_EXP_MAX>>1;
|
||||
fp_declare_init_shape(sxp, x, double);
|
||||
sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX;
|
||||
#endif
|
||||
sxp.ieee_nan.quiet_nan = 0;
|
||||
sxp.ieee_nan.mantissa0 = 0;
|
||||
sxp.ieee_nan.mantissa1 = 0;
|
||||
x = sxp.value;
|
||||
sxp->ieee_nan.quiet_nan = 0;
|
||||
sxp->ieee_nan.mantissa0 = 0;
|
||||
sxp->ieee_nan.mantissa1 = 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
#undef fp_sinh
|
||||
#define fp_sinh fp_do_sinh
|
||||
|
||||
#ifndef FPU_FAST_MATH
|
||||
#if !FPU_FAST_MATH
|
||||
// FIXME: unimplemented
|
||||
PRIVATE fpu_extended fp_do_sinh(fpu_extended x);
|
||||
#else
|
||||
PRIVATE inline fpu_extended fp_do_sinh(fpu_extended x)
|
||||
{
|
||||
if (isinf(x)) return x;
|
||||
fpu_extended exm1 = fp_expm1(fp_fabs(x));
|
||||
return 0.5 * (exm1 / (exm1 + 1.0) + exm1) * fp_sgn1(x);
|
||||
}
|
||||
|
@ -1003,7 +958,7 @@ PRIVATE inline fpu_extended fp_do_sinh(fpu_extended x)
|
|||
#undef fp_cosh
|
||||
#define fp_cosh fp_do_cosh
|
||||
|
||||
#ifndef FPU_FAST_MATH
|
||||
#if !FPU_FAST_MATH
|
||||
// FIXME: unimplemented
|
||||
PRIVATE fpu_extended fp_do_cosh(fpu_extended x);
|
||||
#else
|
||||
|
@ -1017,7 +972,7 @@ PRIVATE inline fpu_extended fp_do_cosh(fpu_extended x)
|
|||
#undef fp_tanh
|
||||
#define fp_tanh fp_do_tanh
|
||||
|
||||
#ifndef FPU_FAST_MATH
|
||||
#if !FPU_FAST_MATH
|
||||
// FIXME: unimplemented
|
||||
PRIVATE fpu_extended fp_do_tanh(fpu_extended x);
|
||||
#else
|
||||
|
@ -1096,46 +1051,48 @@ PRIVATE inline fpu_extended fp_do_atanh(fpu_extended x)
|
|||
return -0.5 * fp_log1p(-(y + y) / (1.0 + y)) * fp_sgn1(x);
|
||||
}
|
||||
|
||||
#undef fp_floor
|
||||
#define fp_floor fp_do_floor
|
||||
|
||||
/*
|
||||
* LLVM 2.9 crashes on first definition,
|
||||
* clang with LLVM 3.x crashes on 2nd definition... sigh
|
||||
*/
|
||||
#if defined(__clang__) || !defined(__llvm__)
|
||||
#define DEFINE_ROUND_FUNC(rounding_mode_str, rounding_mode) \
|
||||
PRIVATE inline fpu_extended fp_do_round_to_ ## rounding_mode_str(fpu_extended __x) \
|
||||
{ \
|
||||
register long double __value; \
|
||||
register int __ignore; \
|
||||
volatile unsigned short __cw; \
|
||||
volatile unsigned short __cwtmp; \
|
||||
__asm __volatile ("fnstcw %3\n\t" \
|
||||
"movzwl %3, %1\n\t" \
|
||||
"andl $0xf3ff, %1\n\t" \
|
||||
"orl %5, %1\n\t" \
|
||||
"movw %w1, %2\n\t" \
|
||||
"fldcw %2\n\t" \
|
||||
"frndint\n\t" \
|
||||
"fldcw %3" \
|
||||
: "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \
|
||||
"=m" (__cw) \
|
||||
: "0" (__x), "i"(rounding_mode)); \
|
||||
return __value; \
|
||||
PRIVATE inline fpu_extended fp_do_floor(fpu_extended x)
|
||||
{
|
||||
volatile unsigned int cw;
|
||||
__asm__ __volatile__("fnstcw %0" : "=m" (cw));
|
||||
volatile unsigned int cw_temp = (cw & 0xf3ff) | 0x0400; // rounding down
|
||||
__asm__ __volatile__("fldcw %0" : : "m" (cw_temp));
|
||||
fpu_extended value;
|
||||
__asm__ __volatile__("frndint" : "=t" (value) : "0" (x));
|
||||
__asm__ __volatile__("fldcw %0" : : "m" (cw));
|
||||
return value;
|
||||
}
|
||||
#else
|
||||
|
||||
#undef fp_ceil
|
||||
#define fp_ceil fp_do_ceil
|
||||
|
||||
PRIVATE inline fpu_extended fp_do_ceil(fpu_extended x)
|
||||
{
|
||||
volatile unsigned int cw;
|
||||
__asm__ __volatile__("fnstcw %0" : "=m" (cw));
|
||||
volatile unsigned int cw_temp = (cw & 0xf3ff) | 0x0800; // rounding up
|
||||
__asm__ __volatile__("fldcw %0" : : "m" (cw_temp));
|
||||
fpu_extended value;
|
||||
__asm__ __volatile__("frndint" : "=t" (value) : "0" (x));
|
||||
__asm__ __volatile__("fldcw %0" : : "m" (cw));
|
||||
return value;
|
||||
}
|
||||
|
||||
#define DEFINE_ROUND_FUNC(rounding_mode_str, rounding_mode) \
|
||||
PRIVATE inline fpu_extended fp_do_round_to_ ## rounding_mode_str(fpu_extended x) \
|
||||
{ \
|
||||
volatile unsigned short cw; \
|
||||
volatile unsigned int cw; \
|
||||
__asm__ __volatile__("fnstcw %0" : "=m" (cw)); \
|
||||
volatile unsigned short cw_temp = (cw & 0xf3ff) | (rounding_mode); \
|
||||
volatile unsigned int cw_temp = (cw & 0xf3ff) | (rounding_mode); \
|
||||
__asm__ __volatile__("fldcw %0" : : "m" (cw_temp)); \
|
||||
fpu_extended value; \
|
||||
__asm__ __volatile__("frndint" : "=t" (value) : "0" (x)); \
|
||||
__asm__ __volatile__("fldcw %0" : : "m" (cw)); \
|
||||
return value; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef fp_round_to_minus_infinity
|
||||
#define fp_round_to_minus_infinity fp_do_round_to_minus_infinity
|
||||
|
@ -1157,13 +1114,6 @@ DEFINE_ROUND_FUNC(zero, 0xc00)
|
|||
|
||||
DEFINE_ROUND_FUNC(nearest, 0x000)
|
||||
|
||||
#undef fp_ceil
|
||||
#define fp_ceil fp_do_round_to_plus_infinity
|
||||
|
||||
#undef fp_floor
|
||||
#define fp_floor fp_do_round_to_minus_infinity
|
||||
|
||||
|
||||
#endif /* USE_X87_ASSEMBLY */
|
||||
|
||||
#ifndef fp_round_to_minus_infinity
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/rounding.cpp - system-dependant FPU rounding mode and precision
|
||||
* fpu/rounding.cpp - system-dependant FPU rounding mode and precision
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#undef PRIVATE
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/rounding.h - system-dependant FPU rounding mode and precision
|
||||
* fpu/rounding.h - system-dependant FPU rounding mode and precision
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_ROUNDING_H
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
/*
|
||||
* fpu/types.h - basic types for fpu registers
|
||||
* types.h - basic types for fpu registers
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_TYPES_H
|
||||
|
@ -111,9 +106,9 @@ typedef uae_f32 fpu_single;
|
|||
|
||||
#elif defined(FPU_IEEE)
|
||||
|
||||
#if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|
||||
#error "No IEEE float format, you lose."
|
||||
#endif
|
||||
// #if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|
||||
// #error "No IEEE float format, you lose."
|
||||
// #endif
|
||||
|
||||
/* 4-byte floats */
|
||||
#if SIZEOF_FLOAT == 4
|
||||
|
@ -138,7 +133,7 @@ typedef long double uae_f64;
|
|||
typedef long double uae_f96;
|
||||
typedef uae_f96 fpu_register;
|
||||
#define USE_LONG_DOUBLE 1
|
||||
#elif SIZEOF_LONG_DOUBLE == 16 && (defined(CPU_i386) || defined(CPU_x86_64) || defined(CPU_ia64))
|
||||
#elif SIZEOF_LONG_DOUBLE == 16 && (defined(__i386__) || defined(__x86_64__))
|
||||
/* Long doubles on x86-64 are really held in old x87 FPU stack. */
|
||||
typedef long double uae_f128;
|
||||
typedef uae_f128 fpu_register;
|
||||
|
@ -159,23 +154,6 @@ typedef fpu_register fpu_extended;
|
|||
typedef uae_f64 fpu_double;
|
||||
typedef uae_f32 fpu_single;
|
||||
|
||||
#elif defined(FPU_MPFR)
|
||||
|
||||
#include <mpfr.h>
|
||||
|
||||
struct fpu_register {
|
||||
mpfr_t f;
|
||||
uae_u64 nan_bits;
|
||||
int nan_sign;
|
||||
operator long double ();
|
||||
fpu_register &operator=(long double);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
union fpu_register_parts {
|
||||
fpu_register val;
|
||||
uae_u32 parts[sizeof(fpu_register) / 4];
|
||||
};
|
||||
|
||||
#endif /* FPU_TYPES_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,44 +1,31 @@
|
|||
/*
|
||||
* m68k.h - machine dependent bits
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* MC68000 emulation - machine dependent bits
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* Copyright 1996 Bernd Schmidt
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* MC68000 emulation - machine dependent bits
|
||||
*
|
||||
* Copyright 1996 Bernd Schmidt
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef M68K_FLAGS_H
|
||||
#define M68K_FLAGS_H
|
||||
|
||||
#ifdef OPTIMIZED_FLAGS
|
||||
|
||||
#if (defined(CPU_i386) && defined(X86_ASSEMBLY)) || (defined(CPU_x86_64) && defined(X86_64_ASSEMBLY))
|
||||
|
||||
# include <cstdlib>
|
||||
#if defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY) || defined(MSVC_INTRINSICS)
|
||||
|
||||
#ifndef SAHF_SETO_PROFITABLE
|
||||
|
||||
|
@ -46,13 +33,8 @@
|
|||
unsigned long hereunder is either 64-bit or 32-bit wide depending
|
||||
on the target. */
|
||||
struct flag_struct {
|
||||
#if defined(CPU_x86_64)
|
||||
uint64 cznv;
|
||||
uint64 x;
|
||||
#else
|
||||
uint32 cznv;
|
||||
uint32 x;
|
||||
#endif
|
||||
unsigned long cznv;
|
||||
unsigned long x;
|
||||
};
|
||||
|
||||
#define FLAGVAL_Z 0x40
|
||||
|
@ -77,9 +59,9 @@ struct flag_struct {
|
|||
|
||||
#define COPY_CARRY (regflags.x = regflags.cznv)
|
||||
|
||||
extern struct flag_struct regflags __asm__ ("regflags");
|
||||
extern struct flag_struct regflags ASM_SYM ("regflags");
|
||||
|
||||
static inline int cctrue(int cc)
|
||||
static __inline__ int cctrue(int cc)
|
||||
{
|
||||
uae_u32 cznv = regflags.cznv;
|
||||
switch(cc){
|
||||
|
@ -111,25 +93,25 @@ static inline int cctrue(int cc)
|
|||
__asm__ __volatile__ ("andl %1,%1\n\t" \
|
||||
"pushf\n\t" \
|
||||
"pop %0\n\t" \
|
||||
: "=rm" (regflags.cznv) : "r" (v) : "memory", "cc")
|
||||
: "=r" (regflags.cznv) : "r" (v) : "cc")
|
||||
|
||||
#define optflag_testw(v) \
|
||||
__asm__ __volatile__ ("andw %w1,%w1\n\t" \
|
||||
"pushf\n\t" \
|
||||
"pop %0\n\t" \
|
||||
: "=rm" (regflags.cznv) : "r" (v) : "memory", "cc")
|
||||
: "=r" (regflags.cznv) : "r" (v) : "cc")
|
||||
|
||||
#define optflag_testb(v) \
|
||||
__asm__ __volatile__ ("andb %b1,%b1\n\t" \
|
||||
"pushf\n\t" \
|
||||
"pop %0\n\t" \
|
||||
: "=rm" (regflags.cznv) : "q" (v) : "memory", "cc")
|
||||
: "=r" (regflags.cznv) : "q" (v) : "cc")
|
||||
|
||||
#define optflag_addl(v, s, d) do { \
|
||||
__asm__ __volatile__ ("addl %k2,%k1\n\t" \
|
||||
"pushf\n\t" \
|
||||
"pop %0\n\t" \
|
||||
: "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \
|
||||
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while (0)
|
||||
|
||||
|
@ -137,7 +119,7 @@ static inline int cctrue(int cc)
|
|||
__asm__ __volatile__ ("addw %w2,%w1\n\t" \
|
||||
"pushf\n\t" \
|
||||
"pop %0\n\t" \
|
||||
: "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \
|
||||
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while (0)
|
||||
|
||||
|
@ -153,7 +135,7 @@ static inline int cctrue(int cc)
|
|||
__asm__ __volatile__ ("subl %k2,%k1\n\t" \
|
||||
"pushf\n\t" \
|
||||
"pop %0\n\t" \
|
||||
: "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \
|
||||
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while (0)
|
||||
|
||||
|
@ -161,7 +143,7 @@ static inline int cctrue(int cc)
|
|||
__asm__ __volatile__ ("subw %w2,%w1\n\t" \
|
||||
"pushf\n\t" \
|
||||
"pop %0\n\t" \
|
||||
: "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \
|
||||
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while (0)
|
||||
|
||||
|
@ -169,7 +151,7 @@ static inline int cctrue(int cc)
|
|||
__asm__ __volatile__ ("subb %b2,%b1\n\t" \
|
||||
"pushf\n\t" \
|
||||
"pop %0\n\t" \
|
||||
: "=rm" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "memory", "cc"); \
|
||||
: "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while (0)
|
||||
|
||||
|
@ -177,19 +159,19 @@ static inline int cctrue(int cc)
|
|||
__asm__ __volatile__ ("cmpl %k1,%k2\n\t" \
|
||||
"pushf\n\t" \
|
||||
"pop %0\n\t" \
|
||||
: "=rm" (regflags.cznv) : "rmi" (s), "r" (d) : "memory", "cc")
|
||||
: "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc")
|
||||
|
||||
#define optflag_cmpw(s, d) \
|
||||
__asm__ __volatile__ ("cmpw %w1,%w2\n\t" \
|
||||
"pushf\n\t" \
|
||||
"pop %0\n\t" \
|
||||
: "=rm" (regflags.cznv) : "rmi" (s), "r" (d) : "memory", "cc")
|
||||
: "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc")
|
||||
|
||||
#define optflag_cmpb(s, d) \
|
||||
__asm__ __volatile__ ("cmpb %b1,%b2\n\t" \
|
||||
"pushf\n\t" \
|
||||
"pop %0\n\t" \
|
||||
: "=rm" (regflags.cznv) : "qmi" (s), "q" (d) : "memory", "cc")
|
||||
: "=r" (regflags.cznv) : "qmi" (s), "q" (d) : "cc")
|
||||
|
||||
#else
|
||||
|
||||
|
@ -220,9 +202,9 @@ struct flag_struct {
|
|||
|
||||
#define COPY_CARRY (regflags.x = (regflags.cznv)>>8)
|
||||
|
||||
extern struct flag_struct regflags __asm__ ("regflags");
|
||||
extern struct flag_struct regflags ASM_SYM("regflags");
|
||||
|
||||
static inline int cctrue(int cc)
|
||||
static __inline__ int cctrue(int cc)
|
||||
{
|
||||
uae_u32 cznv = regflags.cznv;
|
||||
switch(cc){
|
||||
|
@ -252,7 +234,7 @@ static inline int cctrue(int cc)
|
|||
}
|
||||
|
||||
/* Manually emit LAHF instruction so that 64-bit assemblers can grok it */
|
||||
#if defined CPU_x86_64 && defined __GNUC__
|
||||
#if defined __x86_64__ && defined __GNUC__
|
||||
#define ASM_LAHF ".byte 0x9f"
|
||||
#else
|
||||
#define ASM_LAHF "lahf"
|
||||
|
@ -358,7 +340,7 @@ static inline int cctrue(int cc)
|
|||
"seto %%al\n\t" \
|
||||
"movb %%al,regflags\n\t" \
|
||||
"movb %%ah,regflags+1\n\t" \
|
||||
: : "rmi" (s), "r" (d) : "%eax","cc","memory")
|
||||
: : "rmi" (s), "r" (d) : "%eax","cc","memory");
|
||||
|
||||
#define optflag_cmpb(s, d) \
|
||||
__asm__ __volatile__ ("cmpb %b0,%b1\n\t" \
|
||||
|
@ -370,290 +352,7 @@ static inline int cctrue(int cc)
|
|||
|
||||
#endif
|
||||
|
||||
#elif defined(CPU_arm) && defined(ARM_ASSEMBLY)
|
||||
|
||||
struct flag_struct {
|
||||
uae_u32 nzcv;
|
||||
uae_u32 x;
|
||||
};
|
||||
|
||||
#define FLAGVAL_Q 0x08000000
|
||||
#define FLAGVAL_V 0x10000000
|
||||
#define FLAGVAL_C 0x20000000
|
||||
#define FLAGVAL_Z 0x40000000
|
||||
#define FLAGVAL_N 0x80000000
|
||||
|
||||
#define SET_NFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x80000000) | (((y) & 1) << 31))
|
||||
#define SET_ZFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x40000000) | (((y) & 1) << 30))
|
||||
#define SET_CFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x20000000) | (((y) & 1) << 29))
|
||||
#define SET_VFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x10000000) | (((y) & 1) << 28))
|
||||
#define SET_XFLG(y) (regflags.x = (y))
|
||||
|
||||
#define GET_NFLG ((regflags.nzcv >> 31) & 1)
|
||||
#define GET_ZFLG ((regflags.nzcv >> 30) & 1)
|
||||
#define GET_CFLG ((regflags.nzcv >> 29) & 1)
|
||||
#define GET_VFLG ((regflags.nzcv >> 28) & 1)
|
||||
#define GET_XFLG (regflags.x & 1)
|
||||
|
||||
#define CLEAR_CZNV (regflags.nzcv = 0)
|
||||
#define GET_CZNV (regflags.nzcv)
|
||||
#define IOR_CZNV(X) (regflags.nzcv |= (X))
|
||||
#define SET_CZNV(X) (regflags.nzcv = (X))
|
||||
|
||||
#define COPY_CARRY (regflags.x = (regflags.nzcv)>>29)
|
||||
|
||||
extern struct flag_struct regflags __asm__ ("regflags");
|
||||
|
||||
static inline int cctrue(int cc)
|
||||
{
|
||||
unsigned int nzcv = regflags.nzcv;
|
||||
switch(cc){
|
||||
case 0: return 1; /* T */
|
||||
case 1: return 0; /* F */
|
||||
case 2: return (nzcv & 0x60000000) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
|
||||
case 3: return (nzcv & 0x60000000) != 0; /* GET_CFLG || GET_ZFLG; LS */
|
||||
case 4: return (nzcv & 0x20000000) == 0; /* !GET_CFLG; CC */
|
||||
case 5: return (nzcv & 0x20000000) != 0; /* GET_CFLG; CS */
|
||||
case 6: return (nzcv & 0x40000000) == 0; /* !GET_ZFLG; NE */
|
||||
case 7: return (nzcv & 0x40000000) != 0; /* GET_ZFLG; EQ */
|
||||
case 8: return (nzcv & 0x10000000) == 0; /* !GET_VFLG; VC */
|
||||
case 9: return (nzcv & 0x10000000) != 0; /* GET_VFLG; VS */
|
||||
case 10:return (nzcv & 0x80000000) == 0; /* !GET_NFLG; PL */
|
||||
case 11:return (nzcv & 0x80000000) != 0; /* GET_NFLG; MI */
|
||||
case 12:return (((nzcv << 3) ^ nzcv) & 0x80000000) == 0; /* GET_NFLG == GET_VFLG; GE */
|
||||
case 13:return (((nzcv << 3) ^ nzcv) & 0x80000000) != 0; /* GET_NFLG != GET_VFLG; LT */
|
||||
case 14:
|
||||
nzcv &= 0xd0000000;
|
||||
return (((nzcv << 3) ^ nzcv) & 0xc0000000) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
|
||||
case 15:
|
||||
nzcv &= 0xd0000000;
|
||||
return (((nzcv << 3) ^ nzcv) & 0xc0000000) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define optflag_testl(v) do {\
|
||||
__asm__ __volatile__ ("tst %[rv],%[rv]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"bic %[nzcv],#0x30000000\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv) \
|
||||
: [rv] "r" (v) \
|
||||
: "cc"); \
|
||||
} while(0)
|
||||
|
||||
#define optflag_addl(v, s, d) do { \
|
||||
__asm__ __volatile__ ("adds %[rv],%[rd],%[rs]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
|
||||
: [rs] "ri" (s), [rd] "1" (d) \
|
||||
: "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while(0)
|
||||
|
||||
#define optflag_subl(v, s, d) do { \
|
||||
__asm__ __volatile__ ("subs %[rv],%[rd],%[rs]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"eor %[nzcv],#0x20000000\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
|
||||
: [rs] "ri" (s), [rd] "1" (d) \
|
||||
: "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while(0)
|
||||
|
||||
#define optflag_cmpl(s, d) do { \
|
||||
__asm__ __volatile__ ("cmp %[rd],%[rs]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"eor %[nzcv],#0x20000000\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv) \
|
||||
: [rs] "ri" (s), [rd] "0" (d) \
|
||||
: "cc"); \
|
||||
} while(0)
|
||||
|
||||
#if defined(ARMV6_ASSEMBLY)
|
||||
|
||||
// #pragma message "ARM/v6 Assembly optimized flags"
|
||||
|
||||
#define optflag_testw(v) do { \
|
||||
__asm__ __volatile__ ("sxth %[rv],%[rv]\n\t" \
|
||||
"tst %[rv],%[rv]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"bic %[nzcv],#0x30000000\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv) \
|
||||
: [rv] "0" (v) \
|
||||
: "cc"); \
|
||||
}while(0)
|
||||
|
||||
#define optflag_testb(v) do {\
|
||||
__asm__ __volatile__ ("sxtb %[rv],%[rv]\n\t" \
|
||||
"tst %[rv],%[rv]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"bic %[nzcv],#0x30000000\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv) \
|
||||
: [rv] "0" (v) \
|
||||
: "cc"); \
|
||||
}while(0)
|
||||
|
||||
#define optflag_addw(v, s, d) do { \
|
||||
__asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \
|
||||
"sxth %[rs],%[rs]\n\t" \
|
||||
"adds %[rd],%[rd],%[rs]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
|
||||
: [rs] "ri" (s), [rd] "1" (d) \
|
||||
: "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while(0)
|
||||
|
||||
#define optflag_addb(v, s, d) do { \
|
||||
__asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \
|
||||
"sxtb %[rs],%[rs]\n\t" \
|
||||
"adds %[rd],%[rd],%[rs]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
|
||||
: [rs] "ri" (s), [rd] "1" (d) \
|
||||
: "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while(0)
|
||||
|
||||
#define optflag_subw(v, s, d) do { \
|
||||
__asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \
|
||||
"sxth %[rs],%[rs]\n\t" \
|
||||
"subs %[rd],%[rd],%[rs]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"eor %[nzcv],#0x20000000\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
|
||||
: [rs] "ri" (s), [rd] "1" (d) \
|
||||
: "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while(0)
|
||||
|
||||
#define optflag_subb(v, s, d) do { \
|
||||
__asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \
|
||||
"sxtb %[rs],%[rs]\n\t" \
|
||||
"subs %[rd],%[rd],%[rs]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"eor %[nzcv],#0x20000000\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
|
||||
: [rs] "ri" (s), [rd] "1" (d) \
|
||||
: "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while(0)
|
||||
|
||||
#define optflag_cmpw(s, d) do { \
|
||||
__asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \
|
||||
"sxth %[rs],%[rs]\n\t" \
|
||||
"cmp %[rd],%[rs]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"eor %[nzcv],#0x20000000\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv) \
|
||||
: [rs] "ri" (s), [rd] "0" (d) \
|
||||
: "cc"); \
|
||||
} while(0)
|
||||
|
||||
#define optflag_cmpb(s, d) do { \
|
||||
__asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \
|
||||
"sxtb %[rs],%[rs]\n\t" \
|
||||
"cmp %[rd],%[rs]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"eor %[nzcv],#0x20000000\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv) \
|
||||
: [rs] "ri" (s), [rd] "0" (d) \
|
||||
: "cc"); \
|
||||
} while(0)
|
||||
|
||||
#else
|
||||
|
||||
// #pragma message "ARM/generic Assembly optimized flags"
|
||||
|
||||
#define optflag_testw(v) do { \
|
||||
__asm__ __volatile__ ("lsl %[rv],%[rv],#16\n\t" \
|
||||
"tst %[rv],%[rv]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"bic %[nzcv],#0x30000000\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv) \
|
||||
: [rv] "0" (v) \
|
||||
: "cc"); \
|
||||
}while(0)
|
||||
|
||||
#define optflag_testb(v) do {\
|
||||
__asm__ __volatile__ ("lsl %[rv],%[rv],#24\n\t" \
|
||||
"tst %[rv],%[rv]\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"bic %[nzcv],#0x30000000\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv) \
|
||||
: [rv] "0" (v) \
|
||||
: "cc"); \
|
||||
}while(0)
|
||||
|
||||
#define optflag_addw(v, s, d) do { \
|
||||
__asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \
|
||||
"adds %[rd],%[rd],%[rs],lsl #16\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"lsr %[rv],%[rd],#16\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
|
||||
: [rs] "ri" (s), [rd] "1" (d) \
|
||||
: "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while(0)
|
||||
|
||||
#define optflag_addb(v, s, d) do { \
|
||||
__asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \
|
||||
"adds %[rd],%[rd],%[rs],lsl #24\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"lsr %[rv],%[rd],#24\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
|
||||
: [rs] "ri" (s), [rd] "1" (d) \
|
||||
: "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while(0)
|
||||
|
||||
#define optflag_subw(v, s, d) do { \
|
||||
__asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \
|
||||
"subs %[rd],%[rd],%[rs],lsl #16\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"eor %[nzcv],#0x20000000\n\t" \
|
||||
"lsr %[rv],%[rd],#16\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
|
||||
: [rs] "ri" (s), [rd] "1" (d) \
|
||||
: "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while(0)
|
||||
|
||||
#define optflag_subb(v, s, d) do { \
|
||||
__asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \
|
||||
"subs %[rd],%[rd],%[rs],lsl #24\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"eor %[nzcv],#0x20000000\n\t" \
|
||||
"lsr %[rv],%[rd],#24\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
|
||||
: [rs] "ri" (s), [rd] "1" (d) \
|
||||
: "cc"); \
|
||||
COPY_CARRY; \
|
||||
} while(0)
|
||||
|
||||
#define optflag_cmpw(s, d) do { \
|
||||
__asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \
|
||||
"cmp %[rd],%[rs],lsl #16\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"eor %[nzcv],#0x20000000\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv) \
|
||||
: [rs] "ri" (s), [rd] "0" (d) \
|
||||
: "cc"); \
|
||||
} while(0)
|
||||
|
||||
#define optflag_cmpb(s, d) do { \
|
||||
__asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \
|
||||
"cmp %[rd],%[rs],lsl #24\n\t" \
|
||||
"mrs %[nzcv],cpsr\n\t" \
|
||||
"eor %[nzcv],#0x20000000\n\t" \
|
||||
: [nzcv] "=r" (regflags.nzcv) \
|
||||
: [rs] "ri" (s), [rd] "0" (d) \
|
||||
: "cc"); \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined(CPU_sparc) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY))
|
||||
#elif defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY)
|
||||
|
||||
struct flag_struct {
|
||||
unsigned char nzvc;
|
||||
|
@ -684,7 +383,7 @@ extern struct flag_struct regflags;
|
|||
|
||||
#define COPY_CARRY (regflags.x = regflags.nzvc)
|
||||
|
||||
static inline int cctrue(int cc)
|
||||
static __inline__ int cctrue(int cc)
|
||||
{
|
||||
uae_u32 nzvc = regflags.nzvc;
|
||||
switch(cc){
|
||||
|
@ -1346,7 +1045,7 @@ extern struct flag_struct regflags;
|
|||
|
||||
#define COPY_CARRY (SET_XFLG (GET_CFLG))
|
||||
|
||||
static inline int cctrue(const int cc)
|
||||
static __inline__ int cctrue(const int cc)
|
||||
{
|
||||
switch(cc){
|
||||
case 0: return 1; /* T */
|
||||
|
|
|
@ -1,606 +0,0 @@
|
|||
/*
|
||||
* memory.h - memory management
|
||||
*
|
||||
* Copyright (c) 2001-2006 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* memory management
|
||||
*
|
||||
* Copyright 1995 Bernd Schmidt
|
||||
*/
|
||||
|
||||
#ifndef UAE_MEMORY_H
|
||||
#define UAE_MEMORY_H
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "string.h"
|
||||
#include "hardware.h"
|
||||
#include "parameters.h"
|
||||
#include "registers.h"
|
||||
#include "cpummu.h"
|
||||
#include "readcpu.h"
|
||||
|
||||
# include <csetjmp>
|
||||
|
||||
// newcpu.h
|
||||
extern void Exception (int, uaecptr);
|
||||
#ifdef EXCEPTIONS_VIA_LONGJMP
|
||||
extern JMP_BUF excep_env;
|
||||
#define SAVE_EXCEPTION \
|
||||
JMP_BUF excep_env_old; \
|
||||
memcpy(excep_env_old, excep_env, sizeof(JMP_BUF))
|
||||
#define RESTORE_EXCEPTION \
|
||||
memcpy(excep_env, excep_env_old, sizeof(JMP_BUF))
|
||||
#define TRY(var) int var = SETJMP(excep_env); if (!var)
|
||||
#define CATCH(var) else
|
||||
#define THROW(n) LONGJMP(excep_env, n)
|
||||
#define THROW_AGAIN(var) LONGJMP(excep_env, var)
|
||||
#define VOLATILE volatile
|
||||
#else
|
||||
struct m68k_exception {
|
||||
int prb;
|
||||
m68k_exception (int exc) : prb (exc) {}
|
||||
operator int() { return prb; }
|
||||
};
|
||||
#define SAVE_EXCEPTION
|
||||
#define RESTORE_EXCEPTION
|
||||
#define TRY(var) try
|
||||
#define CATCH(var) catch(m68k_exception var)
|
||||
#define THROW(n) throw m68k_exception(n)
|
||||
#define THROW_AGAIN(var) throw
|
||||
#define VOLATILE
|
||||
#endif /* EXCEPTIONS_VIA_LONGJMP */
|
||||
extern int in_exception_2;
|
||||
|
||||
#define STRAM_END 0x0e00000UL // should be replaced by global ROMBase as soon as ROMBase will be a constant
|
||||
#define ROM_END 0x0e80000UL // should be replaced by ROMBase + RealROMSize if we are going to work with larger TOS ROMs than 512 kilobytes
|
||||
#define FastRAM_BEGIN 0x1000000UL // should be replaced by global FastRAMBase as soon as FastRAMBase will be a constant
|
||||
#ifdef FixedSizeFastRAM
|
||||
#define FastRAM_SIZE (FixedSizeFastRAM * 1024 * 1024)
|
||||
#else
|
||||
#define FastRAM_SIZE FastRAMSize
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_VIDEORAM
|
||||
#define ARANYMVRAMSTART 0xf0000000UL
|
||||
#endif
|
||||
|
||||
#define ARANYMVRAMSIZE 0x00100000 // should be a variable to protect VGA card offscreen memory
|
||||
|
||||
#ifdef FIXED_VIDEORAM
|
||||
extern uintptr VMEMBaseDiff;
|
||||
#else
|
||||
extern uae_u32 VideoRAMBase;
|
||||
#endif
|
||||
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
extern uaecptr pc_page, read_page, write_page;
|
||||
extern uintptr pc_offset, read_offset, write_offset;
|
||||
# ifdef PROTECT2K
|
||||
# define ARAM_PAGE_MASK 0x7ff
|
||||
# else
|
||||
# ifdef FULLMMU
|
||||
# define ARAM_PAGE_MASK 0xfff
|
||||
# else
|
||||
# define ARAM_PAGE_MASK 0xfffff
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
extern uintptr MEMBaseDiff;
|
||||
extern uintptr ROMBaseDiff;
|
||||
extern uintptr FastRAMBaseDiff;
|
||||
# define InitMEMBaseDiff(va, ra) (MEMBaseDiff = (uintptr)(va) - (uintptr)(ra))
|
||||
# define InitROMBaseDiff(va, ra) (ROMBaseDiff = (uintptr)(va) - (uintptr)(ra))
|
||||
# define InitFastRAMBaseDiff(va, ra) (FastRAMBaseDiff = (uintptr)(va) - (uintptr)(ra))
|
||||
|
||||
#ifdef FIXED_VIDEORAM
|
||||
#define InitVMEMBaseDiff(va, ra) (VMEMBaseDiff = (uintptr)(va) - (uintptr)(ra))
|
||||
#else
|
||||
#define InitVMEMBaseDiff(va, ra) (ra = (uintptr)(va) + MEMBaseDiff)
|
||||
#endif
|
||||
|
||||
extern "C" void breakpt(void);
|
||||
|
||||
|
||||
static inline uae_u64 do_get_mem_quad(uae_u64 *a) {return SDL_SwapBE64(*a);}
|
||||
static inline void do_put_mem_quad(uae_u64 *a, uae_u64 v) {*a = SDL_SwapBE64(v);}
|
||||
|
||||
|
||||
#ifndef NOCHECKBOUNDARY
|
||||
static ALWAYS_INLINE bool test_ram_boundary(uaecptr addr, int size, bool super, bool write)
|
||||
{
|
||||
if (addr <= (FastRAM_BEGIN + FastRAM_SIZE - size)) {
|
||||
#ifdef PROTECT2K
|
||||
// protect first 2kB of RAM - access in supervisor mode only
|
||||
if (!super && addr < 0x00000800UL)
|
||||
return false;
|
||||
#endif
|
||||
// check for write access to protected areas:
|
||||
// - first two longwords of ST-RAM are non-writable (ROM shadow)
|
||||
// - non-writable area between end of ST-RAM and begin of FastRAM
|
||||
if (!write || addr >= FastRAM_BEGIN || (addr >= 8 && addr <= (STRAM_END - size)))
|
||||
return true;
|
||||
}
|
||||
#ifdef FIXED_VIDEORAM
|
||||
return addr >= ARANYMVRAMSTART && addr <= (ARANYMVRAMSTART + ARANYMVRAMSIZE - size);
|
||||
#else
|
||||
return addr >= VideoRAMBase && addr <= (VideoRAMBase + ARANYMVRAMSIZE - size);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* "size" is the size of the memory access (byte = 1, word = 2, long = 4)
|
||||
*/
|
||||
static ALWAYS_INLINE void check_ram_boundary(uaecptr addr, int size, bool write)
|
||||
{
|
||||
if (test_ram_boundary(addr, size, regs.s, write))
|
||||
return;
|
||||
|
||||
// D(bug("BUS ERROR %s at $%x\n", (write ? "writing" : "reading"), addr));
|
||||
regs.mmu_fault_addr = addr;
|
||||
regs.mmu_ssw = ((size & 3) << 5) | (write ? 0 : (1 << 8));
|
||||
breakpt();
|
||||
THROW(2);
|
||||
}
|
||||
|
||||
#else
|
||||
static inline bool test_ram_boundary(uaecptr, int, bool, bool) { return 1; }
|
||||
static inline void check_ram_boundary(uaecptr, int, bool) { }
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_VIDEORAM
|
||||
# define do_get_real_address(a) ((uae_u8 *)(((uaecptr)(a) < ARANYMVRAMSTART) ? ((uaecptr)(a) + MEMBaseDiff) : ((uaecptr)(a) + VMEMBaseDiff)))
|
||||
#else
|
||||
# define do_get_real_address(a) ((uae_u8 *)((uintptr)(a) + MEMBaseDiff))
|
||||
#endif
|
||||
|
||||
static inline uae_u8 *phys_get_real_address(uaecptr addr)
|
||||
{
|
||||
return do_get_real_address(addr);
|
||||
}
|
||||
|
||||
#ifndef NOCHECKBOUNDARY
|
||||
static inline bool phys_valid_address(uaecptr addr, bool write, int sz)
|
||||
{
|
||||
return test_ram_boundary(addr, sz, regs.s, write);
|
||||
}
|
||||
#else
|
||||
static inline bool phys_valid_address(uaecptr, bool, int) { return true; }
|
||||
#endif
|
||||
|
||||
static inline uae_u64 phys_get_quad(uaecptr addr)
|
||||
{
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
if (((addr ^ read_page) <= ARAM_PAGE_MASK))
|
||||
return do_get_mem_quad((uae_u64*)(addr + read_offset));
|
||||
#endif
|
||||
#ifndef HW_SIGSEGV
|
||||
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||
if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr); /* TODO: must be HWget_q */
|
||||
#endif
|
||||
check_ram_boundary(addr, 8, false);
|
||||
uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr);
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
read_page = addr;
|
||||
read_offset = (uintptr)m - (uintptr)addr;
|
||||
#endif
|
||||
return do_get_mem_quad(m);
|
||||
}
|
||||
|
||||
static inline uae_u32 phys_get_long(uaecptr addr)
|
||||
{
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
if (((addr ^ read_page) <= ARAM_PAGE_MASK))
|
||||
return do_get_mem_long((uae_u32*)(addr + read_offset));
|
||||
#endif
|
||||
#ifndef HW_SIGSEGV
|
||||
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||
if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr);
|
||||
#endif
|
||||
check_ram_boundary(addr, 4, false);
|
||||
uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr);
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
read_page = addr;
|
||||
read_offset = (uintptr)m - (uintptr)addr;
|
||||
#endif
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
|
||||
static inline uae_u32 phys_get_word(uaecptr addr)
|
||||
{
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
if (((addr ^ read_page) <= ARAM_PAGE_MASK))
|
||||
return do_get_mem_word((uae_u16*)(addr + read_offset));
|
||||
#endif
|
||||
#ifndef HW_SIGSEGV
|
||||
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||
if ((addr & 0xfff00000) == 0x00f00000) return HWget_w(addr);
|
||||
#endif
|
||||
check_ram_boundary(addr, 2, false);
|
||||
uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr);
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
read_page = addr;
|
||||
read_offset = (uintptr)m - (uintptr)addr;
|
||||
#endif
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
|
||||
static inline uae_u32 phys_get_byte(uaecptr addr)
|
||||
{
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
if (((addr ^ read_page) <= ARAM_PAGE_MASK))
|
||||
return do_get_mem_byte((uae_u8*)(addr + read_offset));
|
||||
#endif
|
||||
#ifndef HW_SIGSEGV
|
||||
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||
if ((addr & 0xfff00000) == 0x00f00000) return HWget_b(addr);
|
||||
#endif
|
||||
check_ram_boundary(addr, 1, false);
|
||||
uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr);
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
read_page = addr;
|
||||
read_offset = (uintptr)m - (uintptr)addr;
|
||||
#endif
|
||||
return do_get_mem_byte(m);
|
||||
}
|
||||
|
||||
static inline void phys_put_quad(uaecptr addr, uae_u64 l)
|
||||
{
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
|
||||
do_put_mem_quad((uae_u64*)(addr + write_offset), l);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifndef HW_SIGSEGV
|
||||
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||
if ((addr & 0xfff00000) == 0x00f00000) {
|
||||
HWput_l(addr, l); /* TODO: must be HWput_q */
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
check_ram_boundary(addr, 8, true);
|
||||
uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr);
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
write_page = addr;
|
||||
write_offset = (uintptr)m - (uintptr)addr;
|
||||
#endif
|
||||
do_put_mem_quad(m, l);
|
||||
}
|
||||
|
||||
static inline void phys_put_long(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
|
||||
do_put_mem_long((uae_u32*)(addr + write_offset), l);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifndef HW_SIGSEGV
|
||||
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||
if ((addr & 0xfff00000) == 0x00f00000) {
|
||||
HWput_l(addr, l);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
check_ram_boundary(addr, 4, true);
|
||||
uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr);
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
write_page = addr;
|
||||
write_offset = (uintptr)m - (uintptr)addr;
|
||||
#endif
|
||||
do_put_mem_long(m, l);
|
||||
}
|
||||
|
||||
static inline void phys_put_word(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
|
||||
do_put_mem_word((uae_u16*)(addr + write_offset), w);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifndef HW_SIGSEGV
|
||||
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||
if ((addr & 0xfff00000) == 0x00f00000) {
|
||||
HWput_w(addr, w);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
check_ram_boundary(addr, 2, true);
|
||||
uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr);
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
write_page = addr;
|
||||
write_offset = (uintptr)m - (uintptr)addr;
|
||||
#endif
|
||||
do_put_mem_word(m, w);
|
||||
}
|
||||
|
||||
static inline void phys_put_byte(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
|
||||
do_put_mem_byte((uae_u8*)(addr + write_offset), b);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifndef HW_SIGSEGV
|
||||
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||
if ((addr & 0xfff00000) == 0x00f00000) {
|
||||
HWput_b(addr, b);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
check_ram_boundary(addr, 1, true);
|
||||
uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr);
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
write_page = addr;
|
||||
write_offset = (uintptr)m - (uintptr)addr;
|
||||
#endif
|
||||
do_put_mem_byte(m, b);
|
||||
}
|
||||
|
||||
#ifdef FULLMMU
|
||||
static ALWAYS_INLINE bool is_unaligned(uaecptr addr, int size)
|
||||
{
|
||||
return unlikely((addr & (size - 1)) && (addr ^ (addr + size - 1)) & 0x1000);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE uae_u8 *mmu_get_real_address(uaecptr addr, struct mmu_atc_line *cl)
|
||||
{
|
||||
return do_get_real_address(cl->phys + addr);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE uae_u32 mmu_get_quad(uaecptr addr, int data)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_lookup(addr, data, 0, &cl)))
|
||||
return do_get_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl));
|
||||
return mmu_get_quad_slow(addr, regs.s, data, cl);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE uae_u64 get_quad(uaecptr addr)
|
||||
{
|
||||
return mmu_get_quad(addr, 1);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, int data, int size)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_lookup(addr, data, 0, &cl)))
|
||||
return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl));
|
||||
return mmu_get_long_slow(addr, regs.s, data, size, cl);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE uae_u32 get_long(uaecptr addr)
|
||||
{
|
||||
if (unlikely(is_unaligned(addr, 4)))
|
||||
return mmu_get_long_unaligned(addr, 1);
|
||||
return mmu_get_long(addr, 1, sz_long);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, int data, int size)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_lookup(addr, data, 0, &cl)))
|
||||
return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl));
|
||||
return mmu_get_word_slow(addr, regs.s, data, size, cl);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE uae_u16 get_word(uaecptr addr)
|
||||
{
|
||||
if (unlikely(is_unaligned(addr, 2)))
|
||||
return mmu_get_word_unaligned(addr, 1);
|
||||
return mmu_get_word(addr, 1, sz_word);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, int data, int size)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_lookup(addr, data, 0, &cl)))
|
||||
return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl));
|
||||
return mmu_get_byte_slow(addr, regs.s, data, size, cl);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE uae_u8 get_byte(uaecptr addr)
|
||||
{
|
||||
return mmu_get_byte(addr, 1, sz_byte);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void mmu_put_quad(uaecptr addr, uae_u64 val, int data)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_lookup(addr, data, 1, &cl)))
|
||||
do_put_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl), val);
|
||||
else
|
||||
mmu_put_quad_slow(addr, val, regs.s, data, cl);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void put_quad(uaecptr addr, uae_u32 val)
|
||||
{
|
||||
mmu_put_quad(addr, val, 1);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, int data, int size)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_lookup(addr, data, 1, &cl)))
|
||||
do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val);
|
||||
else
|
||||
mmu_put_long_slow(addr, val, regs.s, data, size, cl);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void put_long(uaecptr addr, uae_u32 val)
|
||||
{
|
||||
if (unlikely(is_unaligned(addr, 4)))
|
||||
mmu_put_long_unaligned(addr, val, 1);
|
||||
else
|
||||
mmu_put_long(addr, val, 1, sz_long);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, int data, int size)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_lookup(addr, data, 1, &cl)))
|
||||
do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val);
|
||||
else
|
||||
mmu_put_word_slow(addr, val, regs.s, data, size, cl);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void put_word(uaecptr addr, uae_u16 val)
|
||||
{
|
||||
if (unlikely(is_unaligned(addr, 2)))
|
||||
mmu_put_word_unaligned(addr, val, 1);
|
||||
else
|
||||
mmu_put_word(addr, val, 1, sz_word);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, int data, int size)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_lookup(addr, data, 1, &cl)))
|
||||
do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val);
|
||||
else
|
||||
mmu_put_byte_slow(addr, val, regs.s, data, size, cl);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void put_byte(uaecptr addr, uae_u8 val)
|
||||
{
|
||||
mmu_put_byte(addr, val, 1, sz_byte);
|
||||
}
|
||||
|
||||
static inline uae_u8 *get_real_address(uaecptr addr, int write, int sz)
|
||||
{
|
||||
(void)sz;
|
||||
return phys_get_real_address(mmu_translate(addr, regs.s, 1, write));
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, int super, int data, int size)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_user_lookup(addr, super, data, 0, &cl)))
|
||||
return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl));
|
||||
return mmu_get_long_slow(addr, super, data, size, cl);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, int super, int data, int size)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_user_lookup(addr, super, data, 0, &cl)))
|
||||
return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl));
|
||||
return mmu_get_word_slow(addr, super, data, size, cl);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, int super, int data, int size)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_user_lookup(addr, super, data, 0, &cl)))
|
||||
return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl));
|
||||
return mmu_get_byte_slow(addr, super, data, size, cl);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, int super, int data, int size)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_user_lookup(addr, super, data, 1, &cl)))
|
||||
do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val);
|
||||
else
|
||||
mmu_put_long_slow(addr, val, super, data, size, cl);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, int super, int data, int size)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_user_lookup(addr, super, data, 1, &cl)))
|
||||
do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val);
|
||||
else
|
||||
mmu_put_word_slow(addr, val, super, data, size, cl);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, int super, int data, int size)
|
||||
{
|
||||
struct mmu_atc_line *cl;
|
||||
|
||||
if (likely(mmu_user_lookup(addr, super, data, 1, &cl)))
|
||||
do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val);
|
||||
else
|
||||
mmu_put_byte_slow(addr, val, super, data, size, cl);
|
||||
}
|
||||
|
||||
static inline bool valid_address(uaecptr addr, bool write, int sz)
|
||||
{
|
||||
SAVE_EXCEPTION;
|
||||
TRY(prb) {
|
||||
(void)sz;
|
||||
check_ram_boundary(mmu_translate(addr, regs.s, 1, (write ? 1 : 0)), sz, write);
|
||||
RESTORE_EXCEPTION;
|
||||
return true;
|
||||
}
|
||||
CATCH(prb) {
|
||||
RESTORE_EXCEPTION;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# define get_quad(a) phys_get_quad(a)
|
||||
# define get_long(a) phys_get_long(a)
|
||||
# define get_word(a) phys_get_word(a)
|
||||
# define get_byte(a) phys_get_byte(a)
|
||||
# define put_quad(a,b) phys_put_quad(a,b)
|
||||
# define put_long(a,b) phys_put_long(a,b)
|
||||
# define put_word(a,b) phys_put_word(a,b)
|
||||
# define put_byte(a,b) phys_put_byte(a,b)
|
||||
# define get_real_address(a,w,s) phys_get_real_address(a)
|
||||
|
||||
#define valid_address(a,w,s) phys_valid_address(a,w,s)
|
||||
#endif
|
||||
|
||||
static inline void flush_internals() {
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
pc_page = 0xeeeeeeee;
|
||||
read_page = 0xeeeeeeee;
|
||||
write_page = 0xeeeeeeee;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* MEMORY_H */
|
||||
|
||||
/*
|
||||
vim:ts=4:sw=4:
|
||||
*/
|
|
@ -1,59 +1,642 @@
|
|||
/*
|
||||
* memory.cpp - memory management
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* Memory management
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* (c) 1995 Bernd Schmidt
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Memory management
|
||||
*
|
||||
* (c) 1995 Bernd Schmidt
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include "memory.h"
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
#include "cpu_emulation.h"
|
||||
#include "main.h"
|
||||
#include "video.h"
|
||||
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
uaecptr pc_page = 0xeeeeeeee;
|
||||
uintptr pc_offset = 0;
|
||||
uaecptr read_page = 0xeeeeeeee;
|
||||
uintptr read_offset = 0;
|
||||
uaecptr write_page = 0xeeeeeeee;
|
||||
uintptr write_offset = 0;
|
||||
#include "m68k.h"
|
||||
#include "memory.h"
|
||||
#include "readcpu.h"
|
||||
#include "newcpu.h"
|
||||
|
||||
#if !REAL_ADDRESSING && !DIRECT_ADDRESSING
|
||||
|
||||
static bool illegal_mem = false;
|
||||
|
||||
#ifdef SAVE_MEMORY_BANKS
|
||||
addrbank *mem_banks[65536];
|
||||
#else
|
||||
addrbank mem_banks[65536];
|
||||
#endif
|
||||
|
||||
extern "C" void breakpt(void)
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# define swap_words(X) (X)
|
||||
#else
|
||||
# define swap_words(X) (((X) >> 16) | ((X) << 16))
|
||||
#endif
|
||||
|
||||
#ifdef NO_INLINE_MEMORY_ACCESS
|
||||
uae_u32 longget (uaecptr addr)
|
||||
{
|
||||
// bug("bus err: pc=%08x, sp=%08x, addr=%08x", m68k_getpc(), regs.regs[15], regs.mmu_fault_addr);
|
||||
return call_mem_get_func (get_mem_bank (addr).lget, addr);
|
||||
}
|
||||
uae_u32 wordget (uaecptr addr)
|
||||
{
|
||||
return call_mem_get_func (get_mem_bank (addr).wget, addr);
|
||||
}
|
||||
uae_u32 byteget (uaecptr addr)
|
||||
{
|
||||
return call_mem_get_func (get_mem_bank (addr).bget, addr);
|
||||
}
|
||||
void longput (uaecptr addr, uae_u32 l)
|
||||
{
|
||||
call_mem_put_func (get_mem_bank (addr).lput, addr, l);
|
||||
}
|
||||
void wordput (uaecptr addr, uae_u32 w)
|
||||
{
|
||||
call_mem_put_func (get_mem_bank (addr).wput, addr, w);
|
||||
}
|
||||
void byteput (uaecptr addr, uae_u32 b)
|
||||
{
|
||||
call_mem_put_func (get_mem_bank (addr).bput, addr, b);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* A dummy bank that only contains zeros */
|
||||
|
||||
static uae_u32 REGPARAM2 dummy_lget (uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 dummy_wget (uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 dummy_bget (uaecptr) REGPARAM;
|
||||
static void REGPARAM2 dummy_lput (uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 dummy_wput (uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 dummy_bput (uaecptr, uae_u32) REGPARAM;
|
||||
|
||||
uae_u32 REGPARAM2 dummy_lget (uaecptr addr)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal lget at %08x\n", addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !KNOWN_ALLOC && !NORMAL_ADDRESSING
|
||||
// This part need rewrite for ARAnyM !!
|
||||
// It can be taken from hatari.
|
||||
uae_u32 REGPARAM2 dummy_wget (uaecptr addr)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal wget at %08x\n", addr);
|
||||
|
||||
#error Not prepared for your platform, maybe you need memory banks from hatari
|
||||
return 0;
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 dummy_bget (uaecptr addr)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal bget at %08x\n", addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void REGPARAM2 dummy_lput (uaecptr addr, uae_u32 l)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal lput at %08x\n", addr);
|
||||
}
|
||||
void REGPARAM2 dummy_wput (uaecptr addr, uae_u32 w)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal wput at %08x\n", addr);
|
||||
}
|
||||
void REGPARAM2 dummy_bput (uaecptr addr, uae_u32 b)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal bput at %08x\n", addr);
|
||||
}
|
||||
|
||||
/* Mac RAM (32 bit addressing) */
|
||||
|
||||
static uae_u32 REGPARAM2 ram_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 ram_wget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 ram_bget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 ram_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 ram_wput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 ram_bput(uaecptr, uae_u32) REGPARAM;
|
||||
static uae_u8 *REGPARAM2 ram_xlate(uaecptr addr) REGPARAM;
|
||||
|
||||
static uintptr RAMBaseDiff; // RAMBaseHost - RAMBaseMac
|
||||
|
||||
uae_u32 REGPARAM2 ram_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(RAMBaseDiff + addr);
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 ram_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(RAMBaseDiff + addr);
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 ram_bget(uaecptr addr)
|
||||
{
|
||||
return (uae_u32)*(uae_u8 *)(RAMBaseDiff + addr);
|
||||
}
|
||||
|
||||
void REGPARAM2 ram_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(RAMBaseDiff + addr);
|
||||
do_put_mem_long(m, l);
|
||||
}
|
||||
|
||||
void REGPARAM2 ram_wput(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(RAMBaseDiff + addr);
|
||||
do_put_mem_word(m, w);
|
||||
}
|
||||
|
||||
void REGPARAM2 ram_bput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
*(uae_u8 *)(RAMBaseDiff + addr) = b;
|
||||
}
|
||||
|
||||
uae_u8 *REGPARAM2 ram_xlate(uaecptr addr)
|
||||
{
|
||||
return (uae_u8 *)(RAMBaseDiff + addr);
|
||||
}
|
||||
|
||||
/* Mac RAM (24 bit addressing) */
|
||||
|
||||
static uae_u32 REGPARAM2 ram24_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 ram24_wget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 ram24_bget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 ram24_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 ram24_wput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 ram24_bput(uaecptr, uae_u32) REGPARAM;
|
||||
static uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr) REGPARAM;
|
||||
|
||||
uae_u32 REGPARAM2 ram24_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 ram24_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 ram24_bget(uaecptr addr)
|
||||
{
|
||||
return (uae_u32)*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
}
|
||||
|
||||
void REGPARAM2 ram24_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
do_put_mem_long(m, l);
|
||||
}
|
||||
|
||||
void REGPARAM2 ram24_wput(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
do_put_mem_word(m, w);
|
||||
}
|
||||
|
||||
void REGPARAM2 ram24_bput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)) = b;
|
||||
}
|
||||
|
||||
uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr)
|
||||
{
|
||||
return (uae_u8 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
}
|
||||
|
||||
/* Mac ROM (32 bit addressing) */
|
||||
|
||||
static uae_u32 REGPARAM2 rom_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 rom_wget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 rom_bget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 rom_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 rom_wput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 rom_bput(uaecptr, uae_u32) REGPARAM;
|
||||
static uae_u8 *REGPARAM2 rom_xlate(uaecptr addr) REGPARAM;
|
||||
|
||||
static uintptr ROMBaseDiff; // ROMBaseHost - ROMBaseMac
|
||||
|
||||
uae_u32 REGPARAM2 rom_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(ROMBaseDiff + addr);
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 rom_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(ROMBaseDiff + addr);
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 rom_bget(uaecptr addr)
|
||||
{
|
||||
return (uae_u32)*(uae_u8 *)(ROMBaseDiff + addr);
|
||||
}
|
||||
|
||||
void REGPARAM2 rom_lput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal ROM lput at %08x\n", addr);
|
||||
}
|
||||
|
||||
void REGPARAM2 rom_wput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal ROM wput at %08x\n", addr);
|
||||
}
|
||||
|
||||
void REGPARAM2 rom_bput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal ROM bput at %08x\n", addr);
|
||||
}
|
||||
|
||||
uae_u8 *REGPARAM2 rom_xlate(uaecptr addr)
|
||||
{
|
||||
return (uae_u8 *)(ROMBaseDiff + addr);
|
||||
}
|
||||
|
||||
/* Mac ROM (24 bit addressing) */
|
||||
|
||||
static uae_u32 REGPARAM2 rom24_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 rom24_wget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 rom24_bget(uaecptr) REGPARAM;
|
||||
static uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr) REGPARAM;
|
||||
|
||||
uae_u32 REGPARAM2 rom24_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(ROMBaseDiff + (addr & 0xffffff));
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 rom24_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(ROMBaseDiff + (addr & 0xffffff));
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 rom24_bget(uaecptr addr)
|
||||
{
|
||||
return (uae_u32)*(uae_u8 *)(ROMBaseDiff + (addr & 0xffffff));
|
||||
}
|
||||
|
||||
uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr)
|
||||
{
|
||||
return (uae_u8 *)(ROMBaseDiff + (addr & 0xffffff));
|
||||
}
|
||||
|
||||
/* Frame buffer */
|
||||
|
||||
static uae_u32 REGPARAM2 frame_direct_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 frame_direct_wget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 frame_direct_bget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 frame_direct_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 frame_direct_wput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 frame_direct_bput(uaecptr, uae_u32) REGPARAM;
|
||||
|
||||
static uae_u32 REGPARAM2 frame_host_555_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 frame_host_555_wget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 frame_host_555_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 frame_host_555_wput(uaecptr, uae_u32) REGPARAM;
|
||||
|
||||
static uae_u32 REGPARAM2 frame_host_565_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 frame_host_565_wget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 frame_host_565_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 frame_host_565_wput(uaecptr, uae_u32) REGPARAM;
|
||||
|
||||
static uae_u32 REGPARAM2 frame_host_888_lget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 frame_host_888_lput(uaecptr, uae_u32) REGPARAM;
|
||||
|
||||
static uae_u8 *REGPARAM2 frame_xlate(uaecptr addr) REGPARAM;
|
||||
|
||||
static uintptr FrameBaseDiff; // MacFrameBaseHost - MacFrameBaseMac
|
||||
|
||||
uae_u32 REGPARAM2 frame_direct_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_direct_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(FrameBaseDiff + addr);
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_direct_bget(uaecptr addr)
|
||||
{
|
||||
return (uae_u32)*(uae_u8 *)(FrameBaseDiff + addr);
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_direct_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
do_put_mem_long(m, l);
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_direct_wput(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(FrameBaseDiff + addr);
|
||||
do_put_mem_word(m, w);
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_direct_bput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
*(uae_u8 *)(FrameBaseDiff + addr) = b;
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_host_555_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m, l;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
l = *m;
|
||||
return swap_words(l);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_host_555_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(FrameBaseDiff + addr);
|
||||
return *m;
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_host_555_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
*m = swap_words(l);
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_host_555_wput(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(FrameBaseDiff + addr);
|
||||
*m = w;
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_host_565_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m, l;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
l = *m;
|
||||
l = (l & 0x001f001f) | ((l >> 1) & 0x7fe07fe0);
|
||||
return swap_words(l);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_host_565_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m, w;
|
||||
m = (uae_u16 *)(FrameBaseDiff + addr);
|
||||
w = *m;
|
||||
return (w & 0x1f) | ((w >> 1) & 0x7fe0);
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_host_565_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
l = (l & 0x001f001f) | ((l << 1) & 0xffc0ffc0);
|
||||
*m = swap_words(l);
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_host_565_wput(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(FrameBaseDiff + addr);
|
||||
*m = (w & 0x1f) | ((w << 1) & 0xffc0);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_host_888_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m, l;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
return *m;
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_host_888_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(MacFrameBaseHost + addr - MacFrameBaseMac);
|
||||
*m = l;
|
||||
}
|
||||
|
||||
uae_u8 *REGPARAM2 frame_xlate(uaecptr addr)
|
||||
{
|
||||
return (uae_u8 *)(FrameBaseDiff + addr);
|
||||
}
|
||||
|
||||
/* Mac framebuffer RAM (24 bit addressing)
|
||||
*
|
||||
* This works by duplicating appropriate writes to the 32-bit
|
||||
* address-space framebuffer.
|
||||
*/
|
||||
|
||||
static void REGPARAM2 fram24_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 fram24_wput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 fram24_bput(uaecptr, uae_u32) REGPARAM;
|
||||
|
||||
void REGPARAM2 fram24_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uaecptr page_off = addr & 0xffff;
|
||||
if (0xa700 <= page_off && page_off < 0xfc80) {
|
||||
uae_u32 *fm;
|
||||
fm = (uae_u32 *)(MacFrameBaseHost + page_off - 0xa700);
|
||||
do_put_mem_long(fm, l);
|
||||
}
|
||||
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
do_put_mem_long(m, l);
|
||||
}
|
||||
|
||||
void REGPARAM2 fram24_wput(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uaecptr page_off = addr & 0xffff;
|
||||
if (0xa700 <= page_off && page_off < 0xfc80) {
|
||||
uae_u16 *fm;
|
||||
fm = (uae_u16 *)(MacFrameBaseHost + page_off - 0xa700);
|
||||
do_put_mem_word(fm, w);
|
||||
}
|
||||
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
do_put_mem_word(m, w);
|
||||
}
|
||||
|
||||
void REGPARAM2 fram24_bput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
uaecptr page_off = addr & 0xffff;
|
||||
if (0xa700 <= page_off && page_off < 0xfc80) {
|
||||
*(uae_u8 *)(MacFrameBaseHost + page_off - 0xa700) = b;
|
||||
}
|
||||
|
||||
*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)) = b;
|
||||
}
|
||||
|
||||
/* Default memory access functions */
|
||||
|
||||
uae_u8 *REGPARAM2 default_xlate (uaecptr a)
|
||||
{
|
||||
write_log("Your Mac program just did something terribly stupid\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Address banks */
|
||||
|
||||
addrbank dummy_bank = {
|
||||
dummy_lget, dummy_wget, dummy_bget,
|
||||
dummy_lput, dummy_wput, dummy_bput,
|
||||
default_xlate
|
||||
};
|
||||
|
||||
addrbank ram_bank = {
|
||||
ram_lget, ram_wget, ram_bget,
|
||||
ram_lput, ram_wput, ram_bput,
|
||||
ram_xlate
|
||||
};
|
||||
|
||||
addrbank ram24_bank = {
|
||||
ram24_lget, ram24_wget, ram24_bget,
|
||||
ram24_lput, ram24_wput, ram24_bput,
|
||||
ram24_xlate
|
||||
};
|
||||
|
||||
addrbank rom_bank = {
|
||||
rom_lget, rom_wget, rom_bget,
|
||||
rom_lput, rom_wput, rom_bput,
|
||||
rom_xlate
|
||||
};
|
||||
|
||||
addrbank rom24_bank = {
|
||||
rom24_lget, rom24_wget, rom24_bget,
|
||||
rom_lput, rom_wput, rom_bput,
|
||||
rom24_xlate
|
||||
};
|
||||
|
||||
addrbank frame_direct_bank = {
|
||||
frame_direct_lget, frame_direct_wget, frame_direct_bget,
|
||||
frame_direct_lput, frame_direct_wput, frame_direct_bput,
|
||||
frame_xlate
|
||||
};
|
||||
|
||||
addrbank frame_host_555_bank = {
|
||||
frame_host_555_lget, frame_host_555_wget, frame_direct_bget,
|
||||
frame_host_555_lput, frame_host_555_wput, frame_direct_bput,
|
||||
frame_xlate
|
||||
};
|
||||
|
||||
addrbank frame_host_565_bank = {
|
||||
frame_host_565_lget, frame_host_565_wget, frame_direct_bget,
|
||||
frame_host_565_lput, frame_host_565_wput, frame_direct_bput,
|
||||
frame_xlate
|
||||
};
|
||||
|
||||
addrbank frame_host_888_bank = {
|
||||
frame_host_888_lget, frame_direct_wget, frame_direct_bget,
|
||||
frame_host_888_lput, frame_direct_wput, frame_direct_bput,
|
||||
frame_xlate
|
||||
};
|
||||
|
||||
addrbank fram24_bank = {
|
||||
ram24_lget, ram24_wget, ram24_bget,
|
||||
fram24_lput, fram24_wput, fram24_bput,
|
||||
ram24_xlate
|
||||
};
|
||||
|
||||
void memory_init(void)
|
||||
{
|
||||
for(long i=0; i<65536; i++)
|
||||
put_mem_bank(i<<16, &dummy_bank);
|
||||
|
||||
// Limit RAM size to not overlap ROM
|
||||
uint32 ram_size = RAMSize > ROMBaseMac ? ROMBaseMac : RAMSize;
|
||||
|
||||
RAMBaseDiff = (uintptr)RAMBaseHost - (uintptr)RAMBaseMac;
|
||||
ROMBaseDiff = (uintptr)ROMBaseHost - (uintptr)ROMBaseMac;
|
||||
FrameBaseDiff = (uintptr)MacFrameBaseHost - (uintptr)MacFrameBaseMac;
|
||||
|
||||
// Map RAM, ROM and display
|
||||
if (TwentyFourBitAddressing) {
|
||||
map_banks(&ram24_bank, RAMBaseMac >> 16, ram_size >> 16);
|
||||
map_banks(&rom24_bank, ROMBaseMac >> 16, ROMSize >> 16);
|
||||
|
||||
// Map frame buffer at end of RAM.
|
||||
map_banks(&fram24_bank, ((RAMBaseMac + ram_size) >> 16) - 1, 1);
|
||||
} else {
|
||||
map_banks(&ram_bank, RAMBaseMac >> 16, ram_size >> 16);
|
||||
map_banks(&rom_bank, ROMBaseMac >> 16, ROMSize >> 16);
|
||||
|
||||
// Map frame buffer
|
||||
switch (MacFrameLayout) {
|
||||
case FLAYOUT_DIRECT:
|
||||
map_banks(&frame_direct_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
|
||||
break;
|
||||
case FLAYOUT_HOST_555:
|
||||
map_banks(&frame_host_555_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
|
||||
break;
|
||||
case FLAYOUT_HOST_565:
|
||||
map_banks(&frame_host_565_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
|
||||
break;
|
||||
case FLAYOUT_HOST_888:
|
||||
map_banks(&frame_host_888_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void map_banks(addrbank *bank, int start, int size)
|
||||
{
|
||||
int bnr;
|
||||
unsigned long int hioffs = 0, endhioffs = 0x100;
|
||||
|
||||
if (start >= 0x100) {
|
||||
for (bnr = start; bnr < start + size; bnr++)
|
||||
put_mem_bank (bnr << 16, bank);
|
||||
return;
|
||||
}
|
||||
if (TwentyFourBitAddressing) endhioffs = 0x10000;
|
||||
for (hioffs = 0; hioffs < endhioffs; hioffs += 0x100)
|
||||
for (bnr = start; bnr < start+size; bnr++)
|
||||
put_mem_bank((bnr + hioffs) << 16, bank);
|
||||
}
|
||||
|
||||
#endif /* !REAL_ADDRESSING && !DIRECT_ADDRESSING */
|
||||
|
||||
#endif /* !KNOWN_ALLOC && !NORMAL_ADDRESSING */
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
#ifndef UAE_MEMORY_H
|
||||
#define UAE_MEMORY_H
|
||||
|
||||
#if DIRECT_ADDRESSING
|
||||
extern uintptr MEMBaseDiff;
|
||||
#endif
|
||||
|
||||
extern void Exception (int, uaecptr);
|
||||
#ifdef EXCEPTIONS_VIA_LONGJMP
|
||||
extern JMP_BUF excep_env;
|
||||
|
@ -54,8 +50,109 @@ extern void Exception (int, uaecptr);
|
|||
#define THROW_AGAIN(var) throw
|
||||
#define VOLATILE
|
||||
#endif /* EXCEPTIONS_VIA_LONGJMP */
|
||||
extern int in_exception_2;
|
||||
|
||||
#if DIRECT_ADDRESSING
|
||||
#if !DIRECT_ADDRESSING && !REAL_ADDRESSING
|
||||
|
||||
/* Enabling this adds one additional native memory reference per 68k memory
|
||||
* access, but saves one shift (on the x86). Enabling this is probably
|
||||
* better for the cache. My favourite benchmark (PP2) doesn't show a
|
||||
* difference, so I leave this enabled. */
|
||||
|
||||
#if 1 || defined SAVE_MEMORY
|
||||
#define SAVE_MEMORY_BANKS
|
||||
#endif
|
||||
|
||||
typedef uae_u32 (REGPARAM2 *mem_get_func)(uaecptr) REGPARAM;
|
||||
typedef void (REGPARAM2 *mem_put_func)(uaecptr, uae_u32) REGPARAM;
|
||||
typedef uae_u8 *(REGPARAM2 *xlate_func)(uaecptr) REGPARAM;
|
||||
|
||||
#undef DIRECT_MEMFUNCS_SUCCESSFUL
|
||||
|
||||
#ifndef CAN_MAP_MEMORY
|
||||
#undef USE_COMPILER
|
||||
#endif
|
||||
|
||||
#if defined(USE_COMPILER) && !defined(USE_MAPPED_MEMORY)
|
||||
#define USE_MAPPED_MEMORY
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
/* These ones should be self-explanatory... */
|
||||
mem_get_func lget, wget, bget;
|
||||
mem_put_func lput, wput, bput;
|
||||
/* Use xlateaddr to translate an Amiga address to a uae_u8 * that can
|
||||
* be used to address memory without calling the wget/wput functions.
|
||||
* This doesn't work for all memory banks, so this function may call
|
||||
* abort(). */
|
||||
xlate_func xlateaddr;
|
||||
} addrbank;
|
||||
|
||||
extern uae_u8 filesysory[65536];
|
||||
|
||||
extern addrbank ram_bank; // Mac RAM
|
||||
extern addrbank rom_bank; // Mac ROM
|
||||
extern addrbank frame_bank; // Frame buffer
|
||||
|
||||
/* Default memory access functions */
|
||||
|
||||
extern uae_u8 *REGPARAM2 default_xlate(uaecptr addr) REGPARAM;
|
||||
|
||||
#define bankindex(addr) (((uaecptr)(addr)) >> 16)
|
||||
|
||||
#ifdef SAVE_MEMORY_BANKS
|
||||
extern addrbank *mem_banks[65536];
|
||||
#define get_mem_bank(addr) (*mem_banks[bankindex(addr)])
|
||||
#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = (b))
|
||||
#else
|
||||
extern addrbank mem_banks[65536];
|
||||
#define get_mem_bank(addr) (mem_banks[bankindex(addr)])
|
||||
#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = *(b))
|
||||
#endif
|
||||
|
||||
extern void memory_init(void);
|
||||
extern void map_banks(addrbank *bank, int first, int count);
|
||||
|
||||
#ifndef NO_INLINE_MEMORY_ACCESS
|
||||
|
||||
#define longget(addr) (call_mem_get_func(get_mem_bank(addr).lget, addr))
|
||||
#define wordget(addr) (call_mem_get_func(get_mem_bank(addr).wget, addr))
|
||||
#define byteget(addr) (call_mem_get_func(get_mem_bank(addr).bget, addr))
|
||||
#define longput(addr,l) (call_mem_put_func(get_mem_bank(addr).lput, addr, l))
|
||||
#define wordput(addr,w) (call_mem_put_func(get_mem_bank(addr).wput, addr, w))
|
||||
#define byteput(addr,b) (call_mem_put_func(get_mem_bank(addr).bput, addr, b))
|
||||
|
||||
#else
|
||||
|
||||
extern uae_u32 longget(uaecptr addr);
|
||||
extern uae_u32 wordget(uaecptr addr);
|
||||
extern uae_u32 byteget(uaecptr addr);
|
||||
extern void longput(uaecptr addr, uae_u32 l);
|
||||
extern void wordput(uaecptr addr, uae_u32 w);
|
||||
extern void byteput(uaecptr addr, uae_u32 b);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef MD_HAVE_MEM_1_FUNCS
|
||||
|
||||
#define longget_1 longget
|
||||
#define wordget_1 wordget
|
||||
#define byteget_1 byteget
|
||||
#define longput_1 longput
|
||||
#define wordput_1 wordput
|
||||
#define byteput_1 byteput
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !DIRECT_ADDRESSING && !REAL_ADDRESSING */
|
||||
|
||||
#if REAL_ADDRESSING
|
||||
const uintptr MEMBaseDiff = 0;
|
||||
#elif DIRECT_ADDRESSING
|
||||
extern uintptr MEMBaseDiff;
|
||||
#endif
|
||||
|
||||
#if REAL_ADDRESSING || DIRECT_ADDRESSING
|
||||
static __inline__ uae_u8 *do_get_real_address(uaecptr addr)
|
||||
{
|
||||
return (uae_u8 *)MEMBaseDiff + addr;
|
||||
|
@ -69,57 +166,71 @@ static __inline__ uae_u32 get_long(uaecptr addr)
|
|||
uae_u32 * const m = (uae_u32 *)do_get_real_address(addr);
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
#define phys_get_long get_long
|
||||
static __inline__ uae_u32 get_word(uaecptr addr)
|
||||
{
|
||||
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
#define phys_get_word get_word
|
||||
static __inline__ uae_u32 get_byte(uaecptr addr)
|
||||
{
|
||||
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
|
||||
return do_get_mem_byte(m);
|
||||
}
|
||||
#define phys_get_byte get_byte
|
||||
static __inline__ void put_long(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 * const m = (uae_u32 *)do_get_real_address(addr);
|
||||
do_put_mem_long(m, l);
|
||||
}
|
||||
#define phys_put_long put_long
|
||||
static __inline__ void put_word(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
|
||||
do_put_mem_word(m, w);
|
||||
}
|
||||
#define phys_put_word put_word
|
||||
static __inline__ void put_byte(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
|
||||
do_put_mem_byte(m, b);
|
||||
}
|
||||
#define phys_put_byte put_byte
|
||||
static __inline__ uae_u8 *get_real_address(uaecptr addr)
|
||||
{
|
||||
return do_get_real_address(addr);
|
||||
}
|
||||
static inline uae_u8 *get_real_address(uaecptr addr, int write, int sz)
|
||||
{
|
||||
return do_get_real_address(addr);
|
||||
}
|
||||
static inline uae_u8 *phys_get_real_address(uaecptr addr)
|
||||
{
|
||||
return do_get_real_address(addr);
|
||||
}
|
||||
static __inline__ uae_u32 get_virtual_address(uae_u8 *addr)
|
||||
{
|
||||
return do_get_virtual_address(addr);
|
||||
}
|
||||
#endif /* DIRECT_ADDRESSING */
|
||||
|
||||
static __inline__ void check_ram_boundary(uaecptr addr, int size, bool write) {}
|
||||
static inline void flush_internals() {}
|
||||
#else
|
||||
static __inline__ uae_u32 get_long(uaecptr addr)
|
||||
{
|
||||
return longget_1(addr);
|
||||
}
|
||||
static __inline__ uae_u32 get_word(uaecptr addr)
|
||||
{
|
||||
return wordget_1(addr);
|
||||
}
|
||||
static __inline__ uae_u32 get_byte(uaecptr addr)
|
||||
{
|
||||
return byteget_1(addr);
|
||||
}
|
||||
static __inline__ void put_long(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
longput_1(addr, l);
|
||||
}
|
||||
static __inline__ void put_word(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
wordput_1(addr, w);
|
||||
}
|
||||
static __inline__ void put_byte(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
byteput_1(addr, b);
|
||||
}
|
||||
static __inline__ uae_u8 *get_real_address(uaecptr addr)
|
||||
{
|
||||
return get_mem_bank(addr).xlateaddr(addr);
|
||||
}
|
||||
/* gb-- deliberately not implemented since it shall not be used... */
|
||||
extern uae_u32 get_virtual_address(uae_u8 *addr);
|
||||
#endif /* DIRECT_ADDRESSING || REAL_ADDRESSING */
|
||||
|
||||
#endif /* MEMORY_H */
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,51 +1,41 @@
|
|||
/*
|
||||
* newcpu.h - CPU emulation
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Copyright (c) 2009 ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
* MC68000 emulation
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
* Copyright 1995 Bernd Schmidt
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* MC68000 emulation
|
||||
*
|
||||
* Copyright 1995 Bernd Schmidt
|
||||
*/
|
||||
|
||||
#ifndef NEWCPU_H
|
||||
#define NEWCPU_H
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "registers.h"
|
||||
#include "spcflags.h"
|
||||
#ifndef FLIGHT_RECORDER
|
||||
#define FLIGHT_RECORDER 0
|
||||
#endif
|
||||
|
||||
#include "m68k.h"
|
||||
#include "memory.h"
|
||||
#include "readcpu.h"
|
||||
#include "spcflags.h"
|
||||
|
||||
# include <csetjmp>
|
||||
#if ENABLE_MON
|
||||
#include "mon.h"
|
||||
#include "mon_disass.h"
|
||||
#endif
|
||||
|
||||
extern struct fixup {
|
||||
int flag;
|
||||
uae_u32 reg;
|
||||
uaecptr value;
|
||||
}fixup;
|
||||
|
||||
extern int areg_byteinc[];
|
||||
extern int imm8_table[];
|
||||
|
@ -67,25 +57,27 @@ extern int broken_in;
|
|||
#endif
|
||||
|
||||
#define cpuop_begin() do { cpuop_tag("begin"); } while (0)
|
||||
#define cpuop_end() do { cpuop_tag("end"); } while (0)
|
||||
#define cpuop_end() do { cpuop_tag("end"); } while (0)
|
||||
|
||||
typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM;
|
||||
|
||||
|
||||
struct cputbl {
|
||||
cpuop_func *handler;
|
||||
uae_u16 specific;
|
||||
uae_u16 opcode;
|
||||
};
|
||||
|
||||
extern cpuop_func *cpufunctbl[65536];
|
||||
extern cpuop_func *cpufunctbl[65536] ASM_SYM("cpufunctbl");
|
||||
|
||||
#ifdef USE_JIT
|
||||
#if USE_JIT
|
||||
typedef void compop_func (uae_u32) REGPARAM;
|
||||
|
||||
//NOTE: The "opcode" and "specific" fields were switched in the original source code!
|
||||
|
||||
struct comptbl {
|
||||
compop_func *handler;
|
||||
uae_u32 opcode;
|
||||
uae_u32 specific;
|
||||
uae_u32 opcode;
|
||||
uae_u32 specific;
|
||||
#define COMP_OPCODE_ISJUMP 0x0001
|
||||
#define COMP_OPCODE_LONG_OPCODE 0x0002
|
||||
#define COMP_OPCODE_CMOV 0x0004
|
||||
|
@ -96,84 +88,151 @@ struct comptbl {
|
|||
#endif
|
||||
|
||||
extern void REGPARAM2 op_illg (uae_u32) REGPARAM;
|
||||
extern void m68k_dumpstate(uaecptr *nextpc);
|
||||
|
||||
typedef char flagtype;
|
||||
|
||||
// struct regstruct {
|
||||
// uae_u32 regs[16];
|
||||
|
||||
// uae_u32 pc;
|
||||
// uae_u8 * pc_p;
|
||||
// uae_u8 * pc_oldp;
|
||||
|
||||
// spcflags_t spcflags;
|
||||
// int intmask;
|
||||
|
||||
// uae_u32 vbr, sfc, dfc;
|
||||
// uaecptr usp, isp, msp;
|
||||
// uae_u16 sr;
|
||||
// flagtype t1;
|
||||
// flagtype t0;
|
||||
// flagtype s;
|
||||
// flagtype m;
|
||||
// flagtype x;
|
||||
// flagtype stopped;
|
||||
|
||||
// #if USE_PREFETCH_BUFFER
|
||||
// /* Fellow sources say this is 4 longwords. That's impossible. It needs
|
||||
// * to be at least a longword. The HRM has some cryptic comment about two
|
||||
// * instructions being on the same longword boundary.
|
||||
// * The way this is implemented now seems like a good compromise.
|
||||
// */
|
||||
// uae_u32 prefetch;
|
||||
// #endif
|
||||
// };
|
||||
|
||||
struct regstruct
|
||||
{
|
||||
uae_u32 regs[16];
|
||||
uaecptr usp,isp,msp;
|
||||
uae_u16 sr;
|
||||
flagtype t1;
|
||||
flagtype t0;
|
||||
flagtype s;
|
||||
flagtype m;
|
||||
flagtype x;
|
||||
flagtype stopped;
|
||||
int intmask;
|
||||
|
||||
uae_u32 pc;
|
||||
uae_u32 fault_pc;
|
||||
uae_u8 *pc_p;
|
||||
uae_u8 *pc_oldp;
|
||||
|
||||
uae_u32 vbr,sfc,dfc;
|
||||
|
||||
volatile uae_u32 spcflags;
|
||||
|
||||
#if 1
|
||||
uae_u32 kick_mask;
|
||||
|
||||
/* Fellow sources say this is 4 longwords. That's impossible. It needs
|
||||
* to be at least a longword. The HRM has some cryptic comment about two
|
||||
* instructions being on the same longword boundary.
|
||||
* The way this is implemented now seems like a good compromise.
|
||||
*/
|
||||
uae_u32 prefetch;
|
||||
#endif
|
||||
|
||||
/* MMU reg*/
|
||||
uae_u32 urp,srp;
|
||||
uae_u32 tc;
|
||||
|
||||
int mmu_enabled; /* flagtype tce; */
|
||||
int mmu_pagesize_8k; /* flagtype tcp; */
|
||||
|
||||
uae_u32 dtt0,dtt1,itt0,itt1;
|
||||
uae_u32 mmusr;
|
||||
|
||||
uae_u32 mmu_fslw, mmu_fault_addr;
|
||||
uae_u16 mmu_ssw;
|
||||
uae_u32 wb3_data;
|
||||
uae_u16 wb3_status;
|
||||
|
||||
/* Cache reg*/
|
||||
uae_u32 cacr,caar;
|
||||
};
|
||||
|
||||
extern regstruct regs, lastint_regs;
|
||||
|
||||
#define m68k_dreg(r,num) ((r).regs[(num)])
|
||||
#define m68k_areg(r,num) (((r).regs + 8)[(num)])
|
||||
|
||||
#ifdef FULLMMU
|
||||
static ALWAYS_INLINE uae_u8 get_ibyte(uae_u32 o)
|
||||
{
|
||||
return mmu_get_byte(m68k_getpc() + o + 1, 0, sz_byte);
|
||||
}
|
||||
static ALWAYS_INLINE uae_u16 get_iword(uae_u32 o)
|
||||
{
|
||||
return mmu_get_word(m68k_getpc() + o, 0, sz_word);
|
||||
}
|
||||
static ALWAYS_INLINE uae_u32 get_ilong(uae_u32 o)
|
||||
{
|
||||
uaecptr addr = m68k_getpc() + o;
|
||||
|
||||
if (unlikely(is_unaligned(addr, 4)))
|
||||
return mmu_get_long_unaligned(addr, 0);
|
||||
return mmu_get_long(addr, 0, sz_long);
|
||||
}
|
||||
#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1))
|
||||
#define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o)))
|
||||
#define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (o)))
|
||||
|
||||
#ifdef HAVE_GET_WORD_UNSWAPPED
|
||||
#define GET_OPCODE (do_get_mem_word_unswapped (regs.pc_p))
|
||||
#else
|
||||
#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(get_real_address(m68k_getpc(), 0, sz_byte) + (o) + 1))
|
||||
#define get_iword(o) do_get_mem_word((uae_u16 *)(get_real_address(m68k_getpc(), 0, sz_word) + (o)))
|
||||
#define get_ilong(o) do_get_mem_long((uae_u32 *)(get_real_address(m68k_getpc(), 0, sz_long) + (o)))
|
||||
#define GET_OPCODE (get_iword (0))
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static inline uae_u32 get_ibyte_prefetch (uae_s32 o)
|
||||
#if USE_PREFETCH_BUFFER
|
||||
static __inline__ uae_u32 get_ibyte_prefetch (uae_s32 o)
|
||||
{
|
||||
if (o > 3 || o < 0)
|
||||
return do_get_mem_byte((uae_u8 *)(do_get_real_address(regs.pcp, false, false) + o + 1));
|
||||
return do_get_mem_byte((uae_u8 *)(regs.pc_p + o + 1));
|
||||
|
||||
return do_get_mem_byte((uae_u8 *)(((uae_u8 *)®s.prefetch) + o + 1));
|
||||
}
|
||||
static inline uae_u32 get_iword_prefetch (uae_s32 o)
|
||||
static __inline__ uae_u32 get_iword_prefetch (uae_s32 o)
|
||||
{
|
||||
if (o > 3 || o < 0)
|
||||
return do_get_mem_word((uae_u16 *)(do_get_real_address(regs.pcp, false, false) + o));
|
||||
return do_get_mem_word((uae_u16 *)(regs.pc_p + o));
|
||||
|
||||
return do_get_mem_word((uae_u16 *)(((uae_u8 *)®s.prefetch) + o));
|
||||
}
|
||||
static inline uae_u32 get_ilong_prefetch (uae_s32 o)
|
||||
static __inline__ uae_u32 get_ilong_prefetch (uae_s32 o)
|
||||
{
|
||||
if (o > 3 || o < 0)
|
||||
return do_get_mem_long((uae_u32 *)(do_get_real_address(regs.pcp, false, false) + o));
|
||||
return do_get_mem_long((uae_u32 *)(regs.pc_p + o));
|
||||
if (o == 0)
|
||||
return do_get_mem_long(®s.prefetch);
|
||||
return (do_get_mem_word (((uae_u16 *)®s.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(do_get_real_address(regs.pcp, false, false) + 4));
|
||||
return (do_get_mem_word (((uae_u16 *)®s.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(regs.pc_p + 4));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FULLMMU
|
||||
#define m68k_incpc(o) (regs.pc += (o))
|
||||
#else
|
||||
#define m68k_incpc(o) (regs.pc_p += (o))
|
||||
#endif
|
||||
|
||||
static inline void fill_prefetch_0 (void)
|
||||
static __inline__ void fill_prefetch_0 (void)
|
||||
{
|
||||
#if USE_PREFETCH_BUFFER
|
||||
uae_u32 r;
|
||||
#ifdef UNALIGNED_PROFITABLE
|
||||
r = *(uae_u32 *)do_get_real_address(m68k_getpc(), false, false);
|
||||
r = *(uae_u32 *)regs.pc_p;
|
||||
regs.prefetch = r;
|
||||
#else
|
||||
r = do_get_mem_long ((uae_u32 *)do_get_real_address(m68k_getpc(), false, false));
|
||||
r = do_get_mem_long ((uae_u32 *)regs.pc_p);
|
||||
do_put_mem_long (®s.prefetch, r);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
static inline void fill_prefetch_2 (void)
|
||||
static __inline__ void fill_prefetch_2 (void)
|
||||
{
|
||||
uae_u32 r = do_get_mem_long (®s.prefetch) << 16;
|
||||
uae_u32 r2 = do_get_mem_word (((uae_u16 *)do_get_real_address(regs.pcp, false, false)) + 1);
|
||||
uae_u32 r2 = do_get_mem_word (((uae_u16 *)regs.pc_p) + 1);
|
||||
r |= r2;
|
||||
do_put_mem_long (®s.prefetch, r);
|
||||
}
|
||||
|
@ -181,92 +240,115 @@ static inline void fill_prefetch_2 (void)
|
|||
#define fill_prefetch_2 fill_prefetch_0
|
||||
#endif
|
||||
|
||||
static __inline__ uaecptr m68k_getpc (void)
|
||||
{
|
||||
#if REAL_ADDRESSING || DIRECT_ADDRESSING
|
||||
return get_virtual_address(regs.pc_p);
|
||||
#else
|
||||
return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ void m68k_setpc (uaecptr newpc)
|
||||
{
|
||||
#if ENABLE_MON
|
||||
uae_u32 previous_pc = m68k_getpc();
|
||||
#endif
|
||||
|
||||
#if REAL_ADDRESSING || DIRECT_ADDRESSING
|
||||
regs.pc_p = get_real_address(newpc);
|
||||
#else
|
||||
regs.pc_p = regs.pc_oldp = get_real_address(newpc);
|
||||
regs.pc = newpc;
|
||||
#endif
|
||||
|
||||
#if ENABLE_MON
|
||||
if (IS_BREAK_POINT(newpc)) {
|
||||
printf("Stopped at break point address: %08x. Last PC: %08x\n", newpc, previous_pc);
|
||||
m68k_dumpstate(NULL);
|
||||
const char *arg[4] = {"mon", "-m", "-r", NULL};
|
||||
mon(3, arg);
|
||||
}
|
||||
#endif // end of #if ENABLE_MON
|
||||
}
|
||||
|
||||
static __inline__ void m68k_incpc (uae_s32 delta)
|
||||
{
|
||||
#if ENABLE_MON
|
||||
uae_u32 previous_pc = m68k_getpc();
|
||||
#endif
|
||||
regs.pc_p += (delta);
|
||||
#if ENABLE_MON
|
||||
uaecptr next_pc = m68k_getpc();
|
||||
if (IS_BREAK_POINT(next_pc)) {
|
||||
printf("Stopped at break point address: %08x. Last PC: %08x\n", next_pc, previous_pc);
|
||||
m68k_dumpstate(NULL);
|
||||
const char *arg[4] = {"mon", "-m", "-r", NULL};
|
||||
mon(3, arg);
|
||||
}
|
||||
#endif // end of #if ENABLE_MON
|
||||
}
|
||||
|
||||
/* These are only used by the 68020/68881 code, and therefore don't
|
||||
* need to handle prefetch. */
|
||||
static inline uae_u32 next_ibyte (void)
|
||||
static __inline__ uae_u32 next_ibyte (void)
|
||||
{
|
||||
uae_u32 r = get_ibyte (0);
|
||||
m68k_incpc (2);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline uae_u32 next_iword (void)
|
||||
static __inline__ uae_u32 next_iword (void)
|
||||
{
|
||||
uae_u32 r = get_iword (0);
|
||||
m68k_incpc (2);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline uae_u32 next_ilong (void)
|
||||
static __inline__ uae_u32 next_ilong (void)
|
||||
{
|
||||
uae_u32 r = get_ilong (0);
|
||||
m68k_incpc (4);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void m68k_setpc (uaecptr newpc)
|
||||
{
|
||||
#ifndef FULLMMU
|
||||
regs.pc_p = regs.pc_oldp = get_real_address(newpc, 0, sz_word);
|
||||
#endif
|
||||
regs.fault_pc = regs.pc = newpc;
|
||||
}
|
||||
|
||||
#define m68k_setpc_fast m68k_setpc
|
||||
#define m68k_setpc_bcc m68k_setpc
|
||||
#define m68k_setpc_rte m68k_setpc
|
||||
|
||||
static inline void m68k_do_rts(void)
|
||||
static __inline__ void m68k_do_rts(void)
|
||||
{
|
||||
m68k_setpc(get_long(m68k_areg(regs, 7)));
|
||||
m68k_areg(regs, 7) += 4;
|
||||
m68k_setpc(get_long(m68k_areg(regs, 7)));
|
||||
m68k_areg(regs, 7) += 4;
|
||||
}
|
||||
|
||||
static inline void m68k_do_bsr(uaecptr oldpc, uae_s32 offset)
|
||||
static __inline__ void m68k_do_bsr(uaecptr oldpc, uae_s32 offset)
|
||||
{
|
||||
put_long(m68k_areg(regs, 7) - 4, oldpc);
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
m68k_incpc(offset);
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
put_long(m68k_areg(regs, 7), oldpc);
|
||||
m68k_incpc(offset);
|
||||
}
|
||||
|
||||
static inline void m68k_do_jsr(uaecptr oldpc, uaecptr dest)
|
||||
static __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest)
|
||||
{
|
||||
put_long(m68k_areg(regs, 7) - 4, oldpc);
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
m68k_setpc(dest);
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
put_long(m68k_areg(regs, 7), oldpc);
|
||||
m68k_setpc(dest);
|
||||
}
|
||||
|
||||
static inline void m68k_setstopped (int stop)
|
||||
static __inline__ void m68k_setstopped (int stop)
|
||||
{
|
||||
regs.stopped = stop;
|
||||
/* A traced STOP instruction drops through immediately without
|
||||
actually stopping. */
|
||||
if (stop && !( SPCFLAGS_TEST( SPCFLAG_DOTRACE )))
|
||||
SPCFLAGS_SET( SPCFLAG_STOP );
|
||||
if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0)
|
||||
SPCFLAGS_SET( SPCFLAG_STOP );
|
||||
}
|
||||
|
||||
#ifdef FULLMMU
|
||||
# define GET_OPCODE (get_iword (0))
|
||||
#elif defined ARAM_PAGE_CHECK
|
||||
# ifdef HAVE_GET_WORD_UNSWAPPED
|
||||
# define GET_OPCODE (do_get_mem_word_unswapped((uae_u16*)(pc + pc_offset)));
|
||||
# else
|
||||
# define GET_OPCODE (do_get_mem_word((uae_u16*)(pc + pc_offset)));
|
||||
# endif
|
||||
#else
|
||||
# ifdef HAVE_GET_WORD_UNSWAPPED
|
||||
# define GET_OPCODE (do_get_mem_word_unswapped ((uae_u16*)get_real_address(m68k_getpc(), 0, sz_word)))
|
||||
# else
|
||||
# define GET_OPCODE (get_iword (0))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
extern REGPARAM uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp);
|
||||
extern REGPARAM uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp);
|
||||
extern REGPARAM uae_u32 get_bitfield(uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width);
|
||||
extern REGPARAM void put_bitfield(uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width);
|
||||
|
||||
extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp);
|
||||
extern uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp);
|
||||
|
||||
extern uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf);
|
||||
|
||||
extern void MakeSR (void);
|
||||
extern void MakeFromSR (void);
|
||||
|
@ -278,19 +360,15 @@ extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr);
|
|||
extern void m68k_mull (uae_u32, uae_u32, uae_u16);
|
||||
extern void m68k_emulop (uae_u32);
|
||||
extern void m68k_emulop_return (void);
|
||||
extern void m68k_natfeat_id(void);
|
||||
extern void m68k_natfeat_call(void);
|
||||
extern void init_m68k (void);
|
||||
extern void exit_m68k (void);
|
||||
extern void m68k_dumpstate (FILE *, uaecptr *);
|
||||
extern void m68k_disasm (FILE *, uaecptr, uaecptr *, int);
|
||||
extern void newm68k_disasm(FILE *, uaecptr, uaecptr *, unsigned int);
|
||||
extern void showDisasm(uaecptr);
|
||||
extern void m68k_dumpstate (uaecptr *);
|
||||
extern void m68k_disasm (uaecptr, uaecptr *, int);
|
||||
extern void m68k_reset (void);
|
||||
extern void m68k_enter_debugger(void);
|
||||
extern int m68k_do_specialties(void);
|
||||
extern void m68k_instr_set(void);
|
||||
uae_u32 linea68000(uae_u16 opcode);
|
||||
|
||||
extern void mmu_op (uae_u32, uae_u16);
|
||||
|
||||
/* Opcode of faulting instruction */
|
||||
extern uae_u16 last_op_for_exception_3;
|
||||
|
@ -301,19 +379,24 @@ extern uaecptr last_fault_for_exception_3;
|
|||
|
||||
#define CPU_OP_NAME(a) op ## a
|
||||
|
||||
/* 68040+ 68881 */
|
||||
extern const struct cputbl op_smalltbl_0_ff[];
|
||||
extern const struct cputbl op_smalltbl_0_nf[];
|
||||
/* 68020 + 68881 */
|
||||
extern struct cputbl op_smalltbl_0_ff[];
|
||||
/* 68020 */
|
||||
extern struct cputbl op_smalltbl_1_ff[];
|
||||
/* 68010 */
|
||||
extern struct cputbl op_smalltbl_2_ff[];
|
||||
/* 68000 */
|
||||
extern struct cputbl op_smalltbl_3_ff[];
|
||||
/* 68000 slow but compatible. */
|
||||
extern struct cputbl op_smalltbl_4_ff[];
|
||||
|
||||
#ifdef FLIGHT_RECORDER
|
||||
extern void m68k_record_step(uaecptr, int);
|
||||
#if FLIGHT_RECORDER
|
||||
extern void m68k_record_step(uaecptr) REGPARAM;
|
||||
#endif
|
||||
|
||||
extern void m68k_do_execute(void);
|
||||
extern void m68k_execute(void);
|
||||
#ifdef USE_JIT
|
||||
#if USE_JIT
|
||||
extern void m68k_compile_execute(void);
|
||||
extern void m68k_do_compile_execute(void);
|
||||
#endif
|
||||
#ifdef USE_CPU_EMUL_SERVICES
|
||||
extern int32 emulated_ticks;
|
||||
|
@ -328,7 +411,5 @@ static inline void cpu_check_ticks(void)
|
|||
#define cpu_check_ticks()
|
||||
#define cpu_do_check_ticks()
|
||||
#endif
|
||||
|
||||
cpuop_func op_illg_1;
|
||||
|
||||
|
||||
#endif /* NEWCPU_H */
|
||||
|
|
|
@ -33,13 +33,13 @@
|
|||
#define NOFLAGS_CMP 0
|
||||
|
||||
#undef SET_NFLG_ALWAYS
|
||||
static inline void SET_NFLG_ALWAYS(uae_u32 x)
|
||||
static __inline__ void SET_NFLG_ALWAYS(uae_u32 x)
|
||||
{
|
||||
SET_NFLG(x); /* This has not yet been redefined */
|
||||
}
|
||||
|
||||
#undef SET_CFLG_ALWAYS
|
||||
static inline void SET_CFLG_ALWAYS(uae_u32 x)
|
||||
static __inline__ void SET_CFLG_ALWAYS(uae_u32 x)
|
||||
{
|
||||
SET_CFLG(x); /* This has not yet been redefined */
|
||||
}
|
||||
|
|
|
@ -1,27 +1,33 @@
|
|||
/* 2002 MJ */
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Read 68000 CPU specs from file "table68k"
|
||||
*
|
||||
* Copyright 1995,1996 Bernd Schmidt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "readcpu.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
using std::strncmp;
|
||||
using std::abort;
|
||||
using std::fprintf;
|
||||
using std::strcmp;
|
||||
using std::strlen;
|
||||
using std::malloc;
|
||||
|
||||
int nr_cpuop_funcs;
|
||||
|
||||
struct mnemolookup lookuptab[] = {
|
||||
|
@ -147,20 +153,16 @@ struct mnemolookup lookuptab[] = {
|
|||
{ i_CPUSHA, "CPUSHA" },
|
||||
{ i_MOVE16, "MOVE16" },
|
||||
|
||||
{ i_EMULOP_RETURN, "EMULOP_RETURN" },
|
||||
{ i_EMULOP, "EMULOP" },
|
||||
|
||||
{ i_EMULOP_RETURN, "EMULOP_RETURN" },
|
||||
{ i_EMULOP, "EMULOP" },
|
||||
|
||||
{ i_MMUOP, "MMUOP" },
|
||||
|
||||
{i_NATFEAT_ID, "NATFEAT_ID" },
|
||||
{i_NATFEAT_CALL, "NATFEAT_CALL" },
|
||||
|
||||
{ i_ILLG, "" },
|
||||
};
|
||||
|
||||
struct instr *table68k;
|
||||
|
||||
static inline amodes mode_from_str (const char *str)
|
||||
static __inline__ amodes mode_from_str (const char *str)
|
||||
{
|
||||
if (strncmp (str, "Dreg", 4) == 0) return Dreg;
|
||||
if (strncmp (str, "Areg", 4) == 0) return Areg;
|
||||
|
@ -178,7 +180,7 @@ static inline amodes mode_from_str (const char *str)
|
|||
return (amodes)0;
|
||||
}
|
||||
|
||||
static inline amodes mode_from_mr (int mode, int reg)
|
||||
static __inline__ amodes mode_from_mr (int mode, int reg)
|
||||
{
|
||||
switch (mode) {
|
||||
case 0: return Dreg;
|
||||
|
@ -213,32 +215,31 @@ static void build_insn (int insn)
|
|||
int i, n;
|
||||
|
||||
int flaglive = 0, flagdead = 0;
|
||||
int cflow = 0;
|
||||
int cflow = 0;
|
||||
|
||||
id = defs68k[insn];
|
||||
|
||||
// Control flow information
|
||||
cflow = id.cflow;
|
||||
|
||||
// Mask of flags set/used
|
||||
unsigned char flags_set(0), flags_used(0);
|
||||
|
||||
for (i = 0, n = 4; i < 5; i++, n--) {
|
||||
switch (id.flaginfo[i].flagset) {
|
||||
case fa_unset: case fa_isjmp: break;
|
||||
default: flags_set |= (1 << n);
|
||||
// Control flow information
|
||||
cflow = id.cflow;
|
||||
|
||||
// Mask of flags set/used
|
||||
unsigned char flags_set(0), flags_used(0);
|
||||
|
||||
for (i = 0, n = 4; i < 5; i++, n--) {
|
||||
switch (id.flaginfo[i].flagset) {
|
||||
case fa_unset: case fa_isjmp: break;
|
||||
default: flags_set |= (1 << n);
|
||||
}
|
||||
|
||||
switch (id.flaginfo[i].flaguse) {
|
||||
case fu_unused: case fu_isjmp: break;
|
||||
default: flags_used |= (1 << n);
|
||||
}
|
||||
}
|
||||
|
||||
switch (id.flaginfo[i].flaguse) {
|
||||
case fu_unused: case fu_isjmp: break;
|
||||
default: flags_used |= (1 << n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
switch (id.flaginfo[i].flagset){
|
||||
case fa_unset: break;
|
||||
case fa_isjmp: break;
|
||||
case fa_zero: flagdead |= 1 << i; break;
|
||||
case fa_one: flagdead |= 1 << i; break;
|
||||
case fa_dontcare: flagdead |= 1 << i; break;
|
||||
|
@ -251,8 +252,6 @@ static void build_insn (int insn)
|
|||
for (i = 0; i < 5; i++) {
|
||||
switch (id.flaginfo[i].flaguse) {
|
||||
case fu_unused: break;
|
||||
case fu_isjmp: flaglive |= 1 << i; break;
|
||||
case fu_maybecc: flaglive |= 1 << i; break;
|
||||
case fu_unknown: flaglive = -1; goto out2;
|
||||
case fu_used: flaglive |= 1 << i; break;
|
||||
}
|
||||
|
@ -307,7 +306,6 @@ static void build_insn (int insn)
|
|||
continue;
|
||||
if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff))
|
||||
continue;
|
||||
|
||||
if (bitcnt[bitE] && (bitval[bitE] == 0x00))
|
||||
continue;
|
||||
|
||||
|
@ -348,9 +346,9 @@ static void build_insn (int insn)
|
|||
}
|
||||
}
|
||||
mnp++;
|
||||
if ((unsigned)mnp >= (sizeof(mnemonic)-1)) {
|
||||
mnemonic[sizeof(mnemonic)-1] = '\0';
|
||||
fprintf(stderr, "WTF!!! Instruction '%s' overflow\n", mnemonic);
|
||||
if ((unsigned)mnp >= sizeof(mnemonic) - 1) {
|
||||
mnemonic[sizeof(mnemonic) - 1] = 0;
|
||||
fprintf(stderr, "Instruction %s overflow\n", mnemonic);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
@ -381,7 +379,6 @@ static void build_insn (int insn)
|
|||
case 'A':
|
||||
srcmode = Areg;
|
||||
switch (opcstr[pos++]) {
|
||||
case 'l': srcmode = absl; break;
|
||||
case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
|
||||
case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
|
||||
default: abort();
|
||||
|
@ -391,11 +388,9 @@ static void build_insn (int insn)
|
|||
case 'P': srcmode = Aipi; pos++; break;
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
case 'L':
|
||||
srcmode = absl;
|
||||
break;
|
||||
#endif
|
||||
case '#':
|
||||
switch (opcstr[pos++]) {
|
||||
case 'z': srcmode = imm; break;
|
||||
|
@ -441,7 +436,7 @@ static void build_insn (int insn)
|
|||
srcpos = bitpos[bitK];
|
||||
}
|
||||
break;
|
||||
case 'E': srcmode = immi; srcreg = bitval[bitE];
|
||||
case 'E': srcmode = immi; srcreg = bitval[bitE];
|
||||
if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ??
|
||||
/* 1..255 */
|
||||
srcgather = 1;
|
||||
|
@ -449,8 +444,8 @@ static void build_insn (int insn)
|
|||
srcpos = bitpos[bitE];
|
||||
}
|
||||
break;
|
||||
case 'p': srcmode = immi; srcreg = bitval[bitp];
|
||||
if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ??
|
||||
case 'p': srcmode = immi; srcreg = bitval[bitp];
|
||||
if (CPU_EMU_SIZE < 5) {
|
||||
/* 0..3 */
|
||||
srcgather = 1;
|
||||
srctype = 7;
|
||||
|
@ -587,22 +582,21 @@ static void build_insn (int insn)
|
|||
case 'A':
|
||||
destmode = Areg;
|
||||
switch (opcstr[pos++]) {
|
||||
case 'l': destmode = absl; break;
|
||||
case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
|
||||
case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
|
||||
case 'x': destreg = 0; dstgather = 0; dstpos = 0; break;
|
||||
case 'x': destreg = 0; dstgather = 0; dstpos = 0; break;
|
||||
default: abort();
|
||||
}
|
||||
if (dstpos < 0 || dstpos >= 32)
|
||||
abort();
|
||||
switch (opcstr[pos]) {
|
||||
case 'p': destmode = Apdi; pos++; break;
|
||||
case 'P': destmode = Aipi; pos++; break;
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
case 'L':
|
||||
destmode = absl;
|
||||
break;
|
||||
#endif
|
||||
case '#':
|
||||
switch (opcstr[pos++]) {
|
||||
case 'z': destmode = imm; break;
|
||||
|
@ -773,7 +767,7 @@ static void build_insn (int insn)
|
|||
table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions
|
||||
if ( table68k[opc].mnemo == i_Scc
|
||||
|| table68k[opc].mnemo == i_Bcc
|
||||
|
@ -801,7 +795,7 @@ static void build_insn (int insn)
|
|||
case 15:flags_used = 0x0E; break; /* LE */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 1
|
||||
/* gb-- flagdead and flaglive would not have correct information */
|
||||
table68k[opc].flagdead = flags_set;
|
||||
|
@ -831,7 +825,7 @@ void read_table68k (void)
|
|||
}
|
||||
}
|
||||
|
||||
static int readcpu_mismatch;
|
||||
static int mismatch;
|
||||
|
||||
static void handle_merges (long int opcode)
|
||||
{
|
||||
|
@ -857,9 +851,9 @@ static void handle_merges (long int opcode)
|
|||
case 5:
|
||||
smsk = 63; sbitdst = 64; break;
|
||||
case 6:
|
||||
smsk = 255; sbitdst = 256; break;
|
||||
smsk = 255; sbitdst = 256; break;
|
||||
case 7:
|
||||
smsk = 3; sbitdst = 4; break;
|
||||
smsk = 3; sbitdst = 4; break;
|
||||
default:
|
||||
smsk = 0; sbitdst = 0;
|
||||
abort();
|
||||
|
@ -875,7 +869,7 @@ static void handle_merges (long int opcode)
|
|||
}
|
||||
for (srcreg=0; srcreg < sbitdst; srcreg++) {
|
||||
for (dstreg=0; dstreg < dstend; dstreg++) {
|
||||
uae_u16 code = opcode;
|
||||
uae_u16 code = uae_u16(opcode);
|
||||
|
||||
code = (code & ~smsk) | (srcreg << table68k[opcode].spos);
|
||||
code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos);
|
||||
|
@ -888,20 +882,20 @@ static void handle_merges (long int opcode)
|
|||
|| table68k[code].suse != table68k[opcode].suse
|
||||
|| table68k[code].duse != table68k[opcode].duse)
|
||||
{
|
||||
readcpu_mismatch++; continue;
|
||||
mismatch++; continue;
|
||||
}
|
||||
if (table68k[opcode].suse
|
||||
&& (table68k[opcode].spos != table68k[code].spos
|
||||
|| table68k[opcode].smode != table68k[code].smode
|
||||
|| table68k[opcode].stype != table68k[code].stype))
|
||||
{
|
||||
readcpu_mismatch++; continue;
|
||||
mismatch++; continue;
|
||||
}
|
||||
if (table68k[opcode].duse
|
||||
&& (table68k[opcode].dpos != table68k[code].dpos
|
||||
|| table68k[opcode].dmode != table68k[code].dmode))
|
||||
{
|
||||
readcpu_mismatch++; continue;
|
||||
mismatch++; continue;
|
||||
}
|
||||
|
||||
if (code != opcode)
|
||||
|
@ -914,7 +908,7 @@ void do_merges (void)
|
|||
{
|
||||
long int opcode;
|
||||
int nr = 0;
|
||||
readcpu_mismatch = 0;
|
||||
mismatch = 0;
|
||||
for (opcode = 0; opcode < 65536; opcode++) {
|
||||
if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG)
|
||||
continue;
|
||||
|
@ -926,5 +920,114 @@ void do_merges (void)
|
|||
|
||||
int get_no_mismatches (void)
|
||||
{
|
||||
return readcpu_mismatch;
|
||||
return mismatch;
|
||||
}
|
||||
|
||||
const char *get_instruction_name (unsigned int opcode)
|
||||
{
|
||||
struct instr *ins = &table68k[opcode];
|
||||
for (int i = 0; lookuptab[i].name[0]; i++) {
|
||||
if (ins->mnemo == lookuptab[i].mnemo)
|
||||
return lookuptab[i].name;
|
||||
}
|
||||
abort();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *get_ea_string (amodes mode, wordsizes size)
|
||||
{
|
||||
static char buffer[80];
|
||||
|
||||
buffer[0] = 0;
|
||||
switch (mode){
|
||||
case Dreg:
|
||||
strcpy (buffer,"Dn");
|
||||
break;
|
||||
case Areg:
|
||||
strcpy (buffer,"An");
|
||||
break;
|
||||
case Aind:
|
||||
strcpy (buffer,"(An)");
|
||||
break;
|
||||
case Aipi:
|
||||
strcpy (buffer,"(An)+");
|
||||
break;
|
||||
case Apdi:
|
||||
strcpy (buffer,"-(An)");
|
||||
break;
|
||||
case Ad16:
|
||||
strcpy (buffer,"(d16,An)");
|
||||
break;
|
||||
case Ad8r:
|
||||
strcpy (buffer,"(d8,An,Xn)");
|
||||
break;
|
||||
case PC16:
|
||||
strcpy (buffer,"(d16,PC)");
|
||||
break;
|
||||
case PC8r:
|
||||
strcpy (buffer,"(d8,PC,Xn)");
|
||||
break;
|
||||
case absw:
|
||||
strcpy (buffer,"(xxx).W");
|
||||
break;
|
||||
case absl:
|
||||
strcpy (buffer,"(xxx).L");
|
||||
break;
|
||||
case imm:
|
||||
switch (size){
|
||||
case sz_byte:
|
||||
strcpy (buffer,"#<data>.B");
|
||||
break;
|
||||
case sz_word:
|
||||
strcpy (buffer,"#<data>.W");
|
||||
break;
|
||||
case sz_long:
|
||||
strcpy (buffer,"#<data>.L");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case imm0:
|
||||
strcpy (buffer,"#<data>.B");
|
||||
break;
|
||||
case imm1:
|
||||
strcpy (buffer,"#<data>.W");
|
||||
break;
|
||||
case imm2:
|
||||
strcpy (buffer,"#<data>.L");
|
||||
break;
|
||||
case immi:
|
||||
strcpy (buffer,"#<data>");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char *get_instruction_string (unsigned int opcode)
|
||||
{
|
||||
static char out[100];
|
||||
struct instr *ins;
|
||||
|
||||
strcpy (out, get_instruction_name (opcode));
|
||||
|
||||
ins = &table68k[opcode];
|
||||
if (ins->size == sz_byte)
|
||||
strcat (out,".B");
|
||||
if (ins->size == sz_word)
|
||||
strcat (out,".W");
|
||||
if (ins->size == sz_long)
|
||||
strcat (out,".L");
|
||||
strcat (out," ");
|
||||
if (ins->suse)
|
||||
strcat (out, get_ea_string (amodes(ins->smode), wordsizes(ins->size)));
|
||||
if (ins->duse) {
|
||||
if (ins->suse)
|
||||
strcat (out,",");
|
||||
strcat (out, get_ea_string (amodes(ins->dmode), wordsizes(ins->size)));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* 2002 MJ */
|
||||
#ifndef READCPU_H
|
||||
#define READCPU_H
|
||||
|
||||
|
@ -6,12 +5,12 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ENUMDECL {
|
||||
Dreg, Areg, Aind, Aipi, Apdi, Ad16, Ad8r,
|
||||
absw, absl, PC16, PC8r, imm, imm0, imm1, imm2, immi, am_unknown, am_illg
|
||||
} amodes;
|
||||
} ENUMNAME (amodes);
|
||||
|
||||
typedef enum {
|
||||
ENUMDECL {
|
||||
i_ILLG,
|
||||
|
||||
i_OR, i_AND, i_EOR, i_ORSR, i_ANDSR, i_EORSR,
|
||||
|
@ -36,42 +35,43 @@ typedef enum {
|
|||
i_PACK, i_UNPK, i_TAS, i_BKPT, i_CALLM, i_RTM, i_TRAPcc, i_MOVES,
|
||||
i_FPP, i_FDBcc, i_FScc, i_FTRAPcc, i_FBcc, i_FSAVE, i_FRESTORE,
|
||||
i_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16,
|
||||
i_MMUOP, i_EMULOP_RETURN, i_EMULOP, i_NATFEAT_ID, i_NATFEAT_CALL
|
||||
} instrmnem;
|
||||
i_MMUOP,
|
||||
i_EMULOP_RETURN, i_EMULOP
|
||||
} ENUMNAME (instrmnem);
|
||||
|
||||
extern struct mnemolookup {
|
||||
instrmnem mnemo;
|
||||
const char *name;
|
||||
} lookuptab[];
|
||||
|
||||
typedef enum {
|
||||
ENUMDECL {
|
||||
sz_byte, sz_word, sz_long
|
||||
} wordsizes;
|
||||
} ENUMNAME (wordsizes);
|
||||
|
||||
typedef enum {
|
||||
fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp,
|
||||
fa_isbranch
|
||||
} flagaffect;
|
||||
ENUMDECL {
|
||||
fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp
|
||||
} ENUMNAME (flagaffect);
|
||||
|
||||
typedef enum {
|
||||
ENUMDECL {
|
||||
fu_used, fu_unused, fu_maybecc, fu_unknown, fu_isjmp
|
||||
} flaguse;
|
||||
} ENUMNAME (flaguse);
|
||||
|
||||
typedef enum {
|
||||
fl_normal = 0,
|
||||
ENUMDECL {
|
||||
fl_normal = 0,
|
||||
fl_branch = 1,
|
||||
fl_jump = 2,
|
||||
fl_return = 3,
|
||||
fl_trap = 4,
|
||||
fl_const_jump = 8,
|
||||
/* Instructions that can trap don't mark the end of a block */
|
||||
fl_end_block = 3
|
||||
} cflow_t;
|
||||
fl_jump = 2,
|
||||
fl_return = 3,
|
||||
fl_trap = 4,
|
||||
fl_const_jump = 8,
|
||||
|
||||
/* Instructions that can trap don't mark the end of a block */
|
||||
fl_end_block = 3
|
||||
} ENUMNAME (cflow_t);
|
||||
|
||||
typedef enum {
|
||||
ENUMDECL {
|
||||
bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK,
|
||||
bits, bitS, bitd, bitD, bitr, bitR, bitz, bitE, bitp, lastbit
|
||||
} bitvals;
|
||||
} ENUMNAME (bitvals);
|
||||
|
||||
struct instr_def {
|
||||
unsigned int bits;
|
||||
|
@ -84,7 +84,7 @@ struct instr_def {
|
|||
unsigned int flaguse:3;
|
||||
unsigned int flagset:3;
|
||||
} flaginfo[5];
|
||||
unsigned char cflow;
|
||||
unsigned char cflow;
|
||||
unsigned char sduse;
|
||||
const char *opcstr;
|
||||
};
|
||||
|
@ -103,15 +103,15 @@ extern struct instr {
|
|||
unsigned int mnemo:8;
|
||||
unsigned int cc:4;
|
||||
unsigned int plev:2;
|
||||
wordsizes size:2;
|
||||
amodes smode:5;
|
||||
unsigned int size:2;
|
||||
unsigned int smode:5;
|
||||
unsigned int stype:3;
|
||||
amodes dmode:5;
|
||||
unsigned int dmode:5;
|
||||
unsigned int suse:1;
|
||||
unsigned int duse:1;
|
||||
unsigned int unused1:1;
|
||||
unsigned int clev:3;
|
||||
unsigned int cflow:3;
|
||||
unsigned int cflow:3;
|
||||
unsigned int unused2:2;
|
||||
} *table68k;
|
||||
|
||||
|
@ -120,8 +120,11 @@ extern void do_merges (void);
|
|||
extern int get_no_mismatches (void);
|
||||
extern int nr_cpuop_funcs;
|
||||
|
||||
extern const char *get_instruction_name (unsigned int opcode);
|
||||
extern const char *get_instruction_string (unsigned int opcode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* READCPU_H */
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
/*
|
||||
* readcpu.cpp must be compiled twice, once for the generator program
|
||||
* and once for the actual executable
|
||||
*/
|
||||
#include "readcpu.cpp"
|
|
@ -1,116 +0,0 @@
|
|||
/* 2001 MJ */
|
||||
|
||||
#ifndef REGISTERS_H
|
||||
#define REGISTERS_H
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "spcflags.h"
|
||||
typedef char flagtype;
|
||||
|
||||
|
||||
struct xttrx {
|
||||
uae_u32 log_addr_base : 8;
|
||||
uae_u32 log_addr_mask : 8;
|
||||
uae_u32 enable : 1;
|
||||
uae_u32 s_field : 2;
|
||||
uae_u32 : 3;
|
||||
uae_u32 usr1 : 1;
|
||||
uae_u32 usr0 : 1;
|
||||
uae_u32 : 1;
|
||||
uae_u32 cmode : 2;
|
||||
uae_u32 : 2;
|
||||
uae_u32 write : 1;
|
||||
uae_u32 : 2;
|
||||
};
|
||||
|
||||
struct mmusr_t {
|
||||
uae_u32 phys_addr : 20;
|
||||
uae_u32 bus_err : 1;
|
||||
uae_u32 global : 1;
|
||||
uae_u32 usr1 : 1;
|
||||
uae_u32 usr0 : 1;
|
||||
uae_u32 super : 1;
|
||||
uae_u32 cmode : 2;
|
||||
uae_u32 modif : 1;
|
||||
uae_u32 : 1;
|
||||
uae_u32 write : 1;
|
||||
uae_u32 ttrhit : 1;
|
||||
uae_u32 resident : 1;
|
||||
};
|
||||
|
||||
struct log_addr4 {
|
||||
uae_u32 rif : 7;
|
||||
uae_u32 pif : 7;
|
||||
uae_u32 paif : 6;
|
||||
uae_u32 poff : 12;
|
||||
};
|
||||
|
||||
struct log_addr8 {
|
||||
uae_u32 rif : 7;
|
||||
uae_u32 pif : 7;
|
||||
uae_u32 paif : 5;
|
||||
uae_u32 poff : 13;
|
||||
};
|
||||
|
||||
extern struct regstruct
|
||||
{
|
||||
uae_u32 regs[16];
|
||||
uaecptr usp,isp,msp;
|
||||
uae_u16 sr;
|
||||
flagtype t1;
|
||||
flagtype t0;
|
||||
flagtype s;
|
||||
flagtype m;
|
||||
flagtype x;
|
||||
flagtype stopped;
|
||||
int intmask;
|
||||
|
||||
uae_u32 pc;
|
||||
uae_u32 fault_pc;
|
||||
uae_u8 *pc_p;
|
||||
uae_u8 *pc_oldp;
|
||||
|
||||
uae_u32 vbr,sfc,dfc;
|
||||
|
||||
volatile uae_u32 spcflags;
|
||||
|
||||
#if 0
|
||||
uae_u32 kick_mask;
|
||||
|
||||
/* Fellow sources say this is 4 longwords. That's impossible. It needs
|
||||
* to be at least a longword. The HRM has some cryptic comment about two
|
||||
* instructions being on the same longword boundary.
|
||||
* The way this is implemented now seems like a good compromise.
|
||||
*/
|
||||
uae_u32 prefetch;
|
||||
#endif
|
||||
|
||||
/* MMU reg*/
|
||||
uae_u32 urp,srp;
|
||||
uae_u32 tc;
|
||||
|
||||
int mmu_enabled; /* flagtype tce; */
|
||||
int mmu_pagesize_8k; /* flagtype tcp; */
|
||||
|
||||
uae_u32 dtt0,dtt1,itt0,itt1;
|
||||
uae_u32 mmusr;
|
||||
|
||||
uae_u32 mmu_fslw, mmu_fault_addr;
|
||||
uae_u16 mmu_ssw;
|
||||
uae_u32 wb3_data;
|
||||
uae_u16 wb3_status;
|
||||
|
||||
/* Cache reg*/
|
||||
uae_u32 cacr,caar;
|
||||
} regs, lastint_regs;
|
||||
|
||||
static inline uaecptr m68k_getpc (void)
|
||||
{
|
||||
#ifdef FULLMMU
|
||||
return regs.pc;
|
||||
#else
|
||||
return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,10 +1,24 @@
|
|||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* MC68000 emulation
|
||||
*
|
||||
* Copyright 1995 Bernd Schmidt
|
||||
*/
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* MC68000 emulation
|
||||
*
|
||||
* Copyright 1995 Bernd Schmidt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef SPCFLAGS_H
|
||||
#define SPCFLAGS_H
|
||||
|
@ -12,42 +26,31 @@
|
|||
typedef uae_u32 spcflags_t;
|
||||
|
||||
enum {
|
||||
SPCFLAG_STOP = 0x01,
|
||||
SPCFLAG_INT = 0x02,
|
||||
SPCFLAG_BRK = 0x04,
|
||||
SPCFLAG_TRACE = 0x08,
|
||||
SPCFLAG_DOTRACE = 0x10,
|
||||
SPCFLAG_DOINT = 0x20,
|
||||
#ifdef USE_JIT
|
||||
SPCFLAG_JIT_END_COMPILE = 0x40,
|
||||
SPCFLAG_JIT_EXEC_RETURN = 0x80,
|
||||
SPCFLAG_STOP = 0x01,
|
||||
SPCFLAG_INT = 0x02,
|
||||
SPCFLAG_BRK = 0x04,
|
||||
SPCFLAG_TRACE = 0x08,
|
||||
SPCFLAG_DOTRACE = 0x10,
|
||||
SPCFLAG_DOINT = 0x20,
|
||||
#if USE_JIT
|
||||
SPCFLAG_JIT_END_COMPILE = 0x40,
|
||||
SPCFLAG_JIT_EXEC_RETURN = 0x80,
|
||||
#else
|
||||
SPCFLAG_JIT_END_COMPILE = 0,
|
||||
SPCFLAG_JIT_EXEC_RETURN = 0,
|
||||
SPCFLAG_JIT_END_COMPILE = 0,
|
||||
SPCFLAG_JIT_EXEC_RETURN = 0,
|
||||
#endif
|
||||
SPCFLAG_VBL = 0x100,
|
||||
SPCFLAG_MFP = 0x200,
|
||||
SPCFLAG_INT3 = 0x800,
|
||||
SPCFLAG_INT5 = 0x1000,
|
||||
SPCFLAG_SCC = 0x2000,
|
||||
// SPCFLAG_MODE_CHANGE = 0x4000,
|
||||
SPCFLAG_ALL = SPCFLAG_STOP
|
||||
| SPCFLAG_INT
|
||||
| SPCFLAG_BRK
|
||||
| SPCFLAG_TRACE
|
||||
| SPCFLAG_DOTRACE
|
||||
| SPCFLAG_DOINT
|
||||
| SPCFLAG_JIT_END_COMPILE
|
||||
| SPCFLAG_JIT_EXEC_RETURN
|
||||
| SPCFLAG_INT3
|
||||
| SPCFLAG_VBL
|
||||
| SPCFLAG_INT5
|
||||
| SPCFLAG_SCC
|
||||
| SPCFLAG_MFP
|
||||
,
|
||||
|
||||
|
||||
SPCFLAG_ALL = SPCFLAG_STOP
|
||||
| SPCFLAG_INT
|
||||
| SPCFLAG_BRK
|
||||
| SPCFLAG_TRACE
|
||||
| SPCFLAG_DOTRACE
|
||||
| SPCFLAG_DOINT
|
||||
| SPCFLAG_JIT_END_COMPILE
|
||||
| SPCFLAG_JIT_EXEC_RETURN
|
||||
,
|
||||
|
||||
SPCFLAG_ALL_BUT_EXEC_RETURN = SPCFLAG_ALL & ~SPCFLAG_JIT_EXEC_RETURN
|
||||
|
||||
};
|
||||
|
||||
#define SPCFLAGS_TEST(m) \
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
% J: immediate 0..15
|
||||
% k: immediate 0..7
|
||||
% K: immediate 0..63
|
||||
% p: immediate 0..3 (CINV and CPUSH: cache field)
|
||||
% p: immediate 0..3 (CINV and CPUSH instructions: Cache Field)
|
||||
% s: source mode
|
||||
% S: source reg
|
||||
% d: dest mode
|
||||
|
@ -28,15 +28,14 @@
|
|||
% ArP: --> (Ar)+
|
||||
% L: --> (xxx.L)
|
||||
%
|
||||
% Fields on a line:
|
||||
% 16 chars bitpattern :
|
||||
% CPU level / privildge level :
|
||||
% Fields on a line:
|
||||
% 16 chars bitpattern :
|
||||
% CPU level / privilege level :
|
||||
% CPU level 0: 68000
|
||||
% 1: 68010
|
||||
% 2: 68020
|
||||
% 3: 68020/68881
|
||||
% 4: 68040
|
||||
% 5: 68060
|
||||
% privilege level 0: not privileged
|
||||
% 1: unprivileged only on 68000 (check regs.s)
|
||||
% 2: privileged (check regs.s)
|
||||
|
@ -47,10 +46,8 @@
|
|||
% 0 means flag reset
|
||||
% 1 means flag set
|
||||
% ? means programmer was too lazy to check or instruction may trap
|
||||
% + means instruction is conditional branch (ignored, only for sync)
|
||||
% / means instruction is unconditional branch/call (ignored, only for sync)
|
||||
% x means flag is unknown and well-behaved programs shouldn't check it
|
||||
% everything else means flag set/used
|
||||
% x means flag is unknown and well-behaved programs shouldn't check it
|
||||
%
|
||||
% Control flow
|
||||
% two letters, combination of
|
||||
|
@ -111,7 +108,7 @@
|
|||
0011 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.W s,d[Areg]
|
||||
0011 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.W s,d[!Areg]
|
||||
|
||||
0100 0000 zzdd dDDD:00:XNZVC:X-Z--:--:30: NEGX.z d[!Areg]
|
||||
0100 0000 zzdd dDDD:00:XxZxC:X-Z--:--:30: NEGX.z d[!Areg]
|
||||
0100 0000 11dd dDDD:01:-----:XNZVC:T-:10: MVSR2.W d[!Areg]
|
||||
0100 0010 zzdd dDDD:00:-0100:-----:--:20: CLR.z d[!Areg]
|
||||
0100 0010 11dd dDDD:10:-----:XNZVC:--:10: MVSR2.B d[!Areg]
|
||||
|
@ -122,13 +119,13 @@
|
|||
0100 1000 0000 1rrr:20:-----:-----:--:31: LINK.L Ar,#2
|
||||
0100 1000 00dd dDDD:00:X?Z?C:X-Z--:--:30: NBCD.B d[!Areg]
|
||||
0100 1000 0100 1kkk:20:-----:-----:T-:10: BKPT #k
|
||||
0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg]
|
||||
0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg]
|
||||
0100 1000 01ss sSSS:00:-----:-----:--:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd]
|
||||
0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg]
|
||||
0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg]
|
||||
0100 1000 10dd dDDD:00:-----:-----:--:02: MVMLE.W #1,d[!Dreg,Areg,Aipi]
|
||||
0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg]
|
||||
0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg]
|
||||
0100 1000 11dd dDDD:00:-----:-----:--:02: MVMLE.L #1,d[!Dreg,Areg,Aipi]
|
||||
0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg]
|
||||
0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg]
|
||||
0100 1010 zzss sSSS:00:-NZ00:-----:--:10: TST.z s
|
||||
0100 1010 11dd dDDD:00:-NZ00:-----:--:30: TAS.B d[!Areg]
|
||||
0100 1010 1111 1100:00:-----:-----:T-:00: ILLEGAL
|
||||
|
@ -151,24 +148,21 @@
|
|||
0100 1110 0111 0111:00:XNZVC:-----:-R:00: RTR
|
||||
0100 1110 0111 1010:12:-----:-----:T-:10: MOVEC2 #1
|
||||
0100 1110 0111 1011:12:-----:-----:T-:10: MOVE2C #1
|
||||
0100 1110 10ss sSSS:00://///://///:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd]
|
||||
0100 1110 10ss sSSS:00:-----:-----:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd]
|
||||
0100 rrr1 00ss sSSS:00:-N???:-----:T-:11: CHK.L s[!Areg],Dr
|
||||
0100 rrr1 10ss sSSS:00:-N???:-----:T-:11: CHK.W s[!Areg],Dr
|
||||
0100 1110 11ss sSSS:00://///://///:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd]
|
||||
0100 1110 11ss sSSS:00:-----:-----:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd]
|
||||
0100 rrr1 11ss sSSS:00:-----:-----:--:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar
|
||||
|
||||
% This variant of ADDQ is word and long sized only
|
||||
0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg]
|
||||
0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg]
|
||||
0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg]
|
||||
0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg]
|
||||
0101 jjj0 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #j,d[!Areg]
|
||||
|
||||
% This variant of SUBQ is word and long sized only
|
||||
0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg]
|
||||
0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg]
|
||||
0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg]
|
||||
0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg]
|
||||
0101 jjj1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #j,d[!Areg]
|
||||
|
||||
0101 cccc 1100 1rrr:00:-----:-++++:-B:31: DBcc.W Dr,#1
|
||||
0101 cccc 11dd dDDD:00:-----:-++++:--:20: Scc.B d[!Areg]
|
||||
0101 cccc 1100 1rrr:00:-----:-????:-B:31: DBcc.W Dr,#1
|
||||
0101 cccc 11dd dDDD:00:-----:-????:--:20: Scc.B d[!Areg]
|
||||
0101 cccc 1111 1010:20:-----:-????:T-:10: TRAPcc #1
|
||||
0101 cccc 1111 1011:20:-----:-????:T-:10: TRAPcc #2
|
||||
0101 cccc 1111 1100:20:-----:-????:T-:00: TRAPcc
|
||||
|
@ -176,30 +170,30 @@
|
|||
% Bxx.L is 68020 only, but setting the CPU level to 2 would give illegal
|
||||
% instruction exceptions when compiling a 68000 only emulation, which isn't
|
||||
% what we want either.
|
||||
0110 0001 0000 0000:00://///://///:-B:40: BSR.W #1
|
||||
0110 0001 IIII IIII:00://///://///:-B:40: BSR.B #i
|
||||
0110 0001 1111 1111:00://///://///:-B:40: BSR.L #2
|
||||
0110 CCCC 0000 0000:00:-----:-++++:-B:40: Bcc.W #1
|
||||
0110 CCCC IIII IIII:00:-----:-++++:-B:40: Bcc.B #i
|
||||
0110 CCCC 1111 1111:00:-----:-++++:-B:40: Bcc.L #2
|
||||
0110 0001 0000 0000:00:-----:-----:-B:40: BSR.W #1
|
||||
0110 0001 IIII IIII:00:-----:-----:-B:40: BSR.B #i
|
||||
0110 0001 1111 1111:00:-----:-----:-B:40: BSR.L #2
|
||||
0110 CCCC 0000 0000:00:-----:-????:-B:40: Bcc.W #1
|
||||
0110 CCCC IIII IIII:00:-----:-????:-B:40: Bcc.B #i
|
||||
0110 CCCC 1111 1111:00:-----:-????:-B:40: Bcc.L #2
|
||||
|
||||
0111 rrr0 iiii iiii:00:-NZ00:-----:--:12: MOVE.L #i,Dr
|
||||
|
||||
1000 rrr0 zzss sSSS:00:-NZ00:-----:--:13: OR.z s[!Areg],Dr
|
||||
1000 rrr0 11ss sSSS:00:-NZV0:-----:T-:13: DIVU.W s[!Areg],Dr
|
||||
1000 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: SBCD.B d[Dreg],Dr
|
||||
1000 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp
|
||||
1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Dreg],Dr
|
||||
1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp
|
||||
1000 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: OR.z Dr,d[!Areg,Dreg]
|
||||
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr
|
||||
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp
|
||||
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr
|
||||
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp
|
||||
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr
|
||||
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp
|
||||
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr
|
||||
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp
|
||||
1000 rrr1 11ss sSSS:00:-NZV0:-----:T-:13: DIVS.W s[!Areg],Dr
|
||||
|
||||
1001 rrr0 zzss sSSS:00:XNZVC:-----:--:13: SUB.z s,Dr
|
||||
1001 rrr0 11ss sSSS:00:-----:-----:--:13: SUBA.W s,Ar
|
||||
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr
|
||||
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp
|
||||
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr
|
||||
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp
|
||||
1001 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z Dr,d[!Areg,Dreg]
|
||||
1001 rrr1 11ss sSSS:00:-----:-----:--:13: SUBA.L s,Ar
|
||||
|
||||
|
@ -211,18 +205,18 @@
|
|||
|
||||
1100 rrr0 zzss sSSS:00:-NZ00:-----:--:13: AND.z s[!Areg],Dr
|
||||
1100 rrr0 11ss sSSS:00:-NZ00:-----:--:13: MULU.W s[!Areg],Dr
|
||||
1100 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: ABCD.B d[Dreg],Dr
|
||||
1100 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp
|
||||
1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Dreg],Dr
|
||||
1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp
|
||||
1100 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: AND.z Dr,d[!Areg,Dreg]
|
||||
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg]
|
||||
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg]
|
||||
1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg]
|
||||
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg]
|
||||
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg]
|
||||
1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg]
|
||||
1100 rrr1 11ss sSSS:00:-NZ00:-----:--:13: MULS.W s[!Areg],Dr
|
||||
|
||||
1101 rrr0 zzss sSSS:00:XNZVC:-----:--:13: ADD.z s,Dr
|
||||
1101 rrr0 11ss sSSS:00:-----:-----:--:13: ADDA.W s,Ar
|
||||
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr
|
||||
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp
|
||||
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr
|
||||
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp
|
||||
1101 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z Dr,d[!Areg,Dreg]
|
||||
1101 rrr1 11ss sSSS:00:-----:-----:--:13: ADDA.L s,Ar
|
||||
|
||||
|
@ -230,8 +224,8 @@
|
|||
1110 jjjf zz00 1RRR:00:XNZ0C:-----:--:13: LSf.z #j,DR
|
||||
1110 jjjf zz01 0RRR:00:XNZ0C:X----:--:13: ROXf.z #j,DR
|
||||
1110 jjjf zz01 1RRR:00:-NZ0C:-----:--:13: ROf.z #j,DR
|
||||
1110 rrrf zz10 0RRR:00:XNZVC:X----:--:13: ASf.z Dr,DR
|
||||
1110 rrrf zz10 1RRR:00:XNZ0C:X----:--:13: LSf.z Dr,DR
|
||||
1110 rrrf zz10 0RRR:00:XNZVC:-----:--:13: ASf.z Dr,DR
|
||||
1110 rrrf zz10 1RRR:00:XNZ0C:-----:--:13: LSf.z Dr,DR
|
||||
1110 rrrf zz11 0RRR:00:XNZ0C:X----:--:13: ROXf.z Dr,DR
|
||||
1110 rrrf zz11 1RRR:00:-NZ0C:-----:--:13: ROf.z Dr,DR
|
||||
1110 000f 11dd dDDD:00:XNZVC:-----:--:13: ASfW.W d[!Dreg,Areg]
|
||||
|
@ -261,6 +255,7 @@
|
|||
1111 0011 01ss sSSS:32:-----:-----:--:10: FRESTORE s[!Dreg,Areg,Apdi,Immd]
|
||||
|
||||
% 68040 instructions
|
||||
1111 0101 iiii iSSS:40:-----:-----:T-:11: MMUOP #i,s
|
||||
1111 0100 pp00 1rrr:42:-----:-----:T-:02: CINVL #p,Ar
|
||||
1111 0100 pp01 0rrr:42:-----:-----:T-:02: CINVP #p,Ar
|
||||
1111 0100 pp01 1rrr:42:-----:-----:T-:00: CINVA #p
|
||||
|
@ -269,18 +264,11 @@
|
|||
1111 0100 pp11 1rrr:42:-----:-----:T-:00: CPUSHA #p
|
||||
% destination register number is encoded in the following word
|
||||
1111 0110 0010 0rrr:40:-----:-----:--:12: MOVE16 ArP,AxP
|
||||
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],Al
|
||||
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Areg-Aipi]
|
||||
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],Al
|
||||
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Aipi-Aind]
|
||||
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],L
|
||||
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Areg-Aipi]
|
||||
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],L
|
||||
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Aipi-Aind]
|
||||
|
||||
% MMU disabled
|
||||
% 1111 0101 iiii iSSS:42:?????:?????:T-:11: MMUOP #i,s
|
||||
|
||||
% EmulOp instructions (deprecated, to be removed)
|
||||
0111 0001 0000 0000:02:-----:-----:-R:00: EMULOP_RETURN
|
||||
0111 0001 EEEE EEEE:02:-----:-----:-J:10: EMULOP #E
|
||||
|
||||
% NatFea instructions (do I have the srcaddr correct?) disabled
|
||||
% 0111 0011 0000 0000:00:-----:-----:-J:00: NATFEAT_ID
|
||||
% 0111 0011 0000 0001:00:-----:-----:-J:00: NATFEAT_CALL
|
||||
% EmulOp instructions
|
||||
0111 0001 0000 0000:00:-----:-----:-R:00: EMULOP_RETURN
|
||||
0111 0001 EEEE EEEE:00:-----:-----:-J:10: EMULOP #E
|
||||
|
|
Loading…
Reference in New Issue