Back to BasiliskII uae_cpu but with ARAnyM JIT

This commit is contained in:
uyjulian 2018-04-22 20:39:37 -05:00
parent 1758ef58b5
commit 77e20bda2a
No known key found for this signature in database
GPG Key ID: FEA459A8CA14685B
78 changed files with 4487 additions and 10985 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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);

View File

@ -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
*/

View File

@ -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) {

View File

@ -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);
}

View File

@ -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)

View File

@ -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

View File

@ -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() {}

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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

View File

@ -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(&regs.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;

View File

@ -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

View File

@ -50,7 +50,7 @@
*/
#define CC_FOR_BUILD 1
#include "sysconfig.h"
// #include "sysconfig.h"
#include "sysdeps.h"
#include "readcpu.h"

View File

@ -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

View File

@ -1,5 +0,0 @@
/*
* cpudefs.cpp must be compiled twice, once for the generator program
* and once for the actual executable
*/
#include "cpudefs.cpp"

View File

@ -1,2 +0,0 @@
#define PART_1
#include "cpuemu.cpp"

View File

@ -1,3 +0,0 @@
#define NOFLAGS 1
#define PART_1
#include "cpuemu.cpp"

View File

@ -1,2 +0,0 @@
#define PART_2
#include "cpuemu.cpp"

View File

@ -1,3 +0,0 @@
#define NOFLAGS 1
#define PART_2
#include "cpuemu.cpp"

View File

@ -1,2 +0,0 @@
#define PART_3
#include "cpuemu.cpp"

View File

@ -1,3 +0,0 @@
#define NOFLAGS 1
#define PART_3
#include "cpuemu.cpp"

View File

@ -1,2 +0,0 @@
#define PART_4
#include "cpuemu.cpp"

View File

@ -1,3 +0,0 @@
#define NOFLAGS 1
#define PART_4
#include "cpuemu.cpp"

View File

@ -1,2 +0,0 @@
#define PART_5
#include "cpuemu.cpp"

View File

@ -1,4 +0,0 @@
#define NOFLAGS 1
#define PART_5
#include "cpuemu.cpp"

View File

@ -1,2 +0,0 @@
#define PART_6
#include "cpuemu.cpp"

View File

@ -1,3 +0,0 @@
#define NOFLAGS 1
#define PART_6
#include "cpuemu.cpp"

View File

@ -1,2 +0,0 @@
#define PART_7
#include "cpuemu.cpp"

View File

@ -1,3 +0,0 @@
#define NOFLAGS 1
#define PART_7
#include "cpuemu.cpp"

View File

@ -1,2 +0,0 @@
#define PART_8
#include "cpuemu.cpp"

View File

@ -1,3 +0,0 @@
#define NOFLAGS 1
#define PART_8
#include "cpuemu.cpp"

View File

@ -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

View File

@ -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 = &regs.itt0; break;
case TTR_I1: ttr = &regs.itt1; break;
case TTR_D0: ttr = &regs.dtt0; break;
case TTR_D1: ttr = &regs.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:
*/

View File

@ -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 = &current->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;
}

View File

@ -1,2 +0,0 @@
#define NOFLAGS 1
#include "cpustbl.cpp"

View File

@ -1,5 +0,0 @@
/*
* cpustbl.cpp must be compiled twice, once for the generator program
* and once for the actual executable
*/
#include "cpustbl.cpp"

View File

@ -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:
*/

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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 mantissas 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));
}

View File

@ -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 );

View File

@ -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)

View File

@ -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;
}
/* -------------------------------------------------------------------------- */

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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:
*/

View File

@ -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 */

View File

@ -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

View File

@ -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 *)&regs.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 *)&regs.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(&regs.prefetch);
return (do_get_mem_word (((uae_u16 *)&regs.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 *)&regs.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 (&regs.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 (&regs.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 (&regs.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 */

View File

@ -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 */
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -1,5 +0,0 @@
/*
* readcpu.cpp must be compiled twice, once for the generator program
* and once for the actual executable
*/
#include "readcpu.cpp"

View File

@ -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

View File

@ -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) \

View File

@ -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