diff --git a/BasiliskII/src/CrossPlatform/video_blit.h b/BasiliskII/src/CrossPlatform/video_blit.h index 9ca19ad6..1b6cb68b 100644 --- a/BasiliskII/src/CrossPlatform/video_blit.h +++ b/BasiliskII/src/CrossPlatform/video_blit.h @@ -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 */ diff --git a/BasiliskII/src/CrossPlatform/video_vosf.h b/BasiliskII/src/CrossPlatform/video_vosf.h index 148a9e6f..980ea34d 100644 --- a/BasiliskII/src/CrossPlatform/video_vosf.h +++ b/BasiliskII/src/CrossPlatform/video_vosf.h @@ -21,651 +21,4 @@ #ifndef VIDEO_VOSF_H #define VIDEO_VOSF_H -// Note: this file must be #include'd only in video_x.cpp -#ifdef ENABLE_VOSF - -#include "sigsegv.h" -#include "vm_alloc.h" - -// Glue for SDL and X11 support -#ifdef TEST_VOSF_PERFORMANCE -#define MONITOR_INIT /* nothing */ -#else -#ifdef USE_SDL_VIDEO -#define MONITOR_INIT SDL_monitor_desc &monitor -#define VIDEO_DRV_WIN_INIT driver_base *drv -#define VIDEO_DRV_DGA_INIT driver_base *drv -#define VIDEO_DRV_LOCK_PIXELS SDL_VIDEO_LOCK_SURFACE(drv->s) -#define VIDEO_DRV_UNLOCK_PIXELS SDL_VIDEO_UNLOCK_SURFACE(drv->s) -#define VIDEO_DRV_DEPTH drv->s->format->BitsPerPixel -#define VIDEO_DRV_WIDTH drv->s->w -#define VIDEO_DRV_HEIGHT drv->s->h -#define VIDEO_DRV_ROW_BYTES drv->s->pitch -#else -#ifdef SHEEPSHAVER -#define MONITOR_INIT /* nothing */ -#define VIDEO_DRV_WIN_INIT /* nothing */ -#define VIDEO_DRV_DGA_INIT /* nothing */ -#define VIDEO_DRV_WINDOW the_win -#define VIDEO_DRV_GC the_gc -#define VIDEO_DRV_IMAGE img -#define VIDEO_DRV_HAVE_SHM have_shm -#else -#define MONITOR_INIT X11_monitor_desc &monitor -#define VIDEO_DRV_WIN_INIT driver_window *drv -#define VIDEO_DRV_DGA_INIT driver_dga *drv -#define VIDEO_DRV_WINDOW drv->w -#define VIDEO_DRV_GC drv->gc -#define VIDEO_DRV_IMAGE drv->img -#define VIDEO_DRV_HAVE_SHM drv->have_shm -#endif -#define VIDEO_DRV_LOCK_PIXELS /* nothing */ -#define VIDEO_DRV_UNLOCK_PIXELS /* nothing */ -#define VIDEO_DRV_DEPTH VIDEO_DRV_IMAGE->depth -#define VIDEO_DRV_WIDTH VIDEO_DRV_IMAGE->width -#define VIDEO_DRV_HEIGHT VIDEO_DRV_IMAGE->height -#define VIDEO_DRV_ROW_BYTES VIDEO_DRV_IMAGE->bytes_per_line -#endif -#endif - -// Prototypes -static void vosf_do_set_dirty_area(uintptr first, uintptr last); -static void vosf_set_dirty_area(int x, int y, int w, int h, unsigned screen_width, unsigned screen_height, unsigned bytes_per_row); - -// Variables for Video on SEGV support -static uint8 *the_host_buffer; // Host frame buffer in VOSF mode - -struct ScreenPageInfo { - unsigned top, bottom; // Mapping between this virtual page and Mac scanlines -}; - -struct ScreenInfo { - uintptr memStart; // Start address aligned to page boundary - uint32 memLength; // Length of the memory addressed by the screen pages - - uintptr pageSize; // Size of a page - int pageBits; // Shift count to get the page number - uint32 pageCount; // Number of pages allocated to the screen - - bool dirty; // Flag: set if the frame buffer was touched - bool very_dirty; // Flag: set if the frame buffer was completely modified (e.g. colormap changes) - char * dirtyPages; // Table of flags set if page was altered - ScreenPageInfo * pageInfo; // Table of mappings page -> Mac scanlines -}; - -static ScreenInfo mainBuffer; - -#define PFLAG_SET_VALUE 0x00 -#define PFLAG_CLEAR_VALUE 0x01 -#define PFLAG_SET_VALUE_4 0x00000000 -#define PFLAG_CLEAR_VALUE_4 0x01010101 -#define PFLAG_SET(page) mainBuffer.dirtyPages[page] = PFLAG_SET_VALUE -#define PFLAG_CLEAR(page) mainBuffer.dirtyPages[page] = PFLAG_CLEAR_VALUE -#define PFLAG_ISSET(page) (mainBuffer.dirtyPages[page] == PFLAG_SET_VALUE) -#define PFLAG_ISCLEAR(page) (mainBuffer.dirtyPages[page] != PFLAG_SET_VALUE) - -#ifdef UNALIGNED_PROFITABLE -# define PFLAG_ISSET_4(page) (*((uint32 *)(mainBuffer.dirtyPages + (page))) == PFLAG_SET_VALUE_4) -# define PFLAG_ISCLEAR_4(page) (*((uint32 *)(mainBuffer.dirtyPages + (page))) == PFLAG_CLEAR_VALUE_4) -#else -# define PFLAG_ISSET_4(page) \ - PFLAG_ISSET(page ) && PFLAG_ISSET(page+1) \ - && PFLAG_ISSET(page+2) && PFLAG_ISSET(page+3) -# define PFLAG_ISCLEAR_4(page) \ - PFLAG_ISCLEAR(page ) && PFLAG_ISCLEAR(page+1) \ - && PFLAG_ISCLEAR(page+2) && PFLAG_ISCLEAR(page+3) -#endif - -// Set the selected page range [ first_page, last_page [ into the SET state -#define PFLAG_SET_RANGE(first_page, last_page) \ - memset(mainBuffer.dirtyPages + (first_page), PFLAG_SET_VALUE, \ - (last_page) - (first_page)) - -// Set the selected page range [ first_page, last_page [ into the CLEAR state -#define PFLAG_CLEAR_RANGE(first_page, last_page) \ - memset(mainBuffer.dirtyPages + (first_page), PFLAG_CLEAR_VALUE, \ - (last_page) - (first_page)) - -#define PFLAG_SET_ALL do { \ - PFLAG_SET_RANGE(0, mainBuffer.pageCount); \ - mainBuffer.dirty = true; \ -} while (0) - -#define PFLAG_CLEAR_ALL do { \ - PFLAG_CLEAR_RANGE(0, mainBuffer.pageCount); \ - mainBuffer.dirty = false; \ - mainBuffer.very_dirty = false; \ -} while (0) - -#define PFLAG_SET_VERY_DIRTY do { \ - mainBuffer.very_dirty = true; \ -} while (0) - -// Set the following macro definition to 1 if your system -// provides a really fast strchr() implementation -//#define HAVE_FAST_STRCHR 0 - -static inline unsigned find_next_page_set(unsigned page) -{ -#if HAVE_FAST_STRCHR - char *match = strchr(mainBuffer.dirtyPages + page, PFLAG_SET_VALUE); - return match ? match - mainBuffer.dirtyPages : mainBuffer.pageCount; -#else - while (PFLAG_ISCLEAR_4(page)) - page += 4; - while (PFLAG_ISCLEAR(page)) - page++; - return page; -#endif -} - -static inline unsigned find_next_page_clear(unsigned page) -{ -#if HAVE_FAST_STRCHR - char *match = strchr(mainBuffer.dirtyPages + page, PFLAG_CLEAR_VALUE); - return match ? match - mainBuffer.dirtyPages : mainBuffer.pageCount; -#else - while (PFLAG_ISSET_4(page)) - page += 4; - while (PFLAG_ISSET(page)) - page++; - return page; -#endif -} - -#if defined(HAVE_PTHREADS) -static pthread_mutex_t vosf_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect frame buffer (dirtyPages in fact) -#define LOCK_VOSF pthread_mutex_lock(&vosf_lock); -#define UNLOCK_VOSF pthread_mutex_unlock(&vosf_lock); -#elif defined(HAVE_SPINLOCKS) -static spinlock_t vosf_lock = SPIN_LOCK_UNLOCKED; // Mutex to protect frame buffer (dirtyPages in fact) -#define LOCK_VOSF spin_lock(&vosf_lock) -#define UNLOCK_VOSF spin_unlock(&vosf_lock) -#else -#define LOCK_VOSF -#define UNLOCK_VOSF -#endif - -static int log_base_2(uint32 x) -{ - uint32 mask = 0x80000000; - int l = 31; - while (l >= 0 && (x & mask) == 0) { - mask >>= 1; - l--; - } - return l; -} - -// Extend size to page boundary -static uint32 page_extend(uint32 size) -{ - const uint32 page_size = vm_get_page_size(); - const uint32 page_mask = page_size - 1; - return (size + page_mask) & ~page_mask; -} - - -/* - * Check if VOSF acceleration is profitable on this platform - */ - -#ifndef VOSF_PROFITABLE_TRIES -#define VOSF_PROFITABLE_TRIES VOSF_PROFITABLE_TRIES_DFL -#endif -const int VOSF_PROFITABLE_TRIES_DFL = 3; // Make 3 attempts for full screen update -const int VOSF_PROFITABLE_THRESHOLD = 16667/2; // 60 Hz (half of the quantum) - -static bool video_vosf_profitable(uint32 *duration_p = NULL, uint32 *n_page_faults_p = NULL) -{ - uint32 duration = 0; - uint32 n_tries = VOSF_PROFITABLE_TRIES; - const uint32 n_page_faults = mainBuffer.pageCount * n_tries; - -#ifdef SHEEPSHAVER - const bool accel = PrefsFindBool("gfxaccel"); -#else - const bool accel = false; -#endif - - for (uint32 i = 0; i < n_tries; i++) { - uint64 start = GetTicks_usec(); - for (uint32 p = 0; p < mainBuffer.pageCount; p++) { - uint8 *addr = (uint8 *)(mainBuffer.memStart + (p * mainBuffer.pageSize)); - if (accel) - vosf_do_set_dirty_area((uintptr)addr, (uintptr)addr + mainBuffer.pageSize - 1); - else - addr[0] = 0; // Trigger Screen_fault_handler() - } - duration += uint32(GetTicks_usec() - start); - - PFLAG_CLEAR_ALL; - mainBuffer.dirty = false; - if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0) - return false; - } - - if (duration_p) - *duration_p = duration; - if (n_page_faults_p) - *n_page_faults_p = n_page_faults; - - D(bug("Triggered %d page faults in %ld usec (%.1f usec per fault)\n", n_page_faults, duration, double(duration) / double(n_page_faults))); - return ((duration / n_tries) < (VOSF_PROFITABLE_THRESHOLD * (frame_skip ? frame_skip : 1))); -} - - -/* - * Initialize the VOSF system (mainBuffer structure, SIGSEGV handler) - */ - -static bool video_vosf_init(MONITOR_INIT) -{ - VIDEO_MODE_INIT_MONITOR; - - const uintptr page_size = vm_get_page_size(); - const uintptr page_mask = page_size - 1; - - // Round up frame buffer base to page boundary - mainBuffer.memStart = (((uintptr) the_buffer) + page_mask) & ~page_mask; - - // The frame buffer size shall already be aligned to page boundary (use page_extend) - mainBuffer.memLength = the_buffer_size; - - mainBuffer.pageSize = page_size; - mainBuffer.pageBits = log_base_2(mainBuffer.pageSize); - mainBuffer.pageCount = (mainBuffer.memLength + page_mask)/mainBuffer.pageSize; - - // The "2" more bytes requested are a safety net to insure the - // loops in the update routines will terminate. - // See "How can we deal with array overrun conditions ?" hereunder for further details. - mainBuffer.dirtyPages = (char *) malloc(mainBuffer.pageCount + 2); - if (mainBuffer.dirtyPages == NULL) - return false; - - PFLAG_CLEAR_ALL; - PFLAG_CLEAR(mainBuffer.pageCount); - PFLAG_SET(mainBuffer.pageCount+1); - - // Allocate and fill in pageInfo with start and end (inclusive) row in number of bytes - mainBuffer.pageInfo = (ScreenPageInfo *) malloc(mainBuffer.pageCount * sizeof(ScreenPageInfo)); - if (mainBuffer.pageInfo == NULL) - return false; - - uint32 a = 0; - for (unsigned i = 0; i < mainBuffer.pageCount; i++) { - unsigned y1 = a / VIDEO_MODE_ROW_BYTES; - if (y1 >= VIDEO_MODE_Y) - y1 = VIDEO_MODE_Y - 1; - - unsigned y2 = (a + mainBuffer.pageSize) / VIDEO_MODE_ROW_BYTES; - if (y2 >= VIDEO_MODE_Y) - y2 = VIDEO_MODE_Y - 1; - - mainBuffer.pageInfo[i].top = y1; - mainBuffer.pageInfo[i].bottom = y2; - - a += mainBuffer.pageSize; - if (a > mainBuffer.memLength) - a = mainBuffer.memLength; - } - - // We can now write-protect the frame buffer - if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0) - return false; - - // The frame buffer is sane, i.e. there is no write to it yet - mainBuffer.dirty = false; - return true; -} - - -/* - * Deinitialize VOSF system - */ - -static void video_vosf_exit(void) -{ - if (mainBuffer.pageInfo) { - free(mainBuffer.pageInfo); - mainBuffer.pageInfo = NULL; - } - if (mainBuffer.dirtyPages) { - free(mainBuffer.dirtyPages); - mainBuffer.dirtyPages = NULL; - } -} - - -/* - * Update VOSF state with specified dirty area - */ - -static void vosf_do_set_dirty_area(uintptr first, uintptr last) -{ - const int first_page = (first - mainBuffer.memStart) >> mainBuffer.pageBits; - const int last_page = (last - mainBuffer.memStart) >> mainBuffer.pageBits; - uint8 *addr = (uint8 *)(first & ~(mainBuffer.pageSize - 1)); - for (int i = first_page; i <= last_page; i++) { - if (PFLAG_ISCLEAR(i)) { - PFLAG_SET(i); - vm_protect(addr, mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE); - } - addr += mainBuffer.pageSize; - } -} - -static void vosf_set_dirty_area(int x, int y, int w, int h, unsigned screen_width, unsigned screen_height, unsigned bytes_per_row) -{ - if (x < 0) { - w -= -x; - x = 0; - } - if (y < 0) { - h -= -y; - y = 0; - } - if (w <= 0 || h <= 0) - return; - if (unsigned(x + w) > screen_width) - w -= unsigned(x + w) - screen_width; - if (unsigned(y + h) > screen_height) - h -= unsigned(y + h) - screen_height; - LOCK_VOSF; - if (bytes_per_row >= screen_width) { - const int bytes_per_pixel = bytes_per_row / screen_width; - if (bytes_per_row <= mainBuffer.pageSize) { - const uintptr a0 = mainBuffer.memStart + y * bytes_per_row + x * bytes_per_pixel; - const uintptr a1 = mainBuffer.memStart + (y + h - 1) * bytes_per_row + (x + w - 1) * bytes_per_pixel; - vosf_do_set_dirty_area(a0, a1); - } else { - for (int j = y; j < y + h; j++) { - const uintptr a0 = mainBuffer.memStart + j * bytes_per_row + x * bytes_per_pixel; - const uintptr a1 = a0 + (w - 1) * bytes_per_pixel; - vosf_do_set_dirty_area(a0, a1); - } - } - } else { - const int pixels_per_byte = screen_width / bytes_per_row; - if (bytes_per_row <= mainBuffer.pageSize) { - const uintptr a0 = mainBuffer.memStart + y * bytes_per_row + x / pixels_per_byte; - const uintptr a1 = mainBuffer.memStart + (y + h - 1) * bytes_per_row + (x + w - 1) / pixels_per_byte; - vosf_do_set_dirty_area(a0, a1); - } else { - for (int j = y; j < y + h; j++) { - const uintptr a0 = mainBuffer.memStart + j * bytes_per_row + x / pixels_per_byte; - const uintptr a1 = mainBuffer.memStart + j * bytes_per_row + (x + w - 1) / pixels_per_byte; - vosf_do_set_dirty_area(a0, a1); - } - } - } - mainBuffer.dirty = true; - UNLOCK_VOSF; -} - - -/* - * Screen fault handler - */ - -bool Screen_fault_handler(sigsegv_info_t *sip) -{ - const uintptr addr = (uintptr)sigsegv_get_fault_address(sip); - - /* Someone attempted to write to the frame buffer. Make it writeable - * now so that the data could actually be written to. It will be made - * read-only back in one of the screen update_*() functions. - */ - if (((uintptr)addr - mainBuffer.memStart) < mainBuffer.memLength) { - const int page = ((uintptr)addr - mainBuffer.memStart) >> mainBuffer.pageBits; - LOCK_VOSF; - if (PFLAG_ISCLEAR(page)) { - PFLAG_SET(page); - vm_protect((char *)(addr & ~(mainBuffer.pageSize - 1)), mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE); - } - mainBuffer.dirty = true; - UNLOCK_VOSF; - return true; - } - - /* Otherwise, we don't know how to handle the fault, let it crash */ - return false; -} - - -/* - * Update display for Windowed mode and VOSF - */ - -/* How can we deal with array overrun conditions ? - - The state of the framebuffer pages that have been touched are maintained - in the dirtyPages[] table. That table is (pageCount + 2) bytes long. - -Terminology - - "Last Page" denotes the pageCount-nth page, i.e. dirtyPages[pageCount - 1]. - "CLEAR Page Guard" refers to the page following the Last Page but is always - in the CLEAR state. "SET Page Guard" refers to the page following the CLEAR - Page Guard but is always in the SET state. - -Rough process - - The update routines must determine which pages have to be blitted to the - screen. This job consists in finding the first_page that was touched. - i.e. find the next page that is SET. Then, finding how many pages were - touched starting from first_page. i.e. find the next page that is CLEAR. - -There are two cases to check: - - - Last Page is CLEAR: find_next_page_set() will reach the SET Page Guard - but it is beyond the valid pageCount value. Therefore, we exit from the - update routine. - - - Last Page is SET: first_page equals (pageCount - 1) and - find_next_page_clear() will reach the CLEAR Page Guard. We blit the last - page to the screen. On the next iteration, page equals pageCount and - find_next_page_set() will reach the SET Page Guard. We still safely exit - from the update routine because the SET Page Guard position is greater - than pageCount. -*/ - -#ifndef TEST_VOSF_PERFORMANCE -static void update_display_window_vosf(VIDEO_DRV_WIN_INIT) -{ - VIDEO_MODE_INIT; - - unsigned page = 0; - for (;;) { - const unsigned first_page = find_next_page_set(page); - if (first_page >= mainBuffer.pageCount) - break; - - page = find_next_page_clear(first_page); - PFLAG_CLEAR_RANGE(first_page, page); - - // Make the dirty pages read-only again - const int32 offset = first_page << mainBuffer.pageBits; - const uint32 length = (page - first_page) << mainBuffer.pageBits; - vm_protect((char *)mainBuffer.memStart + offset, length, VM_PAGE_READ); - - // There is at least one line to update - const int y1 = mainBuffer.pageInfo[first_page].top; - const int y2 = mainBuffer.pageInfo[page - 1].bottom; - const int height = y2 - y1 + 1; - - // Update the_host_buffer - VIDEO_DRV_LOCK_PIXELS; - const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES; - const int dst_bytes_per_row = VIDEO_DRV_ROW_BYTES; - int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j; - for (j = y1; j <= y2; j++) { - Screen_blit(the_host_buffer + i2, the_buffer + i1, src_bytes_per_row); - i1 += src_bytes_per_row; - i2 += dst_bytes_per_row; - } - VIDEO_DRV_UNLOCK_PIXELS; - -#ifdef USE_SDL_VIDEO - SDL_UpdateRect(drv->s, 0, y1, VIDEO_MODE_X, height); -#else - if (VIDEO_DRV_HAVE_SHM) - XShmPutImage(x_display, VIDEO_DRV_WINDOW, VIDEO_DRV_GC, VIDEO_DRV_IMAGE, 0, y1, 0, y1, VIDEO_MODE_X, height, 0); - else - XPutImage(x_display, VIDEO_DRV_WINDOW, VIDEO_DRV_GC, VIDEO_DRV_IMAGE, 0, y1, 0, y1, VIDEO_MODE_X, height); -#endif - } - mainBuffer.dirty = false; -} -#endif - - -/* - * Update display for DGA mode and VOSF - * (only in Real or Direct Addressing mode) - */ - -#ifndef TEST_VOSF_PERFORMANCE -#if DIRECT_ADDRESSING -static void update_display_dga_vosf(VIDEO_DRV_DGA_INIT) -{ - VIDEO_MODE_INIT; - - // Compute number of bytes per row, take care to virtual screens - const int src_bytes_per_row = VIDEO_MODE_ROW_BYTES; - const int dst_bytes_per_row = TrivialBytesPerRow(VIDEO_MODE_X, DepthModeForPixelDepth(VIDEO_DRV_DEPTH)); - const int scr_bytes_per_row = VIDEO_DRV_ROW_BYTES; - assert(dst_bytes_per_row <= scr_bytes_per_row); - const int scr_bytes_left = scr_bytes_per_row - dst_bytes_per_row; - - // Full screen update requested? - if (mainBuffer.very_dirty) { - PFLAG_CLEAR_ALL; - vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ); - memcpy(the_buffer_copy, the_buffer, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y); - VIDEO_DRV_LOCK_PIXELS; - int i1 = 0, i2 = 0; - for (uint32_t j = 0; j < VIDEO_MODE_Y; j++) { - Screen_blit(the_host_buffer + i2, the_buffer + i1, src_bytes_per_row); - i1 += src_bytes_per_row; - i2 += scr_bytes_per_row; - } -#ifdef USE_SDL_VIDEO - SDL_UpdateRect(drv->s, 0, 0, VIDEO_MODE_X, VIDEO_MODE_Y); -#endif - VIDEO_DRV_UNLOCK_PIXELS; - return; - } - - // Setup partial blitter (use 64-pixel wide chunks) - const uint32 n_pixels = 64; - const uint32 n_chunks = VIDEO_MODE_X / n_pixels; - const uint32 n_pixels_left = VIDEO_MODE_X - (n_chunks * n_pixels); - const uint32 src_chunk_size = src_bytes_per_row / n_chunks; - const uint32 dst_chunk_size = dst_bytes_per_row / n_chunks; - const uint32 src_chunk_size_left = src_bytes_per_row - (n_chunks * src_chunk_size); - const uint32 dst_chunk_size_left = dst_bytes_per_row - (n_chunks * dst_chunk_size); - - unsigned page = 0; - uint32 last_scanline = uint32(-1); - for (;;) { - const unsigned first_page = find_next_page_set(page); - if (first_page >= mainBuffer.pageCount) - break; - - page = find_next_page_clear(first_page); - PFLAG_CLEAR_RANGE(first_page, page); - - // Make the dirty pages read-only again - const int32 offset = first_page << mainBuffer.pageBits; - const uint32 length = (page - first_page) << mainBuffer.pageBits; - vm_protect((char *)mainBuffer.memStart + offset, length, VM_PAGE_READ); - - // Optimized for scanlines, don't process overlapping lines again - uint32 y1 = mainBuffer.pageInfo[first_page].top; - uint32 y2 = mainBuffer.pageInfo[page - 1].bottom; - if (last_scanline != uint32(-1)) { - if (y1 <= last_scanline && ++y1 >= VIDEO_MODE_Y) - continue; - if (y2 <= last_scanline && ++y2 >= VIDEO_MODE_Y) - continue; - } - last_scanline = y2; - - // Update the_host_buffer and copy of the_buffer, one line at a time - uint32 i1 = y1 * src_bytes_per_row; - uint32 i2 = y1 * scr_bytes_per_row; -#ifdef USE_SDL_VIDEO - int bbi = 0; - SDL_Rect bb[3] = { - { Sint16(VIDEO_MODE_X), Sint16(y1), 0, 0 }, - { Sint16(VIDEO_MODE_X), -1, 0, 0 }, - { Sint16(VIDEO_MODE_X), -1, 0, 0 } - }; -#endif - VIDEO_DRV_LOCK_PIXELS; - for (uint32 j = y1; j <= y2; j++) { - for (uint32 i = 0; i < n_chunks; i++) { - if (memcmp(the_buffer_copy + i1, the_buffer + i1, src_chunk_size) != 0) { - memcpy(the_buffer_copy + i1, the_buffer + i1, src_chunk_size); - Screen_blit(the_host_buffer + i2, the_buffer + i1, src_chunk_size); -#ifdef USE_SDL_VIDEO - const int x = i * n_pixels; - if (x < bb[bbi].x) { - if (bb[bbi].w) - bb[bbi].w += bb[bbi].x - x; - else - bb[bbi].w = n_pixels; - bb[bbi].x = x; - } - else if (x >= bb[bbi].x + bb[bbi].w) - bb[bbi].w = x + n_pixels - bb[bbi].x; -#endif - } - i1 += src_chunk_size; - i2 += dst_chunk_size; - } - if (src_chunk_size_left && dst_chunk_size_left) { - if (memcmp(the_buffer_copy + i1, the_buffer + i1, src_chunk_size_left) != 0) { - memcpy(the_buffer_copy + i1, the_buffer + i1, src_chunk_size_left); - Screen_blit(the_host_buffer + i2, the_buffer + i1, src_chunk_size_left); - } - i1 += src_chunk_size_left; - i2 += dst_chunk_size_left; -#ifdef USE_SDL_VIDEO - const int x = n_chunks * n_pixels; - if (x < bb[bbi].x) { - if (bb[bbi].w) - bb[bbi].w += bb[bbi].x - x; - else - bb[bbi].w = n_pixels_left; - bb[bbi].x = x; - } - else if (x >= bb[bbi].x + bb[bbi].w) - bb[bbi].w = x + n_pixels_left - bb[bbi].x; -#endif - } - i2 += scr_bytes_left; -#ifdef USE_SDL_VIDEO - bb[bbi].h++; - if (bb[bbi].w && (j == y1 || j == y2 - 1 || j == y2)) { - bbi++; - assert(bbi <= 3); - if (j != y2) - bb[bbi].y = j + 1; - } -#endif - } -#ifdef USE_SDL_VIDEO - SDL_UpdateRects(drv->s, bbi, bb); -#endif - VIDEO_DRV_UNLOCK_PIXELS; - } - mainBuffer.dirty = false; -} -#endif -#endif - -#endif /* ENABLE_VOSF */ - #endif /* VIDEO_VOSF_H */ diff --git a/BasiliskII/src/SDL/video_sdl.cpp b/BasiliskII/src/SDL/video_sdl.cpp index 9b2855da..9158d729 100644 --- a/BasiliskII/src/SDL/video_sdl.cpp +++ b/BasiliskII/src/SDL/video_sdl.cpp @@ -67,19 +67,11 @@ using std::vector; static vector 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 &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 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::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 diff --git a/BasiliskII/src/Unix/CMakeLists.txt b/BasiliskII/src/Unix/CMakeLists.txt index 65a607f8..9bc6431f 100644 --- a/BasiliskII/src/Unix/CMakeLists.txt +++ b/BasiliskII/src/Unix/CMakeLists.txt @@ -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 diff --git a/BasiliskII/src/Unix/main_unix.cpp b/BasiliskII/src/Unix/main_unix.cpp index 3affe236..60824593 100644 --- a/BasiliskII/src/Unix/main_unix.cpp +++ b/BasiliskII/src/Unix/main_unix.cpp @@ -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 } diff --git a/BasiliskII/src/Unix/sysdeps.h b/BasiliskII/src/Unix/sysdeps.h index 56b7a71d..68deb7b6 100644 --- a/BasiliskII/src/Unix/sysdeps.h +++ b/BasiliskII/src/Unix/sysdeps.h @@ -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 header file. */ #define HAVE_ARPA_INET_H 1 diff --git a/BasiliskII/src/include/main.h b/BasiliskII/src/include/main.h index b55ddc6d..1ba7b6ac 100644 --- a/BasiliskII/src/include/main.h +++ b/BasiliskII/src/include/main.h @@ -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); diff --git a/BasiliskII/src/include/prefs.h b/BasiliskII/src/include/prefs.h index 216137f2..bce4a6e0 100644 --- a/BasiliskII/src/include/prefs.h +++ b/BasiliskII/src/include/prefs.h @@ -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 */ diff --git a/BasiliskII/src/prefs.cpp b/BasiliskII/src/prefs.cpp index 434992ce..27131b74 100644 --- a/BasiliskII/src/prefs.cpp +++ b/BasiliskII/src/prefs.cpp @@ -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) { diff --git a/BasiliskII/src/prefs_items.cpp b/BasiliskII/src/prefs_items.cpp index afb692b9..4a7f1a34 100644 --- a/BasiliskII/src/prefs_items.cpp +++ b/BasiliskII/src/prefs_items.cpp @@ -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); } diff --git a/BasiliskII/src/uae_cpu/Makefile.am b/BasiliskII/src/uae_cpu/Makefile.am deleted file mode 100644 index 0f27219d..00000000 --- a/BasiliskII/src/uae_cpu/Makefile.am +++ /dev/null @@ -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) diff --git a/BasiliskII/src/uae_cpu/aranym_glue.cpp b/BasiliskII/src/uae_cpu/aranym_glue.cpp deleted file mode 100644 index 7148d446..00000000 --- a/BasiliskII/src/uae_cpu/aranym_glue.cpp +++ /dev/null @@ -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 diff --git a/BasiliskII/src/uae_cpu/basilisk_glue.cpp b/BasiliskII/src/uae_cpu/basilisk_glue.cpp index 1b03160a..b29c7702 100644 --- a/BasiliskII/src/uae_cpu/basilisk_glue.cpp +++ b/BasiliskII/src/uae_cpu/basilisk_glue.cpp @@ -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() {} diff --git a/BasiliskII/src/uae_cpu/build68k.c b/BasiliskII/src/uae_cpu/build68k.c index e996758d..8ec3ab55 100644 --- a/BasiliskII/src/uae_cpu/build68k.c +++ b/BasiliskII/src/uae_cpu/build68k.c @@ -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 -#include -#include -#include #include -#undef abort +#include +#include + +#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; } diff --git a/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp b/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp index 32e6982a..24cfb548 100644 --- a/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp +++ b/BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp @@ -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) { diff --git a/BasiliskII/src/uae_cpu/compiler/compemu.h b/BasiliskII/src/uae_cpu/compiler/compemu.h index 6e3abb1e..15edd102 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu.h +++ b/BasiliskII/src/uae_cpu/compiler/compemu.h @@ -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 diff --git a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp index c7b94244..62fcfd36 100644 --- a/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp +++ b/BasiliskII/src/uae_cpu/compiler/compemu_support.cpp @@ -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(" : 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(" : 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(" : 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(" : 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(" : FP register aliasing : %s", str_on_off(USE_F_ALIAS)); jit_log(" : 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(" : block inlining : %s", str_on_off(follow_const_jumps)); jit_log(" : 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(" : translation cache size is less than %d KB. Disabling JIT.\n", MIN_CACHE_SIZE); + if (PrefsFindInt32("jitcachesize") < MIN_CACHE_SIZE) { + write_log(" : translation cache size is less than %d KB. Disabling JIT.\n", MIN_CACHE_SIZE); return false; } @@ -3579,6 +3587,8 @@ void alloc_cache(void) } } +extern void op_illg_1 (uae_u32 opcode) REGPARAM; + static void calc_checksum(blockinfo* bi, uae_u32* c1, uae_u32* c2) { uae_u32 k1 = 0; @@ -3869,7 +3879,7 @@ static inline void create_popalls(void) r=REG_PC_TMP; compemu_raw_mov_l_rm(r, uae_p32(®s.pc_p)); compemu_raw_and_l_ri(r,TAGMASK); - verify(sizeof(cache_tags[0]) == sizeof(void *)); + assert(sizeof(cache_tags[0]) == sizeof(void *)); compemu_raw_jmp_m_indexed(uae_p32(cache_tags), r, sizeof(void *)); /* now the exit points */ @@ -4009,7 +4019,7 @@ static bool merge_blacklist() #ifdef UAE const char *blacklist = ""; #else - const char *blacklist = bx_options.jit.jitblacklist; + const char *blacklist = PrefsFindString("jitblacklist"); #endif if (blacklist[0] != '\0') { const char *p = blacklist; @@ -4346,38 +4356,86 @@ void flush_icache(int n) #ifdef UAE static #endif -void flush_icache_range(uae_u32 start, uae_u32 length) +// void flush_icache_range(uae_u32 start, uae_u32 length) +// { +// if (!active) +// return; + +// #if LAZY_FLUSH_ICACHE_RANGE +// uae_u8 *start_p = get_real_address(start); +// blockinfo *bi = active; +// while (bi) { +// #if USE_CHECKSUM_INFO +// bool invalidate = false; +// for (checksum_info *csi = bi->csi; csi && !invalidate; csi = csi->next) +// invalidate = (((start_p - csi->start_p) < csi->length) || +// ((csi->start_p - start_p) < length)); +// #else +// // Assume system is consistent and would invalidate the right range +// const bool invalidate = (bi->pc_p - start_p) < length; +// #endif +// if (invalidate) { +// uae_u32 cl = cacheline(bi->pc_p); +// if (bi == cache_tags[cl + 1].bi) +// cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; +// bi->handler_to_use = (cpuop_func *)popall_execute_normal; +// set_dhtu(bi, bi->direct_pen); +// bi->status = BI_NEED_RECOMP; +// } +// bi = bi->next; +// } +// return; +// #else +// UNUSED(start); +// UNUSED(length); +// #endif +// flush_icache(-1); +// } + +void flush_icache_range(uae_u8 *start_p, uae_u32 length) { if (!active) return; #if LAZY_FLUSH_ICACHE_RANGE - uae_u8 *start_p = get_real_address(start); blockinfo *bi = active; while (bi) { #if USE_CHECKSUM_INFO - bool invalidate = false; - for (checksum_info *csi = bi->csi; csi && !invalidate; csi = csi->next) - invalidate = (((start_p - csi->start_p) < csi->length) || - ((csi->start_p - start_p) < length)); + bool candidate = false; + for (checksum_info *csi = bi->csi; csi; csi = csi->next) { + if (((start_p - csi->start_p) < csi->length) || + ((csi->start_p - start_p) < length)) { + candidate = true; + break; + } + } #else // Assume system is consistent and would invalidate the right range - const bool invalidate = (bi->pc_p - start_p) < length; + const bool candidate = (bi->pc_p - start_p) < length; #endif - if (invalidate) { - uae_u32 cl = cacheline(bi->pc_p); - if (bi == cache_tags[cl + 1].bi) - cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; - bi->handler_to_use = (cpuop_func *)popall_execute_normal; - set_dhtu(bi, bi->direct_pen); - bi->status = BI_NEED_RECOMP; - } + blockinfo *dbi = bi; bi = bi->next; + if (candidate) { + uae_u32 cl = cacheline(dbi->pc_p); + if (dbi->status == BI_INVALID || dbi->status == BI_NEED_RECOMP) { + if (dbi == cache_tags[cl+1].bi) + cache_tags[cl].handler = (cpuop_func *)popall_execute_normal; + dbi->handler_to_use = (cpuop_func *)popall_execute_normal; + set_dhtu(dbi, dbi->direct_pen); + dbi->status = BI_INVALID; + } + else { + if (dbi == cache_tags[cl+1].bi) + cache_tags[cl].handler = (cpuop_func *)popall_check_checksum; + dbi->handler_to_use = (cpuop_func *)popall_check_checksum; + set_dhtu(dbi, dbi->direct_pcc); + dbi->status = BI_NEED_CHECK; + } + remove_from_list(dbi); + add_to_dormant(dbi); + } } return; -#else - UNUSED(start); - UNUSED(length); #endif flush_icache(-1); } @@ -4631,7 +4689,7 @@ static void compile_block(cpu_history* pc_hist, int blocklen) comptbl=compfunctbl; } -#ifdef FLIGHT_RECORDER +#if FLIGHT_RECORDER { /* store also opcode to second register */ clobber_flags(); @@ -5008,7 +5066,7 @@ void exec_nostats(void) { for (;;) { uae_u32 opcode = GET_OPCODE; -#ifdef FLIGHT_RECORDER +#if FLIGHT_RECORDER m68k_record_step(m68k_getpc(), opcode); #endif (*cpufunctbl[opcode])(opcode); @@ -5038,7 +5096,7 @@ void execute_normal(void) for (;;) { /* Take note: This is the do-it-normal loop */ pc_hist[blocklen++].location = (uae_u16 *)regs.pc_p; uae_u32 opcode = GET_OPCODE; -#ifdef FLIGHT_RECORDER +#if FLIGHT_RECORDER m68k_record_step(m68k_getpc(), opcode); #endif (*cpufunctbl[opcode])(opcode); @@ -5082,7 +5140,7 @@ setjmpagain: for (;;) { if (quit_program > 0) { if (quit_program == 1) { -#ifdef FLIGHT_RECORDER +#if FLIGHT_RECORDER dump_flight_recorder(); #endif break; diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp.c b/BasiliskII/src/uae_cpu/compiler/gencomp.c index a7c4ee2b..febeddc9 100644 --- a/BasiliskII/src/uae_cpu/compiler/gencomp.c +++ b/BasiliskII/src/uae_cpu/compiler/gencomp.c @@ -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 diff --git a/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c b/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c index 13e2776e..e9bf9bb4 100644 --- a/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c +++ b/BasiliskII/src/uae_cpu/compiler/gencomp_arm.c @@ -50,7 +50,7 @@ */ #define CC_FOR_BUILD 1 -#include "sysconfig.h" +// #include "sysconfig.h" #include "sysdeps.h" #include "readcpu.h" diff --git a/BasiliskII/src/uae_cpu/cpu_emulation.h b/BasiliskII/src/uae_cpu/cpu_emulation.h index 2e926874..cd588ec1 100644 --- a/BasiliskII/src/uae_cpu/cpu_emulation.h +++ b/BasiliskII/src/uae_cpu/cpu_emulation.h @@ -1,7 +1,7 @@ /* - * cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.8 version) + * cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.10 version) * - * Basilisk II (C) 1997-1999 Christian Bauer + * Basilisk II (C) 1997-2008 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +21,8 @@ #ifndef CPU_EMULATION_H #define CPU_EMULATION_H +#include + /* * 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 diff --git a/BasiliskII/src/uae_cpu/cpudefsa.cpp b/BasiliskII/src/uae_cpu/cpudefsa.cpp deleted file mode 100644 index ad7d6979..00000000 --- a/BasiliskII/src/uae_cpu/cpudefsa.cpp +++ /dev/null @@ -1,5 +0,0 @@ -/* - * cpudefs.cpp must be compiled twice, once for the generator program - * and once for the actual executable - */ -#include "cpudefs.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu1.cpp b/BasiliskII/src/uae_cpu/cpuemu1.cpp deleted file mode 100644 index 089eefd4..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu1.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_1 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu1_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu1_nf.cpp deleted file mode 100644 index 58acf444..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu1_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_1 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu2.cpp b/BasiliskII/src/uae_cpu/cpuemu2.cpp deleted file mode 100644 index 1e18b587..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu2.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_2 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu2_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu2_nf.cpp deleted file mode 100644 index 8e5136c4..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu2_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_2 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu3.cpp b/BasiliskII/src/uae_cpu/cpuemu3.cpp deleted file mode 100644 index 0385e2f0..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu3.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_3 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu3_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu3_nf.cpp deleted file mode 100644 index 6565dc8c..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu3_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_3 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu4.cpp b/BasiliskII/src/uae_cpu/cpuemu4.cpp deleted file mode 100644 index 13d27e7a..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu4.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_4 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu4_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu4_nf.cpp deleted file mode 100644 index a16c36cb..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu4_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_4 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu5.cpp b/BasiliskII/src/uae_cpu/cpuemu5.cpp deleted file mode 100644 index 9b33a654..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu5.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_5 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu5_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu5_nf.cpp deleted file mode 100644 index 5bf24360..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu5_nf.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#define NOFLAGS 1 -#define PART_5 -#include "cpuemu.cpp" - diff --git a/BasiliskII/src/uae_cpu/cpuemu6.cpp b/BasiliskII/src/uae_cpu/cpuemu6.cpp deleted file mode 100644 index e4b1efb0..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu6.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_6 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu6_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu6_nf.cpp deleted file mode 100644 index 7afe15d4..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu6_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_6 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu7.cpp b/BasiliskII/src/uae_cpu/cpuemu7.cpp deleted file mode 100644 index faec7ef8..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu7.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_7 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu7_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu7_nf.cpp deleted file mode 100644 index 1e404dea..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu7_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_7 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu8.cpp b/BasiliskII/src/uae_cpu/cpuemu8.cpp deleted file mode 100644 index c4efcfa3..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu8.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define PART_8 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpuemu8_nf.cpp b/BasiliskII/src/uae_cpu/cpuemu8_nf.cpp deleted file mode 100644 index 7c7f8f6e..00000000 --- a/BasiliskII/src/uae_cpu/cpuemu8_nf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define NOFLAGS 1 -#define PART_8 -#include "cpuemu.cpp" diff --git a/BasiliskII/src/uae_cpu/cpufunctbla.cpp b/BasiliskII/src/uae_cpu/cpufunctbla.cpp deleted file mode 100644 index 17dd0d3f..00000000 --- a/BasiliskII/src/uae_cpu/cpufunctbla.cpp +++ /dev/null @@ -1,5 +0,0 @@ -/* - * cpufunctbl.cpp must be compiled twice, once for the generator program - * and once for the actual executable - */ -#include "cpufunctbl.cpp" diff --git a/BasiliskII/src/uae_cpu/cpummu.cpp b/BasiliskII/src/uae_cpu/cpummu.cpp deleted file mode 100644 index 1630bc78..00000000 --- a/BasiliskII/src/uae_cpu/cpummu.cpp +++ /dev/null @@ -1,1096 +0,0 @@ -/* - * cpummu.cpp - 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 - */ - -#define DEBUG 0 -#include "sysdeps.h" - -#include "cpummu.h" -#include "memory.h" -#include "newcpu.h" -#include "debug.h" -#ifdef USE_JIT -# include "compiler/compemu.h" -#endif - -#define DBG_MMU_VERBOSE 1 -#define DBG_MMU_SANITY 1 - -#ifdef FULLMMU - -mmu_atc_l1_array atc_l1[2]; -mmu_atc_l1_array *current_atc; -struct mmu_atc_line atc_l2[2][ATC_L2_SIZE]; - -# ifdef ATC_STATS -static unsigned int mmu_atc_hits[ATC_L2_SIZE]; -# endif - - -static void mmu_dump_ttr(const char * label, uae_u32 ttr) -{ - DUNUSED(label); -#if DEBUG - uae_u32 from_addr, to_addr; - - from_addr = ttr & MMU_TTR_LOGICAL_BASE; - to_addr = (ttr & MMU_TTR_LOGICAL_MASK) << 8; - - D(bug("%s: [%08x] %08x - %08x enabled=%d supervisor=%d wp=%d cm=%02d", - label, ttr, - from_addr, to_addr, - ttr & MMU_TTR_BIT_ENABLED ? 1 : 0, - (ttr & (MMU_TTR_BIT_SFIELD_ENABLED | MMU_TTR_BIT_SFIELD_SUPER)) >> MMU_TTR_SFIELD_SHIFT, - ttr & MMU_TTR_BIT_WRITE_PROTECT ? 1 : 0, - (ttr & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT - )); -#else - DUNUSED(ttr); -#endif -} - -void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode) -{ - uae_u32 * ttr; - uae_u32 * ttr0 = datamode ? ®s.dtt0 : ®s.itt0; - uae_u32 * ttr1 = datamode ? ®s.dtt1 : ®s.itt1; - - if ((*ttr1 & MMU_TTR_BIT_ENABLED) == 0) - ttr = ttr1; - else if ((*ttr0 & MMU_TTR_BIT_ENABLED) == 0) - ttr = ttr0; - else - return; - - *ttr = baseaddr & MMU_TTR_LOGICAL_BASE; - *ttr |= ((baseaddr + size - 1) & MMU_TTR_LOGICAL_BASE) >> 8; - *ttr |= MMU_TTR_BIT_ENABLED; - - D(bug("MMU: map transparent mapping of %08x", *ttr)); -} - -/* check if an address matches a ttr */ -static int mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, int super) -{ - if (ttr & MMU_TTR_BIT_ENABLED) { /* TTR enabled */ - uae_u8 msb, mask; - - msb = ((addr ^ ttr) & MMU_TTR_LOGICAL_BASE) >> 24; - mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16; - - if (!(msb & ~mask)) { - - if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) { - if (((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0) != (super == 0)) { - return TTR_NO_MATCH; - } - } - - return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH; - } - } - return TTR_NO_MATCH; -} - -static inline int mmu_match_ttr(uaecptr addr, int super, int data) -{ - int res; - - if (data) { - res = mmu_do_match_ttr(regs.dtt0, addr, super); - if (res == TTR_NO_MATCH) - res = mmu_do_match_ttr(regs.dtt1, addr, super); - } else { - res = mmu_do_match_ttr(regs.itt0, addr, super); - if (res == TTR_NO_MATCH) - res = mmu_do_match_ttr(regs.itt1, addr, super); - } - return res; -} - -#if DEBUG -/* {{{ mmu_dump_table */ -static void mmu_dump_table(const char * label, uaecptr root_ptr) -{ - DUNUSED(label); - const int ROOT_TABLE_SIZE = 128, - PTR_TABLE_SIZE = 128, - PAGE_TABLE_SIZE = regs.mmu_pagesize_8k ? 32 : 64, - ROOT_INDEX_SHIFT = 25, - PTR_INDEX_SHIFT = 18; - const uae_u32 ptr_addr_mask = (regs.mmu_pagesize_8k ? MMU_PTR_PAGE_ADDR_MASK_8 : MMU_PTR_PAGE_ADDR_MASK_4); - const uae_u32 page_addr_mask = (regs.mmu_pagesize_8k ? MMU_PAGE_ADDR_MASK_8 : MMU_PAGE_ADDR_MASK_4); - const uae_u32 page_ur_mask = (regs.mmu_pagesize_8k ? MMU_PAGE_UR_MASK_8 : MMU_PAGE_UR_MASK_4); - const uae_u32 page_size = (regs.mmu_pagesize_8k ? (1 << 13) : (1 << 12)); - int root_idx, ptr_idx, page_idx; - uae_u32 root_des, ptr_des, page_des; - uaecptr ptr_des_addr, page_addr, - root_log, ptr_log, page_log; - - D(bug("%s: root=%x", label, root_ptr)); - - for (root_idx = 0; root_idx < ROOT_TABLE_SIZE; root_idx++) { - root_des = phys_get_long(root_ptr + (root_idx << 2)); - - if ((root_des & 2) == 0) - continue; /* invalid */ - - D(bug("ROOT: %03d U=%d W=%d UDT=%02d", root_idx, - root_des & 8 ? 1 : 0, - root_des & 4 ? 1 : 0, - root_des & 3 - )); - - root_log = root_idx << ROOT_INDEX_SHIFT; - - ptr_des_addr = root_des & MMU_ROOT_PTR_ADDR_MASK; - - for (ptr_idx = 0; ptr_idx < PTR_TABLE_SIZE; ptr_idx++) { - struct { - uaecptr log, phys; - int start_idx, n_pages; /* number of pages covered by this entry */ - uae_u32 match; - } page_info[PAGE_TABLE_SIZE]; - int n_pages_used; - - ptr_des = phys_get_long(ptr_des_addr + (ptr_idx << 2)); - ptr_log = root_log | (ptr_idx << PTR_INDEX_SHIFT); - - if ((ptr_des & 2) == 0) - continue; /* invalid */ - - page_addr = ptr_des & ptr_addr_mask; - - n_pages_used = -1; - for (page_idx = 0; page_idx < PAGE_TABLE_SIZE; page_idx++) { - - page_des = phys_get_long(page_addr + (page_idx << 2)); - page_log = ptr_log | (page_idx * page_size); - - switch (page_des & 3) { - case 0: /* invalid */ - continue; - case 1: case 3: /* resident */ - case 2: /* indirect */ - if (n_pages_used == -1 || - (page_info[n_pages_used].match & ~page_addr_mask) != (page_des & ~page_addr_mask) || - page_info[n_pages_used].phys + (page_info[n_pages_used].n_pages * page_size) != (page_des & page_addr_mask)) - { - /* use the next entry */ - n_pages_used++; - - page_info[n_pages_used].match = page_des; - page_info[n_pages_used].n_pages = 1; - page_info[n_pages_used].start_idx = page_idx; - page_info[n_pages_used].log = page_log; - page_info[n_pages_used].phys = page_des & page_addr_mask; - } else { - page_info[n_pages_used].n_pages++; - } - break; - } - } - - if (n_pages_used == -1) - continue; - - D(bug(" PTR: %03d U=%d W=%d UDT=%02d", ptr_idx, - ptr_des & 8 ? 1 : 0, - ptr_des & 4 ? 1 : 0, - ptr_des & 3 - )); - - - for (page_idx = 0; page_idx <= n_pages_used; page_idx++) { - page_des = page_info[page_idx].match; - - if ((page_des & MMU_PDT_MASK) == 2) { - D(bug(" PAGE: %03d-%03d log=%08x INDIRECT --> addr=%08x", - page_info[page_idx].start_idx, - page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1, - page_info[page_idx].log, - page_des & MMU_PAGE_INDIRECT_MASK - )); - - } else { - D(bug(" PAGE: %03d-%03d log=%08x addr=%08x UR=%02d G=%d U1/0=%d S=%d CM=%d M=%d U=%d W=%d", - page_info[page_idx].start_idx, - page_info[page_idx].start_idx + page_info[page_idx].n_pages - 1, - page_info[page_idx].log, - page_info[page_idx].phys, - (page_des & page_ur_mask) >> MMU_PAGE_UR_SHIFT, - page_des & MMU_DES_GLOBAL ? 1 : 0, - (page_des & MMU_TTR_UX_MASK) >> MMU_TTR_UX_SHIFT, - page_des & MMU_DES_SUPER ? 1 : 0, - (page_des & MMU_TTR_CACHE_MASK) >> MMU_TTR_CACHE_SHIFT, - page_des & MMU_DES_MODIFIED ? 1 : 0, - page_des & MMU_DES_USED ? 1 : 0, - page_des & MMU_DES_WP ? 1 : 0 - )); - } - } - } - - } -} -/* }}} */ -#endif - -/* {{{ mmu_dump_atc */ -void mmu_dump_atc(void) -{ - int i, j; - for (i = 0; i < 2; i++) { - for (j = 0; j < ATC_L2_SIZE; j++) { - if (atc_l2[i][j].tag == 0x8000) - continue; - D(bug("ATC[%02d] G=%d TT=%d M=%d WP=%d VD=%d VI=%d tag=%08x --> phys=%08x", - j, atc_l2[i][j].global, atc_l2[i][j].tt, atc_l2[i][j].modified, - atc_l2[i][j].write_protect, atc_l2[i][j].valid_data, atc_l2[i][j].valid_inst, - atc_l2[i][j].tag, atc_l2[i][j].phys)); - } - } -} -/* }}} */ - -/* {{{ mmu_dump_tables */ -void mmu_dump_tables(void) -{ - D(bug("URP: %08x SRP: %08x MMUSR: %x TC: %x", regs.urp, regs.srp, regs.mmusr, regs.tc)); - mmu_dump_ttr("DTT0", regs.dtt0); - mmu_dump_ttr("DTT1", regs.dtt1); - mmu_dump_ttr("ITT0", regs.itt0); - mmu_dump_ttr("ITT1", regs.itt1); - mmu_dump_atc(); - //mmu_dump_table("SRP", regs.srp); -} -/* }}} */ - -static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, int super, int write); - -static ALWAYS_INLINE int mmu_get_fc(bool super, bool data) -{ - return (super ? 4 : 0) | (data ? 1 : 2); -} - -static void mmu_bus_error(uaecptr addr, int fc, int write, int size) -{ - uae_u16 ssw = 0; - - ssw |= fc & MMU_SSW_TM; /* Copy TM */ - switch (size) { - case sz_byte: - ssw |= MMU_SSW_SIZE_B; - break; - case sz_word: - ssw |= MMU_SSW_SIZE_W; - break; - case sz_long: - ssw |= MMU_SSW_SIZE_L; - break; - } - - regs.wb3_status = write ? 0x80 | ssw : 0; - if (!write) - ssw |= MMU_SSW_RW; - - regs.mmu_fault_addr = addr; - regs.mmu_ssw = ssw | MMU_SSW_ATC; - - D(bug("BUS ERROR: fc=%d w=%d log=%08x ssw=%04x", fc, write, addr, ssw)); - - breakpt(); - THROW(2); -} - -/* - * Update the atc line for a given address by doing a mmu lookup. - */ -static uaecptr mmu_fill_atc_l2(uaecptr addr, int super, int data, int write, - struct mmu_atc_line *l) -{ - int res; - uae_u32 desc; - - l->tag = ATC_TAG(addr); - l->hw = l->bus_fault = 0; - - /* check ttr0 */ - res = mmu_match_ttr(addr, super, data); - if (res != TTR_NO_MATCH) { - l->tt = 1; - if (data) { - l->valid_data = 1; - l->valid_inst = mmu_match_ttr(addr, super, 0) == res; - } else { - l->valid_inst = 1; - l->valid_data = mmu_match_ttr(addr, super, 1) == res; - } - l->global = 1; - l->modified = 1; - l->write_protect = (res == TTR_NO_WRITE); - l->phys = 0; - - return 0; - } - - l->tt = 0; - if (!regs.mmu_enabled) { - l->valid_data = l->valid_inst = 1; - l->global = 1; - l->modified = 1; - l->write_protect = 0; - l->phys = 0; - return 0; - } - - SAVE_EXCEPTION; - TRY(prb) { - desc = mmu_lookup_pagetable(addr, super, write); - D(bug("translate: %x,%u,%u,%u -> %x", addr, super, write, data, desc)); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - /* bus error during table search */ - desc = 0; - goto fail; - } - - if ((desc & 1) == 0 || (!super && desc & MMU_MMUSR_S)) { - fail: - l->valid_data = l->valid_inst = 0; - l->global = 0; - } else { - l->valid_data = l->valid_inst = 1; - if (regs.mmu_pagesize_8k) - l->phys = (desc & ~0x1fff) - (addr & ~0x1fff); - else - l->phys = (desc & ~0xfff) - (addr & ~0xfff); - l->global = (desc & MMU_MMUSR_G) != 0; - l->modified = (desc & MMU_MMUSR_M) != 0; - l->write_protect = (desc & MMU_MMUSR_W) != 0; - } - - return desc; -} - -static ALWAYS_INLINE bool -mmu_fill_atc_l1(uaecptr addr, int super, int data, int write, - struct mmu_atc_line *l1) -{ - int idx = ATC_L2_INDEX(addr); - int tag = ATC_TAG(addr); - struct mmu_atc_line *l = &atc_l2[super][idx]; - uaecptr phys_addr; - - if (l->tag != tag) { - restart: - mmu_fill_atc_l2(addr, super, data, write, l); - } - if (!(data ? l->valid_data : l->valid_inst)) { - D(bug("MMU: non-resident page (%x,%x,%x)!", addr, regs.pc, regs.fault_pc)); - goto fail; - } - if (write) { - if (l->write_protect) { - D(bug("MMU: write protected (via %s) %x", l->tt ? "ttr" : "atc", addr)); - goto fail; - } - if (!l->modified) - goto restart; - } - *l1 = *l; - - phys_addr = addr + l1->phys; - if ((phys_addr & 0xfff00000) == 0x00f00000) { - l1->hw = 1; - goto fail; - } - if ((phys_addr & 0xfff00000) == 0xfff00000) { - l1->hw = 1; - l1->phys -= 0xff000000; - goto fail; - } - - if (!test_ram_boundary(phys_addr, 1, super, write)) { - l1->bus_fault = 1; - goto fail; - } - - return true; - -fail: - l1->tag = ~l1->tag; - return false; -} - -uaecptr mmu_translate(uaecptr addr, int super, int data, int write) -{ - struct mmu_atc_line *l; - - l = &atc_l2[super][ATC_L2_INDEX(addr)]; - mmu_fill_atc_l2(addr, super, data, write, l); - if (!(data ? l->valid_data : l->valid_inst)) - { - breakpt(); - THROW(2); - } - - return addr + l->phys; -} - -/* - * Lookup the address by walking the page table and updating - * the page descriptors accordingly. Returns the found descriptor - * or produces a bus error. - */ -static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, int super, int write) -{ - uae_u32 desc, desc_addr, wp; - int i; - - wp = 0; - desc = super ? regs.srp : regs.urp; - - /* fetch root table descriptor */ - i = (addr >> 23) & 0x1fc; - desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i; - desc = phys_get_long(desc_addr); - if ((desc & 2) == 0) { - D(bug("MMU: invalid root descriptor for %x", addr)); - return 0; - } - - wp |= desc; - if ((desc & MMU_DES_USED) == 0) - phys_put_long(desc_addr, desc | MMU_DES_USED); - - /* fetch pointer table descriptor */ - i = (addr >> 16) & 0x1fc; - desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i; - desc = phys_get_long(desc_addr); - if ((desc & 2) == 0) { - D(bug("MMU: invalid ptr descriptor for %x", addr)); - return 0; - } - wp |= desc; - if ((desc & MMU_DES_USED) == 0) - phys_put_long(desc_addr, desc | MMU_DES_USED); - - /* fetch page table descriptor */ - if (regs.mmu_pagesize_8k) { - i = (addr >> 11) & 0x7c; - desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_8) | i; - } else { - i = (addr >> 10) & 0xfc; - desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_4) | i; - } - - desc = phys_get_long(desc_addr); - if ((desc & 3) == 2) { - /* indirect */ - desc_addr = desc & MMU_PAGE_INDIRECT_MASK; - desc = phys_get_long(desc_addr); - } - if ((desc & 1) == 0) { - D(bug("MMU: invalid page descriptor log=%08x desc=%08x @%08x", addr, desc, desc_addr)); - return desc; - } - - desc |= wp & MMU_DES_WP; - if (write) { - if (desc & MMU_DES_WP) { - if ((desc & MMU_DES_USED) == 0) { - desc |= MMU_DES_USED; - phys_put_long(desc_addr, desc); - } - } else if ((desc & (MMU_DES_USED|MMU_DES_MODIFIED)) != - (MMU_DES_USED|MMU_DES_MODIFIED)) { - desc |= MMU_DES_USED|MMU_DES_MODIFIED; - phys_put_long(desc_addr, desc); - } - } else { - if ((desc & MMU_DES_USED) == 0) { - desc |= MMU_DES_USED; - phys_put_long(desc_addr, desc); - } - } - return desc; -} - -uae_u16 mmu_get_word_unaligned(uaecptr addr, int data) -{ - uae_u16 res; - - res = (uae_u16)mmu_get_byte(addr, data, sz_word) << 8; - SAVE_EXCEPTION; - TRY(prb) { - res |= mmu_get_byte(addr + 1, data, sz_word); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - breakpt(); - THROW_AGAIN(prb); - } - return res; -} - -uae_u32 mmu_get_long_unaligned(uaecptr addr, int data) -{ - uae_u32 res; - - if (likely(!(addr & 1))) { - res = (uae_u32)mmu_get_word(addr, data, sz_long) << 16; - SAVE_EXCEPTION; - TRY(prb) { - res |= mmu_get_word(addr + 2, data, sz_long); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - breakpt(); - THROW_AGAIN(prb); - } - } else { - res = (uae_u32)mmu_get_byte(addr, data, sz_long) << 8; - SAVE_EXCEPTION; - TRY(prb) { - res = (res | mmu_get_byte(addr + 1, data, sz_long)) << 8; - res = (res | mmu_get_byte(addr + 2, data, sz_long)) << 8; - res |= mmu_get_byte(addr + 3, data, sz_long); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - breakpt(); - THROW_AGAIN(prb); - } - } - return res; -} - -uae_u8 mmu_get_byte_slow(uaecptr addr, int super, int data, - int size, struct mmu_atc_line *cl) -{ - uae_u32 tag = ATC_TAG(addr); - - if (cl->tag == (uae_u16)~tag) { - redo: - if (cl->hw) - return HWget_b(cl->phys + addr); - mmu_bus_error(addr, mmu_get_fc(super, data), 0, size); - return 0; - } - - if (!mmu_fill_atc_l1(addr, super, data, 0, cl)) - goto redo; - - return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl)); -} - -uae_u16 mmu_get_word_slow(uaecptr addr, int super, int data, - int size, struct mmu_atc_line *cl) -{ - uae_u32 tag = ATC_TAG(addr); - - if (cl->tag == (uae_u16)~tag) { - redo: - if (cl->hw) - return HWget_w(cl->phys + addr); - mmu_bus_error(addr, mmu_get_fc(super, data), 0, size); - return 0; - } - - if (!mmu_fill_atc_l1(addr, super, data, 0, cl)) - goto redo; - - return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl)); -} - -uae_u32 mmu_get_long_slow(uaecptr addr, int super, int data, - int size, struct mmu_atc_line *cl) -{ - uae_u32 tag = ATC_TAG(addr); - - if (cl->tag == (uae_u16)~tag) { - redo: - if (cl->hw) - return HWget_l(cl->phys + addr); - mmu_bus_error(addr, mmu_get_fc(super, data), 0, size); - return 0; - } - - if (!mmu_fill_atc_l1(addr, super, data, 0, cl)) - goto redo; - - return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl)); -} - - -uae_u64 mmu_get_quad_slow(uaecptr addr, int super, int data, - struct mmu_atc_line *cl) -{ - uae_u64 h = mmu_get_long_slow(addr, super, data, sz_long, cl); - uae_u64 l = mmu_get_long_slow(addr + 4, super, data, sz_long, cl); - return (h << 32) | l; -} - -REGPARAM2 void mmu_put_long_unaligned(uaecptr addr, uae_u32 val, int data) -{ - SAVE_EXCEPTION; - TRY(prb) { - if (likely(!(addr & 1))) { - mmu_put_word(addr, val >> 16, data, sz_long); - mmu_put_word(addr + 2, val, data, sz_long); - } else { - mmu_put_byte(addr, val >> 24, data, sz_long); - mmu_put_byte(addr + 1, val >> 16, data, sz_long); - mmu_put_byte(addr + 2, val >> 8, data, sz_long); - mmu_put_byte(addr + 3, val, data, sz_long); - } - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.wb3_data = val; - if (regs.mmu_fault_addr != addr) { - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - } - breakpt(); - THROW_AGAIN(prb); - } -} - -REGPARAM2 void mmu_put_word_unaligned(uaecptr addr, uae_u16 val, int data) -{ - SAVE_EXCEPTION; - TRY(prb) { - mmu_put_byte(addr, val >> 8, data, sz_word); - mmu_put_byte(addr + 1, val, data, sz_word); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.wb3_data = val; - if (regs.mmu_fault_addr != addr) { - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - } - breakpt(); - THROW_AGAIN(prb); - } -} - -REGPARAM2 void mmu_put_byte_slow(uaecptr addr, uae_u8 val, int super, int data, - int size, struct mmu_atc_line *cl) -{ - uae_u32 tag = ATC_TAG(addr); - - if (cl->tag == (uae_u16)~tag) { - redo: - if (cl->hw) { - HWput_b(cl->phys + addr, val); - return; - } - regs.wb3_data = val; - mmu_bus_error(addr, mmu_get_fc(super, data), 1, size); - return; - } - - if (!mmu_fill_atc_l1(addr, super, data, 1, cl)) - goto redo; - - do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val); -} - -REGPARAM2 void mmu_put_word_slow(uaecptr addr, uae_u16 val, int super, int data, - int size, struct mmu_atc_line *cl) -{ - uae_u32 tag = ATC_TAG(addr); - - if (cl->tag == (uae_u16)~tag) { - redo: - if (cl->hw) { - HWput_w(cl->phys + addr, val); - return; - } - regs.wb3_data = val; - mmu_bus_error(addr, mmu_get_fc(super, data), 1, size); - return; - } - - if (!mmu_fill_atc_l1(addr, super, data, 1, cl)) - goto redo; - - do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val); -} - -REGPARAM2 void mmu_put_long_slow(uaecptr addr, uae_u32 val, int super, int data, - int size, struct mmu_atc_line *cl) -{ - uae_u32 tag = ATC_TAG(addr); - - if (cl->tag == (uae_u16)~tag) { - redo: - if (cl->hw) { - HWput_l(cl->phys + addr, val); - return; - } - regs.wb3_data = val; - mmu_bus_error(addr, mmu_get_fc(super, data), 1, size); - return; - } - - if (!mmu_fill_atc_l1(addr, super, data, 1, cl)) - goto redo; - - do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val); -} - -REGPARAM2 void mmu_put_quad_slow(uaecptr addr, uae_u64 val, int super, int data, - struct mmu_atc_line *cl) -{ - mmu_put_long_slow(addr, (uae_u32)(val >> 32), super, data, sz_long, cl); - mmu_put_long_slow(addr + 4, (uae_u32)(val), super, data, sz_long, cl); -} - -uae_u32 sfc_get_long(uaecptr addr) -{ - int super = (regs.sfc & 4) != 0; - int data = (regs.sfc & 3) != 2; - uae_u32 res; - - if (likely(!is_unaligned(addr, 4))) - return mmu_get_user_long(addr, super, data, sz_long); - - if (likely(!(addr & 1))) { - res = (uae_u32)mmu_get_user_word(addr, super, data, sz_long) << 16; - SAVE_EXCEPTION; - TRY(prb) { - res |= mmu_get_user_word(addr + 2, super, data, sz_long); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - breakpt(); - THROW_AGAIN(prb); - } - } else { - res = (uae_u32)mmu_get_user_byte(addr, super, data, sz_long) << 8; - SAVE_EXCEPTION; - TRY(prb) { - res = (res | mmu_get_user_byte(addr + 1, super, data, sz_long)) << 8; - res = (res | mmu_get_user_byte(addr + 2, super, data, sz_long)) << 8; - res |= mmu_get_user_byte(addr + 3, super, data, sz_long); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - breakpt(); - THROW_AGAIN(prb); - } - } - return res; -} - -uae_u16 sfc_get_word(uaecptr addr) -{ - int super = (regs.sfc & 4) != 0; - int data = (regs.sfc & 3) != 2; - uae_u16 res; - - if (likely(!is_unaligned(addr, 2))) - return mmu_get_user_word(addr, super, data, sz_word); - - res = (uae_u16)mmu_get_user_byte(addr, super, data, sz_word) << 8; - SAVE_EXCEPTION; - TRY(prb) { - res |= mmu_get_user_byte(addr + 1, super, data, sz_word); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - breakpt(); - THROW_AGAIN(prb); - } - return res; -} - -uae_u8 sfc_get_byte(uaecptr addr) -{ - int super = (regs.sfc & 4) != 0; - int data = (regs.sfc & 3) != 2; - - return mmu_get_user_byte(addr, super, data, sz_byte); -} - -void dfc_put_long(uaecptr addr, uae_u32 val) -{ - int super = (regs.dfc & 4) != 0; - int data = (regs.dfc & 3) != 2; - - SAVE_EXCEPTION; - TRY(prb) { - if (likely(!is_unaligned(addr, 4))) - mmu_put_user_long(addr, val, super, data, sz_long); - else if (likely(!(addr & 1))) { - mmu_put_user_word(addr, val >> 16, super, data, sz_long); - mmu_put_user_word(addr + 2, val, super, data, sz_long); - } else { - mmu_put_user_byte(addr, val >> 24, super, data, sz_long); - mmu_put_user_byte(addr + 1, val >> 16, super, data, sz_long); - mmu_put_user_byte(addr + 2, val >> 8, super, data, sz_long); - mmu_put_user_byte(addr + 3, val, super, data, sz_long); - } - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.wb3_data = val; - if (regs.mmu_fault_addr != addr) { - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - } - breakpt(); - THROW_AGAIN(prb); - } -} - -void dfc_put_word(uaecptr addr, uae_u16 val) -{ - int super = (regs.dfc & 4) != 0; - int data = (regs.dfc & 3) != 2; - - SAVE_EXCEPTION; - TRY(prb) { - if (likely(!is_unaligned(addr, 2))) - mmu_put_user_word(addr, val, super, data, sz_word); - else { - mmu_put_user_byte(addr, val >> 8, super, data, sz_word); - mmu_put_user_byte(addr + 1, val, super, data, sz_word); - } - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.wb3_data = val; - if (regs.mmu_fault_addr != addr) { - regs.mmu_fault_addr = addr; - regs.mmu_ssw |= MMU_SSW_MA; - } - breakpt(); - THROW_AGAIN(prb); - } -} - -void dfc_put_byte(uaecptr addr, uae_u8 val) -{ - int super = (regs.dfc & 4) != 0; - int data = (regs.dfc & 3) != 2; - - SAVE_EXCEPTION; - TRY(prb) { - mmu_put_user_byte(addr, val, super, data, sz_byte); - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - regs.wb3_data = val; - breakpt(); - THROW_AGAIN(prb); - } -} - -void mmu_op(uae_u32 opcode, uae_u16 extra) -{ - int super = (regs.dfc & 4) != 0; - DUNUSED(extra); - if ((opcode & 0xFE0) == 0x0500) { - int regno, glob; - //D(didflush = 0); - uae_u32 addr; - /* PFLUSH */ - regno = opcode & 7; - glob = (opcode & 8) != 0; - - if (opcode & 16) { - D(bug("pflusha(%u,%u)", glob, regs.dfc)); - mmu_flush_atc_all(glob); - } else { - addr = m68k_areg(regs, regno); - D(bug("pflush(%u,%u,%x)", glob, regs.dfc, addr)); - mmu_flush_atc(addr, super, glob); - } - flush_internals(); -#ifdef USE_JIT - flush_icache(0); -#endif - } else if ((opcode & 0x0FD8) == 0x548) { - int write, regno; - uae_u32 addr; - - regno = opcode & 7; - write = (opcode & 32) == 0; - addr = m68k_areg(regs, regno); - //bug("ptest(%u,%u,%x)", write, regs.dfc, addr); - D(bug("PTEST%c (A%d) %08x DFC=%d", write ? 'W' : 'R', regno, addr, regs.dfc)); - mmu_flush_atc(addr, super, true); - SAVE_EXCEPTION; - TRY(prb) { - struct mmu_atc_line *l; - uae_u32 desc; - bool data = (regs.dfc & 3) != 2; - - l = &atc_l2[super][ATC_L2_INDEX(addr)]; - desc = mmu_fill_atc_l2(addr, super, data, write, l); - if (!(data ? l->valid_data : l->valid_inst)) - regs.mmusr = MMU_MMUSR_B; - else if (l->tt) - regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R; - else { - regs.mmusr = desc & (~0xfff|MMU_MMUSR_G|MMU_MMUSR_Ux|MMU_MMUSR_S| - MMU_MMUSR_CM|MMU_MMUSR_M|MMU_MMUSR_W); - regs.mmusr |= MMU_MMUSR_R; - } - } - CATCH(prb) { - regs.mmusr = MMU_MMUSR_B; - } - RESTORE_EXCEPTION; - D(bug("PTEST result: mmusr %08x", regs.mmusr)); - } else - op_illg (opcode); -} - -void mmu_flush_atc(uaecptr addr, bool super, bool global) -{ - struct mmu_atc_line *l; - int i, j; - - l = atc_l1[super][0][0]; - i = ATC_L1_INDEX(addr); - for (j = 0; j < 4; j++) { - if (global || !l[i].global) - l[i].tag = 0x8000; - l += ATC_L1_SIZE; - } - if (regs.mmu_pagesize_8k) { - i = ATC_L1_INDEX(addr) ^ 1; - for (j = 0; j < 4; j++) { - if (global || !l[i].global) - l[i].tag = 0x8000; - l += ATC_L1_SIZE; - } - } - l = atc_l2[super]; - i = ATC_L2_INDEX(addr); - if (global || !l[i].global) - l[i].tag = 0x8000; - if (regs.mmu_pagesize_8k) { - i ^= 1; - if (global || !l[i].global) - l[i].tag = 0x8000; - } -} - -void mmu_flush_atc_all(bool global) -{ - struct mmu_atc_line *l; - unsigned int i; - - l = atc_l1[0][0][0]; - for (i = 0; i < sizeof(atc_l1) / sizeof(*l); l++, i++) { - if (global || !l->global) - l->tag = 0x8000; - } - - l = atc_l2[0]; - for (i = 0; i < sizeof(atc_l2) / sizeof(*l); l++, i++) { - if (global || !l->global) - l->tag = 0x8000; - } -} - -void mmu_reset(void) -{ - mmu_flush_atc_all(true); - - regs.urp = regs.srp = 0; - regs.itt0 = regs.itt1 = 0; - regs.dtt0 = regs.dtt1 = 0; - regs.mmusr = 0; -} - - -void mmu_set_tc(uae_u16 tc) -{ - if (regs.tc == tc) - return; - - regs.tc = tc; - regs.mmu_enabled = tc & 0x8000 ? 1 : 0; - regs.mmu_pagesize_8k = tc & 0x4000 ? 1 : 0; - mmu_flush_atc_all(true); - - D(bug("MMU: enabled=%d page8k=%d\n", regs.mmu_enabled, regs.mmu_pagesize_8k)); -} - -void mmu_set_super(bool super) -{ - current_atc = &atc_l1[super]; -} - -#else - -void mmu_op(uae_u32 opcode, uae_u16 /*extra*/) -{ - if ((opcode & 0xFE0) == 0x0500) { - /* PFLUSH instruction */ - flush_internals(); - } else if ((opcode & 0x0FD8) == 0x548) { - /* PTEST instruction */ - } else - op_illg(opcode); -} - -#endif - -/* -vim:ts=4:sw=4: -*/ diff --git a/BasiliskII/src/uae_cpu/cpummu.h b/BasiliskII/src/uae_cpu/cpummu.h deleted file mode 100644 index 01359f6f..00000000 --- a/BasiliskII/src/uae_cpu/cpummu.h +++ /dev/null @@ -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 - -#define MMU_TEST_PTEST 1 -#define MMU_TEST_VERBOSE 2 -#define MMU_TEST_FORCE_TABLE_SEARCH 4 -#define MMU_TEST_NO_BUSERR 8 - -extern void mmu_dump_tables(void); - -#define MMU_TTR_LOGICAL_BASE 0xff000000 -#define MMU_TTR_LOGICAL_MASK 0x00ff0000 -#define MMU_TTR_BIT_ENABLED (1 << 15) -#define MMU_TTR_BIT_SFIELD_ENABLED (1 << 14) -#define MMU_TTR_BIT_SFIELD_SUPER (1 << 13) -#define MMU_TTR_SFIELD_SHIFT 13 -#define MMU_TTR_UX_MASK ((1 << 9) | (1 << 8)) -#define MMU_TTR_UX_SHIFT 8 -#define MMU_TTR_CACHE_MASK ((1 << 6) | (1 << 5)) -#define MMU_TTR_CACHE_SHIFT 5 -#define MMU_TTR_BIT_WRITE_PROTECT (1 << 2) - -#define MMU_UDT_MASK 3 -#define MMU_PDT_MASK 3 - -#define MMU_DES_WP 4 -#define MMU_DES_USED 8 - -/* page descriptors only */ -#define MMU_DES_MODIFIED 16 -#define MMU_DES_SUPER (1 << 7) -#define MMU_DES_GLOBAL (1 << 10) - -#define MMU_ROOT_PTR_ADDR_MASK 0xfffffe00 -#define MMU_PTR_PAGE_ADDR_MASK_8 0xffffff80 -#define MMU_PTR_PAGE_ADDR_MASK_4 0xffffff00 - -#define MMU_PAGE_INDIRECT_MASK 0xfffffffc -#define MMU_PAGE_ADDR_MASK_8 0xffffe000 -#define MMU_PAGE_ADDR_MASK_4 0xfffff000 -#define MMU_PAGE_UR_MASK_8 ((1 << 12) | (1 << 11)) -#define MMU_PAGE_UR_MASK_4 (1 << 11) -#define MMU_PAGE_UR_SHIFT 11 - -#define MMU_MMUSR_ADDR_MASK 0xfffff000 -#define MMU_MMUSR_B (1 << 11) -#define MMU_MMUSR_G (1 << 10) -#define MMU_MMUSR_U1 (1 << 9) -#define MMU_MMUSR_U0 (1 << 8) -#define MMU_MMUSR_Ux (MMU_MMUSR_U1 | MMU_MMUSR_U0) -#define MMU_MMUSR_S (1 << 7) -#define MMU_MMUSR_CM ((1 << 6) | ( 1 << 5)) -#define MMU_MMUSR_M (1 << 4) -#define MMU_MMUSR_W (1 << 2) -#define MMU_MMUSR_T (1 << 1) -#define MMU_MMUSR_R (1 << 0) - -/* special status word (access error stack frame) */ -#define MMU_SSW_TM 0x0007 -#define MMU_SSW_TT 0x0018 -#define MMU_SSW_SIZE 0x0060 -#define MMU_SSW_SIZE_B 0x0020 -#define MMU_SSW_SIZE_W 0x0040 -#define MMU_SSW_SIZE_L 0x0000 -#define MMU_SSW_RW 0x0100 -#define MMU_SSW_LK 0x0200 -#define MMU_SSW_ATC 0x0400 -#define MMU_SSW_MA 0x0800 - -#define TTR_I0 4 -#define TTR_I1 5 -#define TTR_D0 6 -#define TTR_D1 7 - -#define TTR_NO_MATCH 0 -#define TTR_NO_WRITE 1 -#define TTR_OK_MATCH 2 - -struct mmu_atc_line { - uae_u16 tag; - unsigned tt : 1; - unsigned valid_data : 1; - unsigned valid_inst : 1; - unsigned global : 1; - unsigned modified : 1; - unsigned write_protect : 1; - unsigned hw : 1; - unsigned bus_fault : 1; - uaecptr phys; -}; - -/* - * We don't need to store the whole logical address in the atc cache, as part of - * it is encoded as index into the cache. 14 bits of the address are stored in - * the tag, this means at least 6 bits must go into the index. The upper two - * bits of the tag define the type of data in the atc line: - * - 00: a normal memory address - * - 11: invalid memory address or hardware access - * (generated via ~ATC_TAG(addr) in the slow path) - * - 10: empty atc line - */ - -#define ATC_TAG_SHIFT 18 -#define ATC_TAG(addr) ((uae_u32)(addr) >> ATC_TAG_SHIFT) - - -#define ATC_L1_SIZE_LOG 8 -#define ATC_L1_SIZE (1 << ATC_L1_SIZE_LOG) - -#define ATC_L1_INDEX(addr) (((addr) >> 12) % ATC_L1_SIZE) - -/* - * first level atc cache - * indexed by [super][data][rw][idx] - */ - -typedef struct mmu_atc_line mmu_atc_l1_array[2][2][ATC_L1_SIZE]; -extern mmu_atc_l1_array atc_l1[2]; -extern mmu_atc_l1_array *current_atc; - -#define ATC_L2_SIZE_LOG 12 -#define ATC_L2_SIZE (1 << ATC_L2_SIZE_LOG) - -#define ATC_L2_INDEX(addr) ((((addr) >> 12) ^ ((addr) >> (32 - ATC_L2_SIZE_LOG))) % ATC_L2_SIZE) - -extern struct mmu_atc_line atc_l2[2][ATC_L2_SIZE]; - -/* - * lookup address in the level 1 atc cache, - * the data and write arguments are constant in the common, - * thus allows gcc to generate a constant offset. - */ -static ALWAYS_INLINE int mmu_lookup(uaecptr addr, bool data, bool write, - struct mmu_atc_line **cl) -{ - addr >>= 12; - *cl = &(*current_atc)[data][write][addr % ATC_L1_SIZE]; - return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12); -} - -/* - * similiar to mmu_user_lookup, but for the use of the moves instruction - */ -static ALWAYS_INLINE int mmu_user_lookup(uaecptr addr, bool super, bool data, - bool write, struct mmu_atc_line **cl) -{ - addr >>= 12; - *cl = &atc_l1[super][data][write][addr % ATC_L1_SIZE]; - return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12); -} - -extern REGPARAM2 uae_u16 mmu_get_word_unaligned(uaecptr addr, int data); -extern REGPARAM2 uae_u32 mmu_get_long_unaligned(uaecptr addr, int data); - -extern REGPARAM2 uae_u8 mmu_get_byte_slow(uaecptr addr, int super, int data, - int size, struct mmu_atc_line *cl); -extern REGPARAM2 uae_u16 mmu_get_word_slow(uaecptr addr, int super, int data, - int size, struct mmu_atc_line *cl); -extern REGPARAM2 uae_u32 mmu_get_long_slow(uaecptr addr, int super, int data, - int size, struct mmu_atc_line *cl); -extern REGPARAM2 uae_u64 mmu_get_quad_slow(uaecptr addr, int super, int data, - struct mmu_atc_line *cl); - -extern REGPARAM2 void mmu_put_word_unaligned(uaecptr addr, uae_u16 val, int data); -extern REGPARAM2 void mmu_put_long_unaligned(uaecptr addr, uae_u32 val, int data); - -extern REGPARAM2 void mmu_put_byte_slow(uaecptr addr, uae_u8 val, int super, int data, - int size, struct mmu_atc_line *cl); -extern REGPARAM2 void mmu_put_word_slow(uaecptr addr, uae_u16 val, int super, int data, - int size, struct mmu_atc_line *cl); -extern REGPARAM2 void mmu_put_long_slow(uaecptr addr, uae_u32 val, int super, int data, - int size, struct mmu_atc_line *cl); -extern REGPARAM2 void mmu_put_quad_slow(uaecptr addr, uae_u64 val, int super, int data, - struct mmu_atc_line *cl); - -extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode); - -static inline void mmu_set_ttr(int regno, uae_u32 val) -{ - uae_u32 * ttr; - switch(regno) { - case TTR_I0: ttr = ®s.itt0; break; - case TTR_I1: ttr = ®s.itt1; break; - case TTR_D0: ttr = ®s.dtt0; break; - case TTR_D1: ttr = ®s.dtt1; break; - default: abort(); - } - *ttr = val; -} - -static inline void mmu_set_mmusr(uae_u32 val) -{ - regs.mmusr = val; -} - -#define FC_DATA (regs.s ? 5 : 1) -#define FC_INST (regs.s ? 6 : 2) - -extern uaecptr REGPARAM2 mmu_translate(uaecptr addr, int super, int data, int write); - -extern uae_u32 REGPARAM2 sfc_get_long(uaecptr addr); -extern uae_u16 REGPARAM2 sfc_get_word(uaecptr addr); -extern uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr); -extern void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val); -extern void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val); -extern void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val); - - -extern void REGPARAM2 mmu_flush_atc(uaecptr addr, bool super, bool global); -extern void REGPARAM2 mmu_flush_atc_all(bool global); -extern void REGPARAM2 mmu_op(uae_u32 opcode, uae_u16 extra); - -#ifdef FULLMMU - -extern void REGPARAM2 mmu_reset(void); -extern void REGPARAM2 mmu_set_tc(uae_u16 tc); -extern void REGPARAM2 mmu_set_super(bool super); - -#else - -static inline void mmu_reset(void) -{ -} - -static inline void mmu_set_tc(uae_u16 /*tc*/) -{ -} - -static inline void mmu_set_super(bool /*super*/) -{ -} - -#endif - -#endif /* CPUMMU_H */ -/* -vim:ts=4:sw=4: -*/ diff --git a/BasiliskII/src/uae_cpu/cpuopti.c b/BasiliskII/src/uae_cpu/cpuopti.c new file mode 100644 index 00000000..28ba7c22 --- /dev/null +++ b/BasiliskII/src/uae_cpu/cpuopti.c @@ -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 +#include +#include + +#include "sysdeps.h" + +struct line { + struct line *next, *prev; + int delet; + char *data; +}; + +struct func { + struct line *first_line, *last_line; + int initial_offset; +}; + +static void oops(void) +{ + fprintf(stderr, "Don't know how to optimize this file.\n"); + exit(1); +} + +static char * match(struct line *l, const char *m) +{ + char *str = l->data; + int len = strlen(m); + while (isspace(*str)) + str++; + + if (strncmp(str, m, len) != 0) + return NULL; + return str + len; +} + +static int insn_references_reg (struct line *l, char *reg) +{ + if (reg[0] != 'e') { + fprintf(stderr, "Unknown register?!?\n"); + exit(1); + } + if (strstr (l->data, reg) != 0) + return 1; + if (strstr (l->data, reg+1) != 0) + return 1; + if (strcmp (reg, "eax") == 0 + && (strstr (l->data, "%al") != 0 || strstr (l->data, "%ah") != 0)) + return 1; + if (strcmp (reg, "ebx") == 0 + && (strstr (l->data, "%bl") != 0 || strstr (l->data, "%bh") != 0)) + return 1; + if (strcmp (reg, "ecx") == 0 + && (strstr (l->data, "%cl") != 0 || strstr (l->data, "%ch") != 0)) + return 1; + if (strcmp (reg, "edx") == 0 + && (strstr (l->data, "%dl") != 0 || strstr (l->data, "%dh") != 0)) + return 1; + return 0; +} + +static void do_function(struct func *f) +{ + int v; + int pops_at_end = 0; + struct line *l, *l1, *fl, *l2; + char *s, *s2; + int in_pop_area = 1; + + f->initial_offset = 0; + + l = f->last_line; + fl = f->first_line; + + if (match(l,".LFE")) + l = l->prev; + if (!match(l,"ret")) + oops(); + + while (!match(fl, "op_")) + fl = fl->next; + fl = fl->next; + + /* Try reordering the insns at the end of the function so that the + * pops are all at the end. */ + l2 = l->prev; + /* Tolerate one stack adjustment */ + if (match (l2, "addl $") && strstr(l2->data, "esp") != 0) + l2 = l2->prev; + for (;;) { + char *forbidden_reg; + struct line *l3, *l4; + + while (match (l2, "popl %")) + l2 = l2->prev; + + l3 = l2; + for (;;) { + forbidden_reg = match (l3, "popl %"); + if (forbidden_reg) + break; + if (l3 == fl) + goto reordered; + /* Jumps and labels put an end to our attempts... */ + if (strstr (l3->data, ".L") != 0) + goto reordered; + /* Likewise accesses to the stack pointer... */ + if (strstr (l3->data, "esp") != 0) + goto reordered; + /* Function calls... */ + if (strstr (l3->data, "call") != 0) + goto reordered; + l3 = l3->prev; + } + if (l3 == l2) + exit(1); + for (l4 = l2; l4 != l3; l4 = l4->prev) { + /* The register may not be referenced by any of the insns that we + * move the popl past */ + if (insn_references_reg (l4, forbidden_reg)) + goto reordered; + } + l3->prev->next = l3->next; + l3->next->prev = l3->prev; + l2->next->prev = l3; + l3->next = l2->next; + l2->next = l3; + l3->prev = l2; + } +reordered: + + l = l->prev; + + s = match (l, "addl $"); + s2 = match (fl, "subl $"); + + l1 = l; + if (s == 0) { + char *t = match (l, "popl %"); + if (t != 0 && (strcmp (t, "ecx") == 0 || strcmp (t, "edx") == 0)) { + s = "4,%esp"; + l = l->prev; + t = match (l, "popl %"); + if (t != 0 && (strcmp (t, "ecx") == 0 || strcmp (t, "edx") == 0)) { + s = "8,%esp"; + l = l->prev; + } + } + } else { + l = l->prev; + } + + if (s && s2) { + int v = 0; + if (strcmp (s, s2) != 0) { + fprintf (stderr, "Stack adjustment not matching.\n"); + return; + } + + while (isdigit(*s)) { + v = v * 10 + (*s) - '0'; + s++; + } + + if (strcmp (s, ",%esp") != 0) { + fprintf (stderr, "Not adjusting the stack pointer.\n"); + return; + } + f->initial_offset = v; + fl->delet = 3; + fl = fl->next; + l1->delet = 2; + l1 = l1->prev; + while (l1 != l) { + l1->delet = 1; + l1 = l1->prev; + } + } + + while (in_pop_area) { + char *popm, *pushm; + popm = match (l, "popl %"); + pushm = match (fl, "pushl %"); + if (popm && pushm && strcmp(pushm, popm) == 0) { + pops_at_end++; + fl->delet = l->delet = 1; + } else + in_pop_area = 0; + l = l->prev; + fl = fl->next; + } + if (f->initial_offset) + f->initial_offset += 4 * pops_at_end; +} + +static void output_function(struct func *f) +{ + struct line *l = f->first_line; + + while (l) { + switch (l->delet) { + case 1: + break; + case 0: + printf("%s\n", l->data); + break; + case 2: + if (f->initial_offset) + printf("\taddl $%d,%%esp\n", f->initial_offset); + break; + case 3: + if (f->initial_offset) + printf("\tsubl $%d,%%esp\n", f->initial_offset); + break; + } + l = l->next; + } +} + +int main(int argc, char **argv) +{ + FILE *infile = stdin; + char tmp[4096]; + +#ifdef __mc68000__ + if(system("perl machdep/cpuopti")==-1) { + perror("perl machdep/cpuopti"); + return 10; + } else return 0; +#endif + + /* For debugging... */ + if (argc == 2) + infile = fopen (argv[1], "r"); + + for(;;) { + char *s; + + if ((fgets(tmp, 4095, infile)) == NULL) + break; + + s = strchr (tmp, '\n'); + if (s != NULL) + *s = 0; + + if (strncmp(tmp, ".globl op_", 10) == 0) { + struct line *first_line = NULL, *prev = NULL; + struct line **nextp = &first_line; + struct func f; + int nr_rets = 0; + int can_opt = 1; + + do { + struct line *current; + + if (strcmp (tmp, "#APP") != 0 && strcmp (tmp, "#NO_APP") != 0) { + current = *nextp = (struct line *)malloc(sizeof (struct line)); + nextp = ¤t->next; + current->prev = prev; prev = current; + current->next = NULL; + current->delet = 0; + current->data = strdup (tmp); + if (match (current, "movl %esp,%ebp") || match (current, "enter")) { + fprintf (stderr, "GCC failed to eliminate fp: %s\n", first_line->data); + can_opt = 0; + } + + if (match (current, "ret")) + nr_rets++; + } + if ((fgets(tmp, 4095, infile)) == NULL) + oops(); + s = strchr (tmp, '\n'); + if (s != NULL) + *s = 0; + } while (strncmp (tmp,".Lfe", 4) != 0); + + f.first_line = first_line; + f.last_line = prev; + + if (nr_rets == 1 && can_opt) + do_function(&f); + /*else + fprintf(stderr, "Too many RET instructions: %s\n", first_line->data);*/ + output_function(&f); + } + printf("%s\n", tmp); + } + return 0; +} diff --git a/BasiliskII/src/uae_cpu/cpustbl_nf.cpp b/BasiliskII/src/uae_cpu/cpustbl_nf.cpp deleted file mode 100644 index 0ea66010..00000000 --- a/BasiliskII/src/uae_cpu/cpustbl_nf.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define NOFLAGS 1 -#include "cpustbl.cpp" diff --git a/BasiliskII/src/uae_cpu/cpustbla.cpp b/BasiliskII/src/uae_cpu/cpustbla.cpp deleted file mode 100644 index f3f8e320..00000000 --- a/BasiliskII/src/uae_cpu/cpustbla.cpp +++ /dev/null @@ -1,5 +0,0 @@ -/* - * cpustbl.cpp must be compiled twice, once for the generator program - * and once for the actual executable - */ -#include "cpustbl.cpp" diff --git a/BasiliskII/src/uae_cpu/debug.cpp b/BasiliskII/src/uae_cpu/debug.cpp deleted file mode 100644 index 8b2f14e0..00000000 --- a/BasiliskII/src/uae_cpu/debug.cpp +++ /dev/null @@ -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: -*/ diff --git a/BasiliskII/src/uae_cpu/fpu/core.h b/BasiliskII/src/uae_cpu/fpu/core.h index 1801ff7c..66358a2d 100644 --- a/BasiliskII/src/uae_cpu/fpu/core.h +++ b/BasiliskII/src/uae_cpu/fpu/core.h @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/exceptions.cpp b/BasiliskII/src/uae_cpu/fpu/exceptions.cpp index 2a597997..6aa6431a 100644 --- a/BasiliskII/src/uae_cpu/fpu/exceptions.cpp +++ b/BasiliskII/src/uae_cpu/fpu/exceptions.cpp @@ -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 diff --git a/BasiliskII/src/uae_cpu/fpu/exceptions.h b/BasiliskII/src/uae_cpu/fpu/exceptions.h index f943da04..8c69a69d 100644 --- a/BasiliskII/src/uae_cpu/fpu/exceptions.h +++ b/BasiliskII/src/uae_cpu/fpu/exceptions.h @@ -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 diff --git a/BasiliskII/src/uae_cpu/fpu/flags.cpp b/BasiliskII/src/uae_cpu/fpu/flags.cpp index 4b0972df..2eabef85 100644 --- a/BasiliskII/src/uae_cpu/fpu/flags.cpp +++ b/BasiliskII/src/uae_cpu/fpu/flags.cpp @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/flags.h b/BasiliskII/src/uae_cpu/fpu/flags.h index 3d144ac2..7c0c5b74 100644 --- a/BasiliskII/src/uae_cpu/fpu/flags.h +++ b/BasiliskII/src/uae_cpu/fpu/flags.h @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu.h b/BasiliskII/src/uae_cpu/fpu/fpu.h index d1fe6dd2..3940a75b 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu.h @@ -1,33 +1,28 @@ /* - * fpu/fpu.h - public header + * fpu/fpu.h - public header * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_PUBLIC_HEADER_H @@ -51,9 +46,4 @@ #include "fpu/types.h" #include "fpu/core.h" -void fpu_set_fpsr(uae_u32 new_fpsr); -uae_u32 fpu_get_fpsr(void); -void fpu_set_fpcr(uae_u32 new_fpcr); -uae_u32 fpu_get_fpcr(void); - #endif /* FPU_PUBLIC_HEADER_H */ diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp index 5fa1ad0b..f5a1aeb4 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp +++ b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp @@ -1,42 +1,31 @@ /* - * fpu_ieee.cpp - the IEEE FPU + * fpu/fpu_ieee.cpp * - * Copyright (c) 2001-2008 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/MC68040 emulation - * - * Copyright 1996 Herman ten Brugge - * - * * Following fixes by Lauri Pesonen, July 1999: * * FMOVEM list handling: @@ -98,7 +87,7 @@ */ #include "sysdeps.h" -#include +#include #include "memory.h" #include "readcpu.h" #include "newcpu.h" @@ -141,24 +130,6 @@ fpu_t fpu; #include "fpu/exceptions.cpp" #include "fpu/rounding.cpp" -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) -#define LD(x) x ## L -#ifdef HAVE_POWL -#define POWL(x, y) powl(x, y) -#else -#define POWL(x, y) pow(x, y) -#endif -#ifdef HAVE_LOG10L -#define LOG10L(x) log10l(x) -#else -#define LOG10L(x) log10(x) -#endif -#else -#define LD(x) x -#define POWL(x, y) pow(x, y) -#define LOG10L(x) log10(x) -#endif - /* -------------------------------------------------------------------------- */ /* --- Debugging --- */ /* -------------------------------------------------------------------------- */ @@ -181,9 +152,9 @@ PUBLIC void FFPU fpu_dump_flags(void) (get_fpsr() & FPSR_CCB_NAN) != 0); } -#if FPU_DEBUG && FPU_DUMP_REGISTERS PRIVATE void FFPU dump_registers(const char * str) { +#if FPU_DEBUG && FPU_DUMP_REGISTERS char temp_str[512]; sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n", @@ -193,15 +164,12 @@ PRIVATE void FFPU dump_registers(const char * str) fpu_get_register(6), fpu_get_register(7) ); fpu_debug((temp_str)); -#else -PRIVATE void FFPU dump_registers(const char *) -{ #endif } -#if FPU_DEBUG && FPU_DUMP_FIRST_BYTES PRIVATE void FFPU dump_first_bytes(uae_u8 * buffer, uae_s32 actual) { +#if FPU_DEBUG && FPU_DUMP_FIRST_BYTES char temp_buf1[256], temp_buf2[10]; int bytes = sizeof(temp_buf1)/3-1-3; if (actual < bytes) @@ -215,9 +183,6 @@ PRIVATE void FFPU dump_first_bytes(uae_u8 * buffer, uae_s32 actual) strcat(temp_buf1, "\n"); fpu_debug((temp_buf1)); -#else - PRIVATE void FFPU dump_first_bytes(uae_u8 *, uae_s32) -{ #endif } @@ -235,12 +200,11 @@ PRIVATE inline fpu_register FFPU make_single(uae_u32 value) #if 1 // Use a single, otherwise some checks for NaN, Inf, Zero would have to // be performed - fpu_single result = 0; - fp_declare_init_shape(srp, single); - srp.ieee.negative = (value >> 31) & 1; - srp.ieee.exponent = (value >> 23) & FP_SINGLE_EXP_MAX; - srp.ieee.mantissa = value & 0x007fffff; - result = srp.value; + fpu_single result = 0; // = 0 to workaround a compiler bug on SPARC + fp_declare_init_shape(srp, result, single); + srp->ieee.negative = (value >> 31) & 1; + srp->ieee.exponent = (value >> 23) & FP_SINGLE_EXP_MAX; + srp->ieee.mantissa = value & 0x007fffff; fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); return result; #elif 0 /* Original code */ @@ -248,13 +212,13 @@ PRIVATE inline fpu_register FFPU make_single(uae_u32 value) return (0.0); fpu_register result; - fpu_register_parts *p = (fpu_register_parts *)&result; + 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); + p[FLO] = value << 29; + p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3); fpu_debug(("make_single (%X) = %.04f\n",value,(double)result)); @@ -267,11 +231,10 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) { #if 1 fpu_single input = (fpu_single) src; - fp_declare_init_shape(sip, single); - sip.value = input; - uae_u32 result = (sip.ieee.negative << 31) - | (sip.ieee.exponent << 23) - | sip.ieee.mantissa; + fp_declare_init_shape(sip, input, single); + uae_u32 result = (sip->ieee.negative << 31) + | (sip->ieee.exponent << 23) + | sip->ieee.mantissa; fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result)); return result; #elif 0 /* Original code */ @@ -279,10 +242,10 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src) return 0; uae_u32 result; - fpu_register_parts const *p = (fpu_register_parts const *)&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; @@ -292,7 +255,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)); @@ -305,37 +268,36 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u { // is it zero? if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) - return (wrd1 & 0x80000000) ? -0.0 : 0.0; + return 0.0; fpu_register result; -#if defined(USE_QUAD_DOUBLE) +#if USE_QUAD_DOUBLE // is it NaN? - if ((wrd1 & 0x7fff0000) == 0x7fff0000 && ((wrd2 & 0x7fffffff) != 0 || wrd3 != 0)) { + if ((wrd1 & 0x7fff0000) == 0x7fff0000 && wrd2 != 0 && wrd3 != 0) { make_nan(result); return result; } // is it inf? - if ((wrd1 & 0x7ffff000) == 0x7fff0000 && (wrd2 & 0x7fffffff) == 0 && wrd3 == 0) { + if ((wrd1 & 0x7ffff000) == 0x7fff0000 && wrd2 == 0 && wrd3 == 0) { if ((wrd1 & 0x80000000) == 0) make_inf_positive(result); else make_inf_negative(result); return result; } - fp_declare_init_shape(srp, extended); - srp.ieee.negative = (wrd1 >> 31) & 1; - srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp.ieee.mantissa0 = (wrd2 >> 16) & 0xffff; - srp.ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); - srp.ieee.mantissa2 = (wrd3 & 0xffff) << 16; - srp.ieee.mantissa3 = 0; -#elif defined(USE_LONG_DOUBLE) - fp_declare_init_shape(srp, extended); - srp.ieee.negative = (wrd1 >> 31) & 1; - srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp.ieee.mantissa0 = wrd2; - srp.ieee.mantissa1 = wrd3; - + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff; + srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); + srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16; + srp->ieee.mantissa3 = 0; +#elif USE_LONG_DOUBLE + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp->ieee.mantissa0 = wrd2; + srp->ieee.mantissa1 = wrd3; #else uae_u32 sgn = (wrd1 >> 31) & 1; uae_u32 exp = (wrd1 >> 16) & 0x7fff; @@ -364,14 +326,13 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u else exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; - fp_declare_init_shape(srp, double); - srp.ieee.negative = sgn; - srp.ieee.exponent = exp; + fp_declare_init_shape(srp, result, double); + srp->ieee.negative = sgn; + srp->ieee.exponent = exp; // drop the explicit integer bit - srp.ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; - srp.ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); + srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; + srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); #endif - result = srp.value; fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); return result; } @@ -386,40 +347,37 @@ PRIVATE inline void FFPU make_extended_no_normalize( ) { // is it zero? - if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { - if (wrd1 & 0x80000000) - make_zero_negative(result); - else - make_zero_positive(result); + if ((wrd1 && 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { + make_zero_positive(result); return; } // is it NaN? - if ((wrd1 & 0x7fff0000) == 0x7fff0000 && ((wrd2 & 0x7fffffff) != 0 || wrd3 != 0)) { + if ((wrd1 & 0x7fff0000) == 0x7fff0000 && wrd2 != 0 && wrd3 != 0) { make_nan(result); return; } -#if defined(USE_QUAD_DOUBLE) +#if USE_QUAD_DOUBLE // is it inf? - if ((wrd1 & 0x7ffff000) == 0x7fff0000 && (wrd2 & 0x7fffffff) == 0 && wrd3 == 0) { + if ((wrd1 & 0x7ffff000) == 0x7fff0000 && wrd2 == 0 && wrd3 == 0) { if ((wrd1 & 0x80000000) == 0) make_inf_positive(result); else make_inf_negative(result); return; } - fp_declare_init_shape(srp, extended); - srp.ieee.negative = (wrd1 >> 31) & 1; - srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp.ieee.mantissa0 = (wrd2 >> 16) & 0xffff; - srp.ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); - srp.ieee.mantissa2 = (wrd3 & 0xffff) << 16; - srp.ieee.mantissa3 = 0; -#elif defined(USE_LONG_DOUBLE) - fp_declare_init_shape(srp, extended); - srp.ieee.negative = (wrd1 >> 31) & 1; - srp.ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; - srp.ieee.mantissa0 = wrd2; - srp.ieee.mantissa1 = wrd3; + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff; + srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff); + srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16; + srp->ieee.mantissa3 = 0; +#elif USE_LONG_DOUBLE + fp_declare_init_shape(srp, result, extended); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX; + srp->ieee.mantissa0 = wrd2; + srp->ieee.mantissa1 = wrd3; #else uae_u32 exp = (wrd1 >> 16) & 0x7fff; if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) @@ -429,14 +387,13 @@ PRIVATE inline void FFPU make_extended_no_normalize( else exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; - fp_declare_init_shape(srp, double); - srp.ieee.negative = (wrd1 >> 31) & 1; - srp.ieee.exponent = exp; + fp_declare_init_shape(srp, result, double); + srp->ieee.negative = (wrd1 >> 31) & 1; + srp->ieee.exponent = exp; // drop the explicit integer bit - srp.ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; - srp.ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); + srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11; + srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11); #endif - result = srp.value; fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result)); } @@ -449,43 +406,41 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src, *wrd1 = *wrd2 = *wrd3 = 0; return; } -#if defined(USE_QUAD_DOUBLE) +#if USE_QUAD_DOUBLE // FIXME: deal with denormals? - fp_declare_init_shape(srp, extended); - srp.value = src; - *wrd1 = (srp.ieee.negative << 31) | (srp.ieee.exponent << 16); + fp_declare_init_shape(srp, src, extended); + *wrd1 = (srp->ieee.negative << 31) | (srp->ieee.exponent << 16); // always set the explicit integer bit. - *wrd2 = 0x80000000 | (srp.ieee.mantissa0 << 15) | ((srp.ieee.mantissa1 & 0xfffe0000) >> 17); - *wrd3 = (srp.ieee.mantissa1 << 15) | ((srp.ieee.mantissa2 & 0xfffe0000) >> 17); -#elif defined(USE_LONG_DOUBLE) - fpu_register_parts p = { src }; + *wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 15) | ((srp->ieee.mantissa1 & 0xfffe0000) >> 17); + *wrd3 = (srp->ieee.mantissa1 << 15) | ((srp->ieee.mantissa2 & 0xfffe0000) >> 17); +#elif USE_LONG_DOUBLE + uae_u32 *p = (uae_u32 *)&src; #ifdef WORDS_BIGENDIAN - *wrd1 = p.parts[0]; - *wrd2 = p.parts[1]; - *wrd3 = p.parts[2]; + *wrd1 = p[0]; + *wrd2 = p[1]; + *wrd3 = p[2]; #else - *wrd3 = p.parts[0]; - *wrd2 = p.parts[1]; - *wrd1 = (p.parts[2] & 0xffff) << 16; + *wrd3 = p[0]; + *wrd2 = p[1]; + *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16; #endif #else - fp_declare_init_shape(srp, double); - srp.value = src; + fp_declare_init_shape(srp, src, double); fpu_debug(("extract_extended (%d,%d,%X,%X)\n", - srp.ieee.negative , srp.ieee.exponent, - srp.ieee.mantissa0, srp.ieee.mantissa1)); + srp->ieee.negative , srp->ieee.exponent, + srp->ieee.mantissa0, srp->ieee.mantissa1)); - uae_u32 exp = srp.ieee.exponent; + uae_u32 exp = srp->ieee.exponent; if (exp == FP_DOUBLE_EXP_MAX) exp = FP_EXTENDED_EXP_MAX; else exp += FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS; - *wrd1 = (srp.ieee.negative << 31) | (exp << 16); + *wrd1 = (srp->ieee.negative << 31) | (exp << 16); // always set the explicit integer bit. - *wrd2 = 0x80000000 | (srp.ieee.mantissa0 << 11) | ((srp.ieee.mantissa1 & 0xffe00000) >> 21); - *wrd3 = srp.ieee.mantissa1 << 11; + *wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 11) | ((srp->ieee.mantissa1 & 0xffe00000) >> 21); + *wrd3 = srp->ieee.mantissa1 << 11; #endif fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); } @@ -531,88 +486,41 @@ PRIVATE inline void FFPU extract_double(fpu_register const & src, // to_pack PRIVATE inline fpu_register FFPU make_packed(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) { - fpu_register d; - bool sm = (wrd1 & 0x80000000) != 0; - bool se = (wrd1 & 0x40000000) != 0; - int exp = (wrd1 & 0x7fff0000) >> 16; - unsigned int dig; - fpu_register pwr; - - if (exp == 0x7fff) - { - if (wrd2 == 0 && wrd3 == 0) - { - sm ? make_inf_negative(d) : make_inf_positive(d); - } else - { - make_nan(d); - } - return d; - } - dig = wrd1 & 0x0000000f; - if (dig == 0 && wrd2 == 0 && wrd3 == 0) - { - sm ? make_zero_negative(d) : make_zero_positive(d); - return d; - } + fpu_double d; + char *cp; + char str[100]; - /* - * Convert the bcd exponent to binary by successive adds and - * muls. Set the sign according to SE. Subtract 16 to compensate - * for the mantissa which is to be interpreted as 17 integer - * digits, rather than 1 integer and 16 fraction digits. - * Note: this operation can never overflow. - */ - exp = ((wrd1 >> 24) & 0xf); - exp = exp * 10 + ((wrd1 >> 20) & 0xf); - exp = exp * 10 + ((wrd1 >> 16) & 0xf); - if (se) - exp = -exp; - /* sub to compensate for shift of mant */ - exp = exp - 16; - - /* - * Convert the bcd mantissa to binary by successive - * adds and muls. Set the sign according to SM. - * The mantissa digits will be converted with the decimal point - * assumed following the least-significant digit. - * Note: this operation can never overflow. - */ - d = wrd1 & 0xf; - d = (d * LD(10.0)) + ((wrd2 >> 28) & 0xf); - d = (d * LD(10.0)) + ((wrd2 >> 24) & 0xf); - d = (d * LD(10.0)) + ((wrd2 >> 20) & 0xf); - d = (d * LD(10.0)) + ((wrd2 >> 16) & 0xf); - d = (d * LD(10.0)) + ((wrd2 >> 12) & 0xf); - d = (d * LD(10.0)) + ((wrd2 >> 8) & 0xf); - d = (d * LD(10.0)) + ((wrd2 >> 4) & 0xf); - d = (d * LD(10.0)) + ((wrd2 ) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 28) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 24) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 20) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 16) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 12) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 8) & 0xf); - d = (d * LD(10.0)) + ((wrd3 >> 4) & 0xf); - d = (d * LD(10.0)) + ((wrd3 ) & 0xf); + cp = str; + if (wrd1 & 0x80000000) + *cp++ = '-'; + *cp++ = (char)((wrd1 & 0xf) + '0'); + *cp++ = '.'; + *cp++ = (char)(((wrd2 >> 28) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 16) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 12) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 8) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 4) & 0xf) + '0'); + *cp++ = (char)(((wrd2 >> 0) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 28) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 16) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 12) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 8) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 4) & 0xf) + '0'); + *cp++ = (char)(((wrd3 >> 0) & 0xf) + '0'); + *cp++ = 'E'; + if (wrd1 & 0x40000000) + *cp++ = '-'; + *cp++ = (char)(((wrd1 >> 24) & 0xf) + '0'); + *cp++ = (char)(((wrd1 >> 20) & 0xf) + '0'); + *cp++ = (char)(((wrd1 >> 16) & 0xf) + '0'); + *cp = 0; + sscanf(str, "%le", &d); - /* Check the sign of the mant and make the value in fp0 the same sign. */ - if (sm) - d = -d; - - /* - * Calculate power-of-ten factor from exponent. - */ - if (exp < 0) - { - exp = -exp; - pwr = POWL(LD(10.0), exp); - d = d / pwr; - } else - { - pwr = POWL(LD(10.0), exp); - d = d * pwr; - } + fpu_debug(("make_packed str = %s\n",str)); fpu_debug(("make_packed(%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)d)); return d; @@ -621,88 +529,52 @@ PRIVATE inline fpu_register FFPU make_packed(uae_u32 wrd1, uae_u32 wrd2, uae_u32 // from_pack PRIVATE inline void FFPU extract_packed(fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) { - fpu_register pwr; - int exp; - fpu_register d; - bool sm, se; - int dig; - + int i; + int t; + char *cp; + char str[100]; + + sprintf(str, "%.16e", src); + + fpu_debug(("extract_packed(%.04f,%s)\n",(double)src,str)); + + cp = str; *wrd1 = *wrd2 = *wrd3 = 0; - - d = src; - sm = false; - if (isneg(src)) - { - d = -d; - sm = true; + if (*cp == '-') { + cp++; + *wrd1 = 0x80000000; + } + if (*cp == '+') + cp++; + *wrd1 |= (*cp++ - '0'); + if (*cp == '.') + cp++; + for (i = 0; i < 8; i++) { + *wrd2 <<= 4; + if (*cp >= '0' && *cp <= '9') + *wrd2 |= *cp++ - '0'; + } + for (i = 0; i < 8; i++) { + *wrd3 <<= 4; + if (*cp >= '0' && *cp <= '9') + *wrd3 |= *cp++ - '0'; + } + if (*cp == 'e' || *cp == 'E') { + cp++; + if (*cp == '-') { + cp++; + *wrd1 |= 0x40000000; + } + if (*cp == '+') + cp++; + t = 0; + for (i = 0; i < 3; i++) { + if (*cp >= '0' && *cp <= '9') + t = (t << 4) | (*cp++ - '0'); + } + *wrd1 |= t << 16; } - if (isnan(src)) - { - *wrd1 = sm ? 0xffff0000 : 0x7fff0000; - *wrd2 = 0xffffffff; - *wrd3 = 0xffffffff; - return; - } - if (isinf(src)) - { - *wrd1 = sm ? 0xffff0000 : 0x7fff0000; - *wrd2 = *wrd3 = 0; - return; - } - if (iszero(src)) - { - *wrd1 = sm ? 0x80000000 : 0x00000000; - *wrd2 = *wrd3 = 0; - return; - } - sm = false; - if (isneg(src)) - { - d = -d; - sm = true; - } - exp = (int)floor(LOG10L(d)); - se = false; - if (exp < 0) - { - exp = -exp; - se = true; - pwr = POWL(LD(10.0), exp); - d = d * pwr; - } else - { - pwr = POWL(LD(10.0), exp); - d = d / pwr; - } - dig = (int)d; d = LD(10) * (d - dig); *wrd1 |= dig; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 28; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 24; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 20; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 16; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 12; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 8; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig << 4; - dig = (int)d; d = LD(10) * (d - dig); *wrd2 |= dig; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 28; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 24; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 20; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 16; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 12; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 8; - dig = (int)d; d = LD(10) * (d - dig); *wrd3 |= dig << 4; - dig = (int)d; *wrd3 |= dig; - - dig = (exp / 100) % 10; - *wrd1 |= dig << 24; - dig = (exp / 10) % 10; - *wrd1 |= dig << 20; - dig = (exp) % 10; - *wrd1 |= dig << 16; - if (sm) - *wrd1 |= 0x80000000; - if (se) - *wrd1 |= 0x40000000; fpu_debug(("extract_packed(%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3)); } @@ -756,9 +628,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(); @@ -799,8 +673,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: @@ -847,15 +721,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; } @@ -864,7 +729,7 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe PRIVATE inline uae_s32 FFPU toint(fpu_register const & src) { fpu_register result; - switch (get_fpcr() & FPCR_ROUNDING_MODE) { + switch (get_fpcr() & 0x30) { case FPCR_ROUND_ZERO: result = fp_round_to_zero(src); break; @@ -1086,7 +951,7 @@ PRIVATE inline int FFPU fpp_cond(int condition) if (NaN) N = Z = 0; - switch (condition & 0x1f) { + switch (condition) { case 0x00: CONDRET("False",0); case 0x01: CONDRET("Equal",Z); case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N)); @@ -1156,7 +1021,7 @@ void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) { fpu_debug(("fscc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); - uae_u32 ad = 0; + uae_u32 ad; int cc = fpp_cond(extra & 0x3f); if (cc == -1) { m68k_setpc (m68k_getpc () - 4); @@ -1174,11 +1039,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); @@ -1210,7 +1075,7 @@ void FFPU fpuop_save(uae_u32 opcode) { fpu_debug(("fsave_opp at %08lx\n", m68k_getpc ())); - uae_u32 ad = 0; + uae_u32 ad; int incr = (opcode & 0x38) == 0x20 ? -1 : 1; int i; @@ -1271,7 +1136,7 @@ void FFPU fpuop_restore(uae_u32 opcode) { fpu_debug(("frestore_opp at %08lx\n", m68k_getpc ())); - uae_u32 ad = 0; + uae_u32 ad; uae_u32 d; int incr = (opcode & 0x38) == 0x20 ? -1 : 1; @@ -1468,7 +1333,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) } else if (extra & 0x2000) { /* FMOVEM FPP->memory */ - uae_u32 ad = 0; + uae_u32 ad; int incr = 0; if (get_fp_ad(opcode, &ad) == 0) { @@ -1510,7 +1375,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) } else { /* FMOVEM memory->FPP */ - uae_u32 ad = 0; + uae_u32 ad; if (get_fp_ad(opcode, &ad) == 0) { m68k_setpc (m68k_getpc () - 4); @@ -1556,7 +1421,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) return; case 6: case 7: { - uae_u32 ad = 0, list = 0; + uae_u32 ad, list = 0; int incr = 0; if (extra & 0x2000) { /* FMOVEM FPP->memory */ @@ -1703,27 +1568,27 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) switch (extra & 0x7f) { case 0x00: // FPU registers[reg] = 4.0 * atan(1.0); - FPU registers[reg] = LD(3.1415926535897932384626433832795029); + FPU registers[reg] = 3.1415926535897932384626433832795; fpu_debug(("FP const: Pi\n")); break; case 0x0b: // FPU registers[reg] = log10 (2.0); - FPU registers[reg] = LD(0.30102999566398119521); // 0.3010299956639811952137388947244930L + FPU registers[reg] = 0.30102999566398119521373889472449; fpu_debug(("FP const: Log 10 (2)\n")); break; case 0x0c: // FPU registers[reg] = exp (1.0); - FPU registers[reg] = LD(2.7182818284590452353); // 2.7182818284590452353602874713526625L + FPU registers[reg] = 2.7182818284590452353602874713527; fpu_debug(("FP const: e\n")); break; case 0x0d: // FPU registers[reg] = log (exp (1.0)) / log (2.0); - FPU registers[reg] = LD(1.4426950408889634073599246810019); + FPU registers[reg] = 1.4426950408889634073599246810019; fpu_debug(("FP const: Log 2 (e)\n")); break; case 0x0e: // FPU registers[reg] = log (exp (1.0)) / log (10.0); - FPU registers[reg] = LD(0.4342944819032518276511289189166051); + FPU registers[reg] = 0.43429448190325182765112891891661; fpu_debug(("FP const: Log 10 (e)\n")); break; case 0x0f: @@ -1732,70 +1597,70 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) break; case 0x30: // FPU registers[reg] = log (2.0); - FPU registers[reg] = LD(0.6931471805599453094172321214581766); + FPU registers[reg] = 0.69314718055994530941723212145818; fpu_debug(("FP const: ln(2)\n")); break; case 0x31: // FPU registers[reg] = log (10.0); - FPU registers[reg] = LD(2.3025850929940456840179914546843642); + FPU registers[reg] = 2.3025850929940456840179914546844; fpu_debug(("FP const: ln(10)\n")); break; case 0x32: // ?? - FPU registers[reg] = LD(1.0e0); + FPU registers[reg] = 1.0e0; fpu_debug(("FP const: 1.0e0\n")); break; case 0x33: - FPU registers[reg] = LD(1.0e1); + FPU registers[reg] = 1.0e1; fpu_debug(("FP const: 1.0e1\n")); break; case 0x34: - FPU registers[reg] = LD(1.0e2); + FPU registers[reg] = 1.0e2; fpu_debug(("FP const: 1.0e2\n")); break; case 0x35: - FPU registers[reg] = LD(1.0e4); + FPU registers[reg] = 1.0e4; fpu_debug(("FP const: 1.0e4\n")); break; case 0x36: - FPU registers[reg] = LD(1.0e8); + FPU registers[reg] = 1.0e8; fpu_debug(("FP const: 1.0e8\n")); break; case 0x37: - FPU registers[reg] = LD(1.0e16); + FPU registers[reg] = 1.0e16; fpu_debug(("FP const: 1.0e16\n")); break; case 0x38: - FPU registers[reg] = LD(1.0e32); + FPU registers[reg] = 1.0e32; fpu_debug(("FP const: 1.0e32\n")); break; case 0x39: - FPU registers[reg] = LD(1.0e64); + FPU registers[reg] = 1.0e64; fpu_debug(("FP const: 1.0e64\n")); break; case 0x3a: - FPU registers[reg] = LD(1.0e128); + FPU registers[reg] = 1.0e128; fpu_debug(("FP const: 1.0e128\n")); break; case 0x3b: - FPU registers[reg] = LD(1.0e256); + FPU registers[reg] = 1.0e256; fpu_debug(("FP const: 1.0e256\n")); break; -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE case 0x3c: - FPU registers[reg] = LD(1.0e512); + FPU registers[reg] = 1.0e512L; fpu_debug(("FP const: 1.0e512\n")); break; case 0x3d: - FPU registers[reg] = LD(1.0e1024); + FPU registers[reg] = 1.0e1024L; fpu_debug(("FP const: 1.0e1024\n")); break; case 0x3e: - FPU registers[reg] = LD(1.0e2048); + FPU registers[reg] = 1.0e2048L; fpu_debug(("FP const: 1.0e2048\n")); break; case 0x3f: - FPU registers[reg] = LD(1.0e4096); + FPU registers[reg] = 1.0e4096L; fpu_debug(("FP const: 1.0e4096\n")); #endif break; @@ -1896,20 +1761,20 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) fpu_debug(("FMUL %.04f\n",(double)src)); get_dest_flags(FPU registers[reg]); get_source_flags(src); - if (fl_dest.in_range && fl_source.in_range) { + 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) ) { + 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 { @@ -1917,8 +1782,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 { @@ -2102,21 +1967,17 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) fpu_debug(("FMUL %.04f\n",(double)src)); get_dest_flags(FPU registers[reg]); get_source_flags(src); - if (fl_dest.in_range && fl_source.in_range) { + if(fl_dest.in_range && fl_source.in_range) { FPU registers[reg] *= src; - if (unlikely(isinf(FPU registers[reg]))) - { - isneg(FPU registers[reg]) ? make_inf_negative(FPU registers[reg]) : make_inf_positive(FPU registers[reg]); - } } 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 { @@ -2124,8 +1985,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 { @@ -2161,23 +2022,19 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) // an overflow or underflow always results. // Here (int) cast is okay. int scale_factor = (int)fp_round_to_zero(src); -#if defined(USE_LONG_DOUBLE) || defined(USE_QUAD_DOUBLE) - fp_declare_init_shape(sxp, extended); - sxp.value = FPU registers[reg]; - sxp.ieee.exponent += scale_factor; - FPU registers[reg] = sxp.value; +#if USE_LONG_DOUBLE || USE_QUAD_DOUBLE + fp_declare_init_shape(sxp, FPU registers[reg], extended); + sxp->ieee.exponent += scale_factor; #else - fp_declare_init_shape(sxp, double); - sxp.value = FPU registers[reg]; - uae_u32 exp = sxp.ieee.exponent + scale_factor; + fp_declare_init_shape(sxp, FPU registers[reg], double); + uae_u32 exp = sxp->ieee.exponent + scale_factor; if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS) exp = 0; else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS) exp = FP_DOUBLE_EXP_MAX; else exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS; - sxp.ieee.exponent = exp; - FPU registers[reg] = sxp.value; + sxp->ieee.exponent = exp; #endif } else if (fl_source.infinity) { @@ -2199,10 +2056,6 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) case 0x22: /* FADD */ fpu_debug(("FADD %.04f\n",(double)src)); FPU registers[reg] += src; - if (unlikely(isinf(FPU registers[reg]))) - { - isneg(FPU registers[reg]) ? make_inf_negative(FPU registers[reg]) : make_inf_positive(FPU registers[reg]); - } make_fpsr(FPU registers[reg]); break; case 0x30: /* FSINCOS */ @@ -2223,17 +2076,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) case 0x38: /* FCMP */ fpu_debug(("FCMP %.04f\n",(double)src)); set_fpsr(0); - if (isinf(FPU registers[reg])) - { - if (isinf(src) && isneg(FPU registers[reg]) == isneg (src)) - make_fpsr(0); - else - make_fpsr(FPU registers[reg]); - } - else if (isinf(src)) - make_fpsr(-src); - else - make_fpsr(FPU registers[reg] - src); + make_fpsr(FPU registers[reg] - src); break; case 0x3a: /* FTST */ fpu_debug(("FTST %.04f\n",(double)src)); @@ -2257,27 +2100,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 -------------------------- */ PRIVATE uae_u8 m_fpu_state_original[108]; // 90/94/108 diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h index 3321891a..89501956 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_ieee.h @@ -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 diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp deleted file mode 100644 index 1975aba8..00000000 --- a/BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp +++ /dev/null @@ -1,2110 +0,0 @@ -/* - * fpu_mpfr.cpp - emulate 68881/68040 fpu with mpfr - * - * Copyright (c) 2012, 2013 Andreas Schwab - * - * 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 -#include "memory.h" -#include "readcpu.h" -#include "newcpu.h" -#include "main.h" -#define FPU_IMPLEMENTATION -#include "fpu/fpu.h" - -#include "fpu/flags.h" -#include "fpu/exceptions.h" -#include "fpu/rounding.h" -#include "fpu/impl.h" - -#define SINGLE_PREC 24 -#define SINGLE_MIN_EXP -126 -#define SINGLE_MAX_EXP 127 -#define SINGLE_BIAS 127 -#define DOUBLE_PREC 53 -#define DOUBLE_MIN_EXP -1022 -#define DOUBLE_MAX_EXP 1023 -#define DOUBLE_BIAS 1023 -#define EXTENDED_PREC 64 -#define EXTENDED_MIN_EXP -16383 -#define EXTENDED_MAX_EXP 16383 -#define EXTENDED_BIAS 16383 - -fpu_t fpu; -// The constant ROM -// Constants 48 to 63 are mapped to index 16 to 31 -const int num_fpu_constants = 32; -static mpfr_t fpu_constant_rom[num_fpu_constants]; -#define FPU_CONSTANT_ONE fpu_constant_rom[18] -// Exceptions generated during execution in addition to the ones -// maintained by mpfr -static uae_u32 cur_exceptions; -static uaecptr cur_instruction_address; - -static void -set_format (int prec) -{ - // MPFR represents numbers as 0.m*2^e - switch (prec) - { - case SINGLE_PREC: - mpfr_set_emin (SINGLE_MIN_EXP + 1 - (SINGLE_PREC - 1)); - mpfr_set_emax (SINGLE_MAX_EXP + 1); - break; - case DOUBLE_PREC: - mpfr_set_emin (DOUBLE_MIN_EXP + 1 - (DOUBLE_PREC - 1)); - mpfr_set_emax (DOUBLE_MAX_EXP + 1); - break; - case EXTENDED_PREC: - mpfr_set_emin (EXTENDED_MIN_EXP + 1 - (EXTENDED_PREC - 1)); - mpfr_set_emax (EXTENDED_MAX_EXP + 1); - break; - } -} - -static mpfr_rnd_t -get_cur_rnd () -{ - switch (get_rounding_mode ()) - { - default: - case FPCR_ROUND_NEAR: - return MPFR_RNDN; - case FPCR_ROUND_ZERO: - return MPFR_RNDZ; - case FPCR_ROUND_MINF: - return MPFR_RNDD; - case FPCR_ROUND_PINF: - return MPFR_RNDU; - } -} - -static mpfr_prec_t -get_cur_prec () -{ - switch (get_rounding_precision ()) - { - default: - case FPCR_PRECISION_EXTENDED: - return EXTENDED_PREC; - case FPCR_PRECISION_SINGLE: - return SINGLE_PREC; - case FPCR_PRECISION_DOUBLE: - return DOUBLE_PREC; - } -} - -#define DEFAULT_NAN_BITS 0xffffffffffffffffULL - -static void -set_nan (fpu_register ®, uae_u64 nan_bits, int nan_sign) -{ - mpfr_set_nan (reg.f); - reg.nan_bits = nan_bits; - reg.nan_sign = nan_sign; -} - -static void -set_nan (fpu_register ®) -{ - set_nan (reg, DEFAULT_NAN_BITS, 0); -} - -static bool fpu_inited; - -void -fpu_init (bool integral_68040) -{ - fpu.is_integral = integral_68040; - - mpfr_set_default_prec (EXTENDED_PREC); - mpfr_set_default_rounding_mode (MPFR_RNDN); - set_format (EXTENDED_PREC); - - for (int i = 0; i < 8; i++) - mpfr_init (fpu.registers[i].f); - mpfr_init (fpu.result.f); - - // Initialize constant ROM - for (int i = 0; i < num_fpu_constants; i++) - mpfr_init (fpu_constant_rom[i]); - - // 0: pi - mpfr_const_pi (fpu_constant_rom[0], MPFR_RNDN); - // 11: log10 (2) - mpfr_set_ui (fpu_constant_rom[11], 2, MPFR_RNDN); - mpfr_log10 (fpu_constant_rom[11], fpu_constant_rom[11], MPFR_RNDZ); - // 12: e - mpfr_set_ui (fpu_constant_rom[12], 1, MPFR_RNDN); - mpfr_exp (fpu_constant_rom[12], fpu_constant_rom[12], MPFR_RNDZ); - // 13: log2 (e) - mpfr_log2 (fpu_constant_rom[13], fpu_constant_rom[12], MPFR_RNDU); - // 14: log10 (e) - mpfr_log10 (fpu_constant_rom[14], fpu_constant_rom[12], MPFR_RNDU); - // 15: 0 - mpfr_set_zero (fpu_constant_rom[15], 0); - // 48: ln (2) - mpfr_const_log2 (fpu_constant_rom[16], MPFR_RNDN); - // 49: ln (10) - mpfr_set_ui (fpu_constant_rom[17], 10, MPFR_RNDN); - mpfr_log (fpu_constant_rom[17], fpu_constant_rom[17], MPFR_RNDN); - // 50 to 63: powers of 10 - mpfr_set_ui (fpu_constant_rom[18], 1, MPFR_RNDN); - for (int i = 19; i < 32; i++) - { - mpfr_set_ui (fpu_constant_rom[i], 1L << (i - 19) , MPFR_RNDN); - mpfr_exp10 (fpu_constant_rom[i], fpu_constant_rom[i], MPFR_RNDN); - } - - fpu_inited = true; - - fpu_reset (); -} - -void -fpu_exit () -{ - if (!fpu_inited) return; - - for (int i = 0; i < 8; i++) - mpfr_clear (fpu.registers[i].f); - mpfr_clear (fpu.result.f); - for (int i = 0; i < num_fpu_constants; i++) - mpfr_clear (fpu_constant_rom[i]); -} - -void -fpu_reset () -{ - set_fpcr (0); - set_fpsr (0); - fpu.instruction_address = 0; - - for (int i = 0; i < 8; i++) - set_nan (fpu.registers[i]); -} - -fpu_register::operator long double () -{ - return mpfr_get_ld (f, MPFR_RNDN); -} - -fpu_register & -fpu_register::operator= (long double x) -{ - mpfr_set_ld (f, x, MPFR_RNDN); - nan_bits = DEFAULT_NAN_BITS; - nan_sign = 0; - return *this; -} - -static bool -get_fp_addr (uae_u32 opcode, uae_u32 *addr, bool write) -{ - uaecptr pc; - int mode; - int reg; - - mode = (opcode >> 3) & 7; - reg = opcode & 7; - switch (mode) - { - case 0: - case 1: - return false; - case 2: - *addr = m68k_areg (regs, reg); - break; - case 3: - *addr = m68k_areg (regs, reg); - break; - case 4: - *addr = m68k_areg (regs, reg); - break; - case 5: - *addr = m68k_areg (regs, reg) + (uae_s16) next_iword(); - break; - case 6: - *addr = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch (reg) - { - case 0: - *addr = (uae_s16) next_iword(); - break; - case 1: - *addr = next_ilong(); - break; - case 2: - if (write) - return false; - pc = m68k_getpc (); - *addr = pc + (uae_s16) next_iword(); - break; - case 3: - if (write) - return false; - pc = m68k_getpc (); - *addr = get_disp_ea_020 (pc, next_iword()); - break; - default: - return false; - } - } - return true; -} - -static void -set_from_single (fpu_register &value, uae_u32 data) -{ - int s = data >> 31; - int e = (data >> 23) & 0xff; - uae_u32 m = data & 0x7fffff; - - if (e == 0xff) - { - if (m != 0) - { - if (!(m & 0x400000)) - cur_exceptions |= FPSR_EXCEPTION_SNAN; - set_nan (value, (uae_u64) (m | 0xc00000) << (32 + 8), s); - } - else - mpfr_set_inf (value.f, 0); - } - else - { - if (e != 0) - // Add integer bit - m |= 0x800000; - else - e++; - // Remove bias - e -= SINGLE_BIAS; - mpfr_set_ui_2exp (value.f, m, e - (SINGLE_PREC - 1), MPFR_RNDN); - } - mpfr_setsign (value.f, value.f, s, MPFR_RNDN); -} - -static void -set_from_double (fpu_register &value, uae_u32 words[2]) -{ - int s = words[0] >> 31; - int e = (words[0] >> 20) & 0x7ff; - uae_u32 m = words[0] & 0xfffff; - - if (e == 0x7ff) - { - if ((m | words[1]) != 0) - { - if (!(m & 0x80000)) - cur_exceptions |= FPSR_EXCEPTION_SNAN; - set_nan (value, (((uae_u64) (m | 0x180000) << (32 + 11)) - | ((uae_u64) words[1] << 11)), s); - } - else - mpfr_set_inf (value.f, 0); - } - else - { - if (e != 0) - // Add integer bit - m |= 0x100000; - else - e++; - // Remove bias - e -= DOUBLE_BIAS; - mpfr_set_uj_2exp (value.f, ((uintmax_t) m << 32) | words[1], - e - (DOUBLE_PREC - 1), MPFR_RNDN); - } - mpfr_setsign (value.f, value.f, s, MPFR_RNDN); -} - -static void -set_from_extended (fpu_register &value, uae_u32 words[3], bool check_snan) -{ - int s = words[0] >> 31; - int e = (words[0] >> 16) & 0x7fff; - - if (e == 0x7fff) - { - if (((words[1] & 0x7fffffff) | words[2]) != 0) - { - if (check_snan) - { - if ((words[1] & 0x40000000) == 0) - cur_exceptions |= FPSR_EXCEPTION_SNAN; - words[1] |= 0x40000000; - } - set_nan (value, ((uae_u64) words[1] << 32) | words[2], s); - } - else - mpfr_set_inf (value.f, 0); - } - else - { - // Remove bias - e -= EXTENDED_BIAS; - mpfr_set_uj_2exp (value.f, ((uintmax_t) words[1] << 32) | words[2], - e - (EXTENDED_PREC - 1), MPFR_RNDN); - } - mpfr_setsign (value.f, value.f, s, MPFR_RNDN); -} - -#define from_bcd(d) ((d) < 10 ? (d) : (d) - 10) - -static void -set_from_packed (fpu_register &value, uae_u32 words[3]) -{ - char str[32], *p = str; - int sm = words[0] >> 31; - int se = (words[0] >> 30) & 1; - int i; - - if (((words[0] >> 16) & 0x7fff) == 0x7fff) - { - if ((words[1] | words[2]) != 0) - { - if ((words[1] & 0x40000000) == 0) - cur_exceptions |= FPSR_EXCEPTION_SNAN; - set_nan (value, ((uae_u64) (words[1] | 0x40000000) << 32) | words[2], - sm); - } - else - mpfr_set_inf (value.f, 0); - } - else - { - if (sm) - *p++ = '-'; - *p++ = from_bcd (words[0] & 15) + '0'; - *p++ = '.'; - for (i = 0; i < 8; i++) - { - p[i] = from_bcd ((words[1] >> (28 - i * 4)) & 15) + '0'; - p[i + 8] = from_bcd ((words[2] >> (28 - i * 4)) & 15) + '0'; - } - p += 16; - *p++ = 'e'; - if (se) - *p++ = '-'; - *p++ = from_bcd ((words[0] >> 24) & 15) + '0'; - *p++ = from_bcd ((words[0] >> 20) & 15) + '0'; - *p++ = from_bcd ((words[0] >> 16) & 15) + '0'; - *p = 0; - mpfr_set_str (value.f, str, 10, MPFR_RNDN); - } - mpfr_setsign (value.f, value.f, sm, MPFR_RNDN); -} - -static bool -get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register &value) -{ - int mode, reg, size; - uaecptr pc; - uae_u32 addr; - uae_u32 words[3]; - static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; - static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; - - if ((extra & 0x4000) == 0) - { - mpfr_set (value.f, fpu.registers[(extra >> 10) & 7].f, MPFR_RNDN); - value.nan_bits = fpu.registers[(extra >> 10) & 7].nan_bits; - value.nan_sign = fpu.registers[(extra >> 10) & 7].nan_sign; - /* Check for SNaN. */ - if (mpfr_nan_p (value.f) && (value.nan_bits & (1ULL << 62)) == 0) - { - value.nan_bits |= 1ULL << 62; - cur_exceptions |= FPSR_EXCEPTION_SNAN; - } - return true; - } - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; - switch (mode) - { - case 0: - switch (size) - { - case 6: - mpfr_set_si (value.f, (uae_s8) m68k_dreg (regs, reg), MPFR_RNDN); - break; - case 4: - mpfr_set_si (value.f, (uae_s16) m68k_dreg (regs, reg), MPFR_RNDN); - break; - case 0: - mpfr_set_si (value.f, (uae_s32) m68k_dreg (regs, reg), MPFR_RNDN); - break; - case 1: - set_from_single (value, m68k_dreg (regs, reg)); - break; - default: - return false; - } - return true; - case 1: - return false; - case 2: - case 3: - addr = m68k_areg (regs, reg); - break; - case 4: - addr = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); - break; - case 5: - addr = m68k_areg (regs, reg) + (uae_s16) next_iword (); - break; - case 6: - addr = get_disp_ea_020 (m68k_areg (regs, reg), next_iword ()); - break; - case 7: - switch (reg) - { - case 0: - addr = (uae_s16) next_iword (); - break; - case 1: - addr = next_ilong (); - break; - case 2: - pc = m68k_getpc (); - addr = pc + (uae_s16) next_iword (); - break; - case 3: - pc = m68k_getpc (); - addr = get_disp_ea_020 (pc, next_iword ()); - break; - case 4: - addr = m68k_getpc (); - m68k_incpc (sz2[size]); - if (size == 6) // Immediate byte - addr++; - break; - default: - return false; - } - } - - switch (size) - { - case 0: - mpfr_set_si (value.f, (uae_s32) get_long (addr), MPFR_RNDN); - break; - case 1: - set_from_single (value, get_long (addr)); - break; - case 2: - words[0] = get_long (addr); - words[1] = get_long (addr + 4); - words[2] = get_long (addr + 8); - set_from_extended (value, words, true); - break; - case 3: - words[0] = get_long (addr); - words[1] = get_long (addr + 4); - words[2] = get_long (addr + 8); - set_from_packed (value, words); - break; - case 4: - mpfr_set_si (value.f, (uae_s16) get_word (addr), MPFR_RNDN); - break; - case 5: - words[0] = get_long (addr); - words[1] = get_long (addr + 4); - set_from_double (value, words); - break; - case 6: - mpfr_set_si (value.f, (uae_s8) get_byte (addr), MPFR_RNDN); - break; - default: - return false; - } - - 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; - } - - return true; -} - -static void -update_exceptions () -{ - uae_u32 exc, aexc; - - exc = cur_exceptions; - // Add any mpfr detected exceptions - if (mpfr_underflow_p ()) - exc |= FPSR_EXCEPTION_UNFL; - if (mpfr_overflow_p ()) - exc |= FPSR_EXCEPTION_OVFL; - if (mpfr_inexflag_p ()) - exc |= FPSR_EXCEPTION_INEX2; - set_exception_status (exc); - - aexc = get_accrued_exception (); - if (exc & (FPSR_EXCEPTION_SNAN|FPSR_EXCEPTION_OPERR)) - aexc |= FPSR_ACCR_IOP; - if (exc & FPSR_EXCEPTION_OVFL) - aexc |= FPSR_ACCR_OVFL; - if ((exc & (FPSR_EXCEPTION_UNFL|FPSR_EXCEPTION_INEX2)) - == (FPSR_EXCEPTION_UNFL|FPSR_EXCEPTION_INEX2)) - aexc |= FPSR_ACCR_UNFL; - if (exc & FPSR_EXCEPTION_DZ) - aexc |= FPSR_ACCR_DZ; - if (exc & (FPSR_EXCEPTION_INEX1|FPSR_EXCEPTION_INEX2|FPSR_EXCEPTION_OVFL)) - aexc |= FPSR_ACCR_INEX; - set_accrued_exception (aexc); - - if ((fpu.fpcr.exception_enable & exc) != 0) - { - fpu.instruction_address = cur_instruction_address; - // TODO: raise exceptions - // Problem: FPSP040 depends on proper FPU stack frames, it would suffer - // undefined behaviour with our dummy FSAVE implementation - } -} - -static void -set_fp_register (int reg, mpfr_t value, uae_u64 nan_bits, int nan_sign, - int t, mpfr_rnd_t rnd, bool do_flags) -{ - mpfr_subnormalize (value, t, rnd); - mpfr_set (fpu.registers[reg].f, value, rnd); - fpu.registers[reg].nan_bits = nan_bits; - fpu.registers[reg].nan_sign = nan_sign; - if (do_flags) - { - uae_u32 flags = 0; - - if (mpfr_zero_p (fpu.registers[reg].f)) - flags |= FPSR_CCB_ZERO; - if (mpfr_signbit (fpu.registers[reg].f)) - flags |= FPSR_CCB_NEGATIVE; - if (mpfr_nan_p (fpu.registers[reg].f)) - flags |= FPSR_CCB_NAN; - if (mpfr_inf_p (fpu.registers[reg].f)) - flags |= FPSR_CCB_INFINITY; - set_fpccr (flags); - } -} - -static void -set_fp_register (int reg, mpfr_t value, int t, mpfr_rnd_t rnd, bool do_flags) -{ - set_fp_register (reg, value, DEFAULT_NAN_BITS, 0, t, rnd, do_flags); -} - -static void -set_fp_register (int reg, fpu_register &value, int t, mpfr_rnd_t rnd, - bool do_flags) -{ - set_fp_register (reg, value.f, value.nan_bits, value.nan_sign, t, rnd, - do_flags); -} - -static uae_u32 -extract_to_single (fpu_register &value) -{ - uae_u32 word; - int t; - mpfr_rnd_t rnd = get_cur_rnd (); - MPFR_DECL_INIT (single, SINGLE_PREC); - - set_format (SINGLE_PREC); - // Round to single - t = mpfr_set (single, value.f, rnd); - t = mpfr_check_range (single, t, rnd); - mpfr_subnormalize (single, t, rnd); - set_format (EXTENDED_PREC); - - if (mpfr_inf_p (single)) - word = 0x7f800000; - else if (mpfr_nan_p (single)) - { - if ((value.nan_bits & (1ULL << 62)) == 0) - { - value.nan_bits |= 1ULL << 62; - cur_exceptions |= FPSR_EXCEPTION_SNAN; - } - word = 0x7f800000 | ((value.nan_bits >> (32 + 8)) & 0x7fffff); - if (value.nan_sign) - word |= 0x80000000; - } - else if (mpfr_zero_p (single)) - word = 0; - else - { - int e; - mpz_t f; - mpz_init (f); - word = 0; - // Get exponent and mantissa - e = mpfr_get_z_2exp (f, single); - // Move binary point - e += SINGLE_PREC - 1; - // Add bias - e += SINGLE_BIAS; - if (e <= 0) - { - // Denormalized number - mpz_tdiv_q_2exp (f, f, -e + 1); - e = 0; - } - mpz_export (&word, 0, 1, 4, 0, 0, f); - // Remove integer bit - word &= 0x7fffff; - word |= e << 23; - mpz_clear (f); - } - if (mpfr_signbit (single)) - word |= 0x80000000; - return word; -} - -static void -extract_to_double (fpu_register &value, uint32_t *words) -{ - int t; - mpfr_rnd_t rnd = get_cur_rnd (); - MPFR_DECL_INIT (dbl, DOUBLE_PREC); - - set_format (DOUBLE_PREC); - // Round to double - t = mpfr_set (dbl, value.f, rnd); - t = mpfr_check_range (dbl, t, rnd); - mpfr_subnormalize (dbl, t, rnd); - set_format (EXTENDED_PREC); - - if (mpfr_inf_p (dbl)) - { - words[0] = 0x7ff00000; - words[1] = 0; - } - else if (mpfr_nan_p (dbl)) - { - if ((value.nan_bits & (1ULL << 62)) == 0) - { - value.nan_bits |= 1ULL << 62; - cur_exceptions |= FPSR_EXCEPTION_SNAN; - } - words[0] = 0x7ff00000 | ((value.nan_bits >> (32 + 11)) & 0xfffff); - words[1] = value.nan_bits >> 11; - if (value.nan_sign) - words[0] |= 0x80000000; - } - else if (mpfr_zero_p (dbl)) - { - words[0] = 0; - words[1] = 0; - } - else - { - int e, off = 0; - mpz_t f; - mpz_init (f); - words[0] = words[1] = 0; - // Get exponent and mantissa - e = mpfr_get_z_2exp (f, dbl); - // Move binary point - e += DOUBLE_PREC - 1; - // Add bias - e += DOUBLE_BIAS; - if (e <= 0) - { - // Denormalized number - mpz_tdiv_q_2exp (f, f, -e + 1); - if (e <= -20) - // No more than 32 bits left - off = 1; - e = 0; - } - mpz_export (&words[off], 0, 1, 4, 0, 0, f); - // Remove integer bit - words[0] &= 0xfffff; - words[0] |= e << 20; - mpz_clear (f); - } - if (mpfr_signbit (dbl)) - words[0] |= 0x80000000; -} - -static void -extract_to_extended (fpu_register &value, uint32_t *words) -{ - if (mpfr_inf_p (value.f)) - { - words[0] = 0x7fff0000; - words[1] = 0; - words[2] = 0; - } - else if (mpfr_nan_p (value.f)) - { - words[0] = 0x7fff0000; - words[1] = value.nan_bits >> 32; - words[2] = value.nan_bits; - if (value.nan_sign) - words[0] |= 0x80000000; - } - else if (mpfr_zero_p (value.f)) - { - words[0] = 0; - words[1] = 0; - words[2] = 0; - } - else - { - int e, off = 0; - mpz_t f; - - mpz_init (f); - words[0] = words[1] = words[2] = 0; - // Get exponent and mantissa - e = mpfr_get_z_2exp (f, value.f); - // Move binary point - e += EXTENDED_PREC - 1; - // Add bias - e += EXTENDED_BIAS; - if (e < 0) - { - // Denormalized number - mpz_tdiv_q_2exp (f, f, -e); - if (e <= -32) - // No more than 32 bits left - off = 1; - e = 0; - } - mpz_export (&words[1 + off], 0, 1, 4, 0, 0, f); - words[0] = e << 16; - mpz_clear (f); - } - if (mpfr_signbit (value.f)) - words[0] |= 0x80000000; -} - -static void -extract_to_packed (fpu_register &value, int k, uae_u32 *words) -{ - if (mpfr_inf_p (value.f)) - { - words[0] = 0x7fff0000; - words[1] = 0; - words[2] = 0; - } - else if (mpfr_nan_p (value.f)) - { - words[0] = 0x7fff0000; - words[1] = value.nan_bits >> 32; - words[2] = value.nan_bits; - if (value.nan_sign) - words[0] |= 0x80000000; - } - else if (mpfr_zero_p (value.f)) - { - words[0] = 0; - words[1] = 0; - words[2] = 0; - } - else - { - char str[100], *p = str; - mpfr_exp_t e; - mpfr_rnd_t rnd = get_cur_rnd (); - - words[0] = words[1] = words[2] = 0; - if (k >= 64) - k -= 128; - else if (k >= 18) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - if (k <= 0) - { - MPFR_DECL_INIT (temp, 16); - - mpfr_log10 (temp, value.f, rnd); - k = mpfr_get_si (temp, MPFR_RNDZ) - k + 1; - } - if (k <= 0) - k = 1; - else if (k >= 18) - k = 17; - mpfr_get_str (str, &e, 10, k, value.f, rnd); - e--; - if (*p == '-') - p++; - // Pad to 17 digits - while (k < 17) - p[k++] = '0'; - if (e < 0) - { - words[0] |= 0x40000000; - e = -e; - } - words[0] |= (e % 10) << 16; - e /= 10; - words[0] |= (e % 10) << 20; - e /= 10; - words[0] |= (e % 10) << 24; - e /= 10; - if (e) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - words[0] |= e << 12; - words[0] |= *p++ & 15; - for (k = 0; k < 8; k++) - words[1] = (words[1] << 4) | (*p++ & 15); - for (k = 0; k < 8; k++) - words[2] = (words[2] << 4) | (*p++ & 15); - - } - if (mpfr_signbit (value.f)) - words[0] |= 0x80000000; -} - -static long -extract_to_integer (mpfr_t value, long min, long max) -{ - long result; - mpfr_rnd_t rnd = get_cur_rnd (); - - if (mpfr_fits_slong_p (value, rnd)) - { - result = mpfr_get_si (value, rnd); - if (result > max) - { - result = max; - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (result < min) - { - result = min; - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - } - else - { - if (!mpfr_signbit (value)) - result = max; - else - result = min; - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - return result; -} - -static bool -fpuop_fmove_memory (uae_u32 opcode, uae_u32 extra) -{ - int mode, reg, size; - uaecptr pc; - uae_u32 addr; - uae_u32 words[3]; - static const int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0}; - static const int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0}; - - mpfr_clear_flags (); - cur_exceptions = 0; - mode = (opcode >> 3) & 7; - reg = opcode & 7; - size = (extra >> 10) & 7; - fpu_register &value = fpu.registers[(extra >> 7) & 7]; - - switch (mode) - { - case 0: - switch (size) - { - case 0: - m68k_dreg (regs, reg) = extract_to_integer (value.f, -0x7fffffff-1, 0x7fffffff); - break; - case 1: - m68k_dreg (regs, reg) = extract_to_single (value); - break; - case 4: - m68k_dreg (regs, reg) &= ~0xffff; - m68k_dreg (regs, reg) |= extract_to_integer (value.f, -32768, 32767) & 0xffff; - break; - case 6: - m68k_dreg (regs, reg) &= ~0xff; - m68k_dreg (regs, reg) |= extract_to_integer (value.f, -128, 127) & 0xff; - break; - default: - return false; - } - update_exceptions (); - return true; - case 1: - return false; - case 2: - addr = m68k_areg (regs, reg); - break; - case 3: - addr = m68k_areg (regs, reg); - break; - case 4: - addr = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); - break; - case 5: - addr = m68k_areg (regs, reg) + (uae_s16) next_iword(); - break; - case 6: - addr = get_disp_ea_020 (m68k_areg (regs, reg), next_iword()); - break; - case 7: - switch (reg) - { - case 0: - addr = (uae_s16) next_iword(); - break; - case 1: - addr = next_ilong(); - break; - case 2: - pc = m68k_getpc (); - addr = pc + (uae_s16) next_iword(); - break; - case 3: - pc = m68k_getpc (); - addr = get_disp_ea_020 (pc, next_iword ()); - break; - case 4: - addr = m68k_getpc (); - m68k_incpc (sz2[size]); - break; - default: - return false; - } - } - - switch (size) - { - case 0: - put_long (addr, extract_to_integer (value.f, -0x7fffffff-1, 0x7fffffff)); - break; - case 1: - put_long (addr, extract_to_single (value)); - break; - case 2: - extract_to_extended (value, words); - put_long (addr, words[0]); - put_long (addr + 4, words[1]); - put_long (addr + 8, words[2]); - break; - case 3: - extract_to_packed (value, extra & 0x7f, words); - put_long (addr, words[0]); - put_long (addr + 4, words[1]); - put_long (addr + 8, words[2]); - break; - case 4: - put_word (addr, extract_to_integer (value.f, -32768, 32767)); - break; - case 5: - extract_to_double (value, words); - put_long (addr, words[0]); - put_long (addr + 4, words[1]); - break; - case 6: - put_byte (addr, extract_to_integer (value.f, -128, 127)); - break; - case 7: - extract_to_packed (value, m68k_dreg (regs, (extra >> 4) & 7) & 0x7f, words); - put_long (addr, words[0]); - put_long (addr + 4, words[1]); - put_long (addr + 8, words[2]); - break; - } - - 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; - } - - update_exceptions (); - return true; -} - -static bool -fpuop_fmovem_control (uae_u32 opcode, uae_u32 extra) -{ - int list, mode, reg; - uae_u32 addr; - - list = (extra >> 10) & 7; - mode = (opcode >> 3) & 7; - reg = opcode & 7; - - if (list == 0) - return false; - - if (extra & 0x2000) - { - // FMOVEM to - if (mode == 0) - { - switch (list) - { - case 1: - m68k_dreg (regs, reg) = fpu.instruction_address; - break; - case 2: - m68k_dreg (regs, reg) = get_fpsr (); - break; - case 4: - m68k_dreg (regs, reg) = get_fpcr (); - break; - default: - return false; - } - } - else if (mode == 1) - { - if (list != 1) - return false; - m68k_areg (regs, reg) = fpu.instruction_address; - } - else - { - int nwords; - - if (!get_fp_addr (opcode, &addr, true)) - return false; - nwords = (list & 1) + ((list >> 1) & 1) + ((list >> 2) & 1); - if (mode == 4) - addr -= nwords * 4; - if (list & 4) - { - put_long (addr, get_fpcr ()); - addr += 4; - } - if (list & 2) - { - put_long (addr, get_fpsr ()); - addr += 4; - } - if (list & 1) - { - put_long (addr, fpu.instruction_address); - addr += 4; - } - if (mode == 4) - m68k_areg (regs, reg) = addr - nwords * 4; - else if (mode == 3) - m68k_areg (regs, reg) = addr; - } - } - else - { - // FMOVEM from - - if (mode == 0) - { - switch (list) - { - case 1: - fpu.instruction_address = m68k_dreg (regs, reg); - break; - case 2: - set_fpsr (m68k_dreg (regs, reg)); - break; - case 4: - set_fpcr (m68k_dreg (regs, reg)); - break; - default: - return false; - } - } - else if (mode == 1) - { - if (list != 1) - return false; - fpu.instruction_address = m68k_areg (regs, reg); - } - else if ((opcode & 077) == 074) - { - switch (list) - { - case 1: - fpu.instruction_address = next_ilong (); - break; - case 2: - set_fpsr (next_ilong ()); - break; - case 4: - set_fpcr (next_ilong ()); - break; - default: - return false; - } - } - else - { - int nwords; - - if (!get_fp_addr (opcode, &addr, false)) - return false; - nwords = (list & 1) + ((list >> 1) & 1) + ((list >> 2) & 1); - if (mode == 4) - addr -= nwords * 4; - if (list & 4) - { - set_fpcr (get_long (addr)); - addr += 4; - } - if (list & 2) - { - set_fpsr (get_long (addr)); - addr += 4; - } - if (list & 1) - { - fpu.instruction_address = get_long (addr); - addr += 4; - } - if (mode == 4) - m68k_areg (regs, reg) = addr - nwords * 4; - else if (mode == 3) - m68k_areg (regs, reg) = addr; - } - } - - return true; -} - -static bool -fpuop_fmovem_register (uae_u32 opcode, uae_u32 extra) -{ - uae_u32 addr; - uae_u32 words[3]; - int list; - int i; - - set_format (EXTENDED_PREC); - if (!get_fp_addr (opcode, &addr, extra & 0x2000)) - return false; - if (extra & 0x800) - list = m68k_dreg (regs, (extra >> 4) & 7) & 0xff; - else - list = extra & 0xff; - - if (extra & 0x2000) - { - // FMOVEM to memory - - switch (opcode & 070) - { - case 030: - return false; - case 040: - if (extra & 0x1000) - return false; - for (i = 7; i >= 0; i--) - if (list & (1 << i)) - { - extract_to_extended (fpu.registers[i], words); - addr -= 12; - put_long (addr, words[0]); - put_long (addr + 4, words[1]); - put_long (addr + 8, words[2]); - } - m68k_areg (regs, opcode & 7) = addr; - break; - default: - if ((extra & 0x1000) == 0) - return false; - for (i = 0; i < 8; i++) - if (list & (0x80 >> i)) - { - extract_to_extended (fpu.registers[i], words); - put_long (addr, words[0]); - put_long (addr + 4, words[1]); - put_long (addr + 8, words[2]); - addr += 12; - } - if ((opcode & 070) == 030) - m68k_areg (regs, opcode & 7) = addr; - break; - } - } - else - { - // FMOVEM from memory - - if ((opcode & 070) == 040) - return false; - - if ((extra & 0x1000) == 0) - return false; - for (i = 0; i < 8; i++) - if (list & (0x80 >> i)) - { - words[0] = get_long (addr); - words[1] = get_long (addr + 4); - words[2] = get_long (addr + 8); - addr += 12; - set_from_extended (fpu.registers[i], words, false); - } - if ((opcode & 070) == 030) - m68k_areg (regs, opcode & 7) = addr; - } - return true; -} - -static int -do_getexp (mpfr_t value, mpfr_rnd_t rnd) -{ - int t = 0; - - if (mpfr_inf_p (value)) - { - mpfr_set_nan (value); - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (!mpfr_nan_p (value) && !mpfr_zero_p (value)) - t = mpfr_set_si (value, mpfr_get_exp (value) - 1, rnd); - return t; -} - -static int -do_getman (mpfr_t value) -{ - if (mpfr_inf_p (value)) - { - mpfr_set_nan (value); - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (!mpfr_nan_p (value) && !mpfr_zero_p (value)) - mpfr_set_exp (value, 1); - return 0; -} - -static int -do_scale (mpfr_t value, mpfr_t reg, mpfr_rnd_t rnd) -{ - long scale; - int t = 0; - - if (mpfr_nan_p (value)) - ; - else if (mpfr_inf_p (value)) - { - mpfr_set_nan (value); - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (mpfr_fits_slong_p (value, rnd)) - { - scale = mpfr_get_si (value, MPFR_RNDZ); - mpfr_clear_inexflag (); - t = mpfr_mul_2si (value, reg, scale, rnd); - } - else - mpfr_set_inf (value, -mpfr_signbit (value)); - return t; -} - -static int -do_remainder (mpfr_t value, mpfr_t reg, mpfr_rnd_t rnd) -{ - long quo; - int t = 0; - - if (mpfr_nan_p (value) || mpfr_nan_p (reg)) - ; - else if (mpfr_zero_p (value) || mpfr_inf_p (reg)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_remquo (value, &quo, reg, value, rnd); - if (quo < 0) - quo = (-quo & 0x7f) | 0x80; - else - quo &= 0x7f; - fpu.fpsr.quotient = quo << 16; - return t; -} - -// Unfortunately, mpfr_fmod does not return the quotient bits, so we -// have to reimplement it here -static int -mpfr_rem1 (mpfr_t rem, int *quo, mpfr_t x, mpfr_t y, mpfr_rnd_t rnd) -{ - mpfr_exp_t ex, ey; - int inex, sign, signx = mpfr_signbit (x); - mpz_t mx, my, r; - - mpz_init (mx); - mpz_init (my); - mpz_init (r); - - ex = mpfr_get_z_2exp (mx, x); /* x = mx*2^ex */ - ey = mpfr_get_z_2exp (my, y); /* y = my*2^ey */ - - /* to get rid of sign problems, we compute it separately: - quo(-x,-y) = quo(x,y), rem(-x,-y) = -rem(x,y) - quo(-x,y) = -quo(x,y), rem(-x,y) = -rem(x,y) - thus quo = sign(x/y)*quo(|x|,|y|), rem = sign(x)*rem(|x|,|y|) */ - sign = (signx != mpfr_signbit (y)); - mpz_abs (mx, mx); - mpz_abs (my, my); - - /* divide my by 2^k if possible to make operations mod my easier */ - { - unsigned long k = mpz_scan1 (my, 0); - ey += k; - mpz_fdiv_q_2exp (my, my, k); - } - - if (ex <= ey) - { - /* q = x/y = mx/(my*2^(ey-ex)) */ - mpz_mul_2exp (my, my, ey - ex); /* divide mx by my*2^(ey-ex) */ - /* 0 <= |r| <= |my|, r has the same sign as mx */ - mpz_tdiv_qr (mx, r, mx, my); - /* mx is the quotient */ - mpz_tdiv_r_2exp (mx, mx, 7); - *quo = mpz_get_si (mx); - } - else /* ex > ey */ - { - /* to get the low 7 more bits of the quotient, we first compute - R = X mod Y*2^7, where X and Y are defined below. Then the - low 7 of the quotient are floor(R/Y). */ - mpz_mul_2exp (my, my, 7); /* 2^7*Y */ - - mpz_set_ui (r, 2); - mpz_powm_ui (r, r, ex - ey, my); /* 2^(ex-ey) mod my */ - mpz_mul (r, r, mx); - mpz_mod (r, r, my); - - /* now 0 <= r < 2^7*Y */ - mpz_fdiv_q_2exp (my, my, 7); /* back to Y */ - mpz_tdiv_qr (mx, r, r, my); - /* oldr = mx*my + newr */ - *quo = mpz_get_si (mx); - - /* now 0 <= |r| < |my| */ - } - - if (mpz_cmp_ui (r, 0) == 0) - { - inex = mpfr_set_ui (rem, 0, MPFR_RNDN); - /* take into account sign of x */ - if (signx) - mpfr_neg (rem, rem, MPFR_RNDN); - } - else - { - /* take into account sign of x */ - if (signx) - mpz_neg (r, r); - inex = mpfr_set_z_2exp (rem, r, ex > ey ? ey : ex, rnd); - } - - if (sign) - *quo |= 0x80; - - mpz_clear (mx); - mpz_clear (my); - mpz_clear (r); - - return inex; -} - -static int -do_fmod (mpfr_t value, mpfr_t reg, mpfr_rnd_t rnd) -{ - int t = 0; - - if (mpfr_nan_p (value) || mpfr_nan_p (reg)) - mpfr_set_nan (value); - else if (mpfr_zero_p (value) || mpfr_inf_p (reg)) - { - mpfr_set_nan (value); - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (mpfr_zero_p (reg) || mpfr_inf_p (value)) - { - fpu.fpsr.quotient = 0; - t = mpfr_set (value, reg, rnd); - } - else - { - int quo; - - t = mpfr_rem1 (value, &quo, reg, value, rnd); - fpu.fpsr.quotient = quo << 16; - } - return t; -} - -static void -do_fcmp (mpfr_t source, mpfr_t dest) -{ - uae_u32 flags = 0; - - if (mpfr_nan_p (source) || mpfr_nan_p (dest)) - flags |= FPSR_CCB_NAN; - else - { - int cmp = mpfr_cmp (dest, source); - if (cmp < 0) - flags |= FPSR_CCB_NEGATIVE; - else if (cmp == 0) - { - flags |= FPSR_CCB_ZERO; - if ((mpfr_zero_p (dest) || mpfr_inf_p (dest)) && mpfr_signbit (dest)) - flags |= FPSR_CCB_NEGATIVE; - } - } - set_fpccr (flags); -} - -static void -do_ftst (mpfr_t value) -{ - uae_u32 flags = 0; - - if (mpfr_signbit (value)) - flags |= FPSR_CCB_NEGATIVE; - if (mpfr_nan_p (value)) - flags |= FPSR_CCB_NAN; - else if (mpfr_zero_p (value)) - flags |= FPSR_CCB_ZERO; - else if (mpfr_inf_p (value)) - flags |= FPSR_CCB_INFINITY; - set_fpccr (flags); -} - -static bool -fpuop_general (uae_u32 opcode, uae_u32 extra) -{ - mpfr_prec_t prec = get_cur_prec (); - mpfr_rnd_t rnd = get_cur_rnd (); - int reg = (extra >> 7) & 7; - int t = 0; - fpu_register value; - bool ret; - - mpfr_init2 (value.f, prec); - value.nan_bits = DEFAULT_NAN_BITS; - value.nan_sign = 0; - - mpfr_clear_flags (); - set_format (prec); - cur_exceptions = 0; - cur_instruction_address = m68k_getpc () - 4; - if ((extra & 0xfc00) == 0x5c00) - { - // FMOVECR - int rom_index = extra & 0x7f; - if (rom_index == 0 || (rom_index >= 11 && rom_index <= 15)) - t = mpfr_set (value.f, fpu_constant_rom[rom_index], rnd); - else if (rom_index >= 48 && rom_index <= 63) - t = mpfr_set (value.f, fpu_constant_rom[rom_index - 32], rnd); - else - mpfr_set_zero (value.f, 0); - set_fp_register (reg, value, t, rnd, true); - } - else if (extra & 0x40) - { - static const char valid[64] = - { - 1, 1, 0, 0, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 1, 1, 0, 1, 1, - 1, 0, 0, 0, 1, 0, 0, 0 - }; - - if (extra & 4) - // FD... - prec = DOUBLE_PREC; - else - // FS... - prec = SINGLE_PREC; - set_format (prec); - MPFR_DECL_INIT (value2, prec); - - if (!fpu.is_integral) - { - ret = false; - goto out; - } - if (!valid[extra & 0x3b]) - { - ret = false; - goto out; - } - if (!get_fp_value (opcode, extra, value)) - { - ret = false; - goto out; - } - - switch (extra & 0x3f) - { - case 0: // FSMOVE - case 4: // FDMOVE - mpfr_set (value2, value.f, rnd); - break; - case 1: // FSSQRT - case 5: // FDSQRT - if (mpfr_sgn (value.f) < 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_sqrt (value2, value.f, rnd); - break; - case 24: // FSABS - case 28: // FDABS - t = mpfr_abs (value2, value.f, rnd); - break; - case 26: // FSNEG - case 30: // FDNEG - t = mpfr_neg (value2, value.f, rnd); - break; - case 32: // FSDIV - case 36: // FDDIV - if (mpfr_zero_p (value.f)) - { - if (mpfr_regular_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (mpfr_zero_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (mpfr_inf_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_div (value2, fpu.registers[reg].f, value.f, rnd); - break; - case 34: // FSADD - case 38: // FDADD - if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) - && mpfr_signbit (fpu.registers[reg].f) != mpfr_signbit (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_add (value2, fpu.registers[reg].f, value.f, rnd); - break; - case 35: // FSMUL - case 39: // FDMUL - if ((mpfr_zero_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) - || (mpfr_inf_p (value.f) && mpfr_zero_p (fpu.registers[reg].f))) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_mul (value2, fpu.registers[reg].f, value.f, rnd); - break; - case 40: // FSSUB - case 44: // FDSUB - if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) - && mpfr_signbit (fpu.registers[reg].f) == mpfr_signbit (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_sub (value2, fpu.registers[reg].f, value.f, rnd); - break; - } - set_fp_register (reg, value2, t, rnd, true); - } - else if ((extra & 0x30) == 0x30) - { - if ((extra & 15) > 10 || (extra & 15) == 9) - { - ret = false; - goto out; - } - if (!get_fp_value (opcode, extra, value)) - { - ret = false; - goto out; - } - - if ((extra & 15) < 8) - { - // FSINCOS - int reg2 = extra & 7; - MPFR_DECL_INIT (value2, prec); - - if (mpfr_inf_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_sin_cos (value.f, value2, value.f, rnd); - if (reg2 != reg) - set_fp_register (reg2, value2, t >> 2, rnd, false); - set_fp_register (reg, value, t & 3, rnd, true); - } - else if ((extra & 15) == 8) - // FCMP - do_fcmp (value.f, fpu.registers[reg].f); - else - // FTST - do_ftst (value.f); - } - else - { - static const char valid[64] = - { - 1, 1, 1, 1, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 1, - 1, 1, 1, 0, 1, 1, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1 - }; - if (!valid[extra & 0x3f]) - { - ret = false; - goto out; - } - if (!get_fp_value (opcode, extra, value)) - { - ret = false; - goto out; - } - - switch (extra & 0x3f) - { - case 0: // FMOVE - break; - case 1: // FINT - t = mpfr_rint (value.f, value.f, rnd); - break; - case 2: // FSINH - t = mpfr_sinh (value.f, value.f, rnd); - break; - case 3: // FINTRZ - t = mpfr_rint (value.f, value.f, MPFR_RNDZ); - break; - case 4: // FSQRT - if (mpfr_sgn (value.f) < 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_sqrt (value.f, value.f, rnd); - break; - case 6: // FLOGNP1 - if (!mpfr_nan_p (value.f)) - { - int cmp = mpfr_cmp_si (value.f, -1); - if (cmp == 0) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (cmp < 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - t = mpfr_log1p (value.f, value.f, rnd); - break; - case 8: // FETOXM1 - t = mpfr_expm1 (value.f, value.f, rnd); - break; - case 9: // FTANH - t = mpfr_tanh (value.f, value.f, rnd); - break; - case 10: // FATAN - t = mpfr_atan (value.f, value.f, rnd); - break; - case 12: // FASIN - if (mpfr_cmpabs (value.f, FPU_CONSTANT_ONE) > 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_asin (value.f, value.f, rnd); - break; - case 13: // FATANH - if (mpfr_cmpabs (value.f, FPU_CONSTANT_ONE) > 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_atanh (value.f, value.f, rnd); - break; - case 14: // FSIN - if (mpfr_inf_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_sin (value.f, value.f, rnd); - break; - case 15: // FTAN - if (mpfr_inf_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_tan (value.f, value.f, rnd); - break; - case 16: // FETOX - t = mpfr_exp (value.f, value.f, rnd); - break; - case 17: // FTWOTOX - t = mpfr_ui_pow (value.f, 2, value.f, rnd); - break; - case 18: // FTENTOX - t = mpfr_ui_pow (value.f, 10, value.f, rnd); - break; - case 20: // FLOGN - if (mpfr_zero_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (mpfr_sgn (value.f) < 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_log (value.f, value.f, rnd); - break; - case 21: // FLOG10 - if (mpfr_zero_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (mpfr_sgn (value.f) < 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_log10 (value.f, value.f, rnd); - break; - case 22: // FLOG2 - if (mpfr_zero_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (mpfr_sgn (value.f) < 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_log2 (value.f, value.f, rnd); - break; - case 24: // FABS - t = mpfr_abs (value.f, value.f, rnd); - value.nan_sign = 0; - break; - case 25: // FCOSH - t = mpfr_cosh (value.f, value.f, rnd); - break; - case 26: // FNEG - t = mpfr_neg (value.f, value.f, rnd); - value.nan_sign = !value.nan_sign; - break; - case 28: // FACOS - if (mpfr_cmpabs (value.f, FPU_CONSTANT_ONE) > 0) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_acos (value.f, value.f, rnd); - break; - case 29: // FCOS - if (mpfr_inf_p (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_cos (value.f, value.f, rnd); - break; - case 30: // FGETEXP - t = do_getexp (value.f, rnd); - break; - case 31: // FGETMAN - t = do_getman (value.f); - break; - case 32: // FDIV - if (mpfr_zero_p (value.f)) - { - if (mpfr_regular_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (mpfr_zero_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (mpfr_inf_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_div (value.f, fpu.registers[reg].f, value.f, rnd); - break; - case 33: // FMOD - t = do_fmod (value.f, fpu.registers[reg].f, rnd); - break; - case 34: // FADD - if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) - && mpfr_signbit (fpu.registers[reg].f) != mpfr_signbit (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_add (value.f, fpu.registers[reg].f, value.f, rnd); - break; - case 35: // FMUL - if ((mpfr_zero_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) - || (mpfr_inf_p (value.f) && mpfr_zero_p (fpu.registers[reg].f))) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_mul (value.f, fpu.registers[reg].f, value.f, rnd); - break; - case 36: // FSGLDIV - { - MPFR_DECL_INIT (value2, SINGLE_PREC); - - set_format (SINGLE_PREC); - if (mpfr_zero_p (value.f)) - { - if (mpfr_regular_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_DZ; - else if (mpfr_zero_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - } - else if (mpfr_inf_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_div (value2, fpu.registers[reg].f, value.f, rnd); - mpfr_set (value.f, value2, rnd); - } - break; - case 37: // FREM - t = do_remainder (value.f, fpu.registers[reg].f, rnd); - break; - case 38: // FSCALE - t = do_scale (value.f, fpu.registers[reg].f, rnd); - break; - case 39: // FSGLMUL - { - MPFR_DECL_INIT (value2, SINGLE_PREC); - - set_format (SINGLE_PREC); - if ((mpfr_zero_p (value.f) && mpfr_inf_p (fpu.registers[reg].f)) - || (mpfr_inf_p (value.f) && mpfr_zero_p (fpu.registers[reg].f))) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_mul (value2, fpu.registers[reg].f, value.f, rnd); - mpfr_set (value.f, value2, rnd); - } - break; - case 40: // FSUB - if (mpfr_inf_p (fpu.registers[reg].f) && mpfr_inf_p (value.f) - && mpfr_signbit (fpu.registers[reg].f) == mpfr_signbit (value.f)) - cur_exceptions |= FPSR_EXCEPTION_OPERR; - t = mpfr_sub (value.f, fpu.registers[reg].f, value.f, rnd); - break; - } - set_fp_register (reg, value, t, rnd, true); - } - update_exceptions (); - ret = true; - out: - mpfr_clear (value.f); - return ret; -} - -void -fpuop_arithmetic (uae_u32 opcode, uae_u32 extra) -{ - bool valid; - - switch ((extra >> 13) & 7) - { - case 3: - valid = fpuop_fmove_memory (opcode, extra); - break; - case 4: - case 5: - valid = fpuop_fmovem_control (opcode, extra); - break; - case 6: - case 7: - valid = fpuop_fmovem_register (opcode, extra); - break; - case 0: - case 2: - valid = fpuop_general (opcode, extra); - break; - default: - valid = false; - break; - } - - if (!valid) - { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } -} - -static bool -check_fp_cond (uae_u32 pred) -{ - uae_u32 fpcc = get_fpccr (); - - if ((pred & 16) != 0 && (fpcc & FPSR_CCB_NAN) != 0) - { - // IEEE non-aware test - set_exception_status (get_exception_status () | FPSR_EXCEPTION_BSUN); - set_accrued_exception (get_accrued_exception () | FPSR_ACCR_IOP); - } - - switch (pred & 15) - { - case 0: // F / SF - return false; - case 1: // EQ /SEQ - return (fpcc & FPSR_CCB_ZERO) != 0; - case 2: // OGT / GT - return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO | FPSR_CCB_NEGATIVE)) == 0; - case 3: // OGE / GE - return (fpcc & FPSR_CCB_ZERO) != 0 || (fpcc & (FPSR_CCB_NAN | FPSR_CCB_NEGATIVE)) == 0; - case 4: // OLT / LT - return (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_NAN | FPSR_CCB_ZERO)) == FPSR_CCB_NEGATIVE; - case 5: // OLE / LE - return (fpcc & FPSR_CCB_ZERO) != 0 || (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_NAN)) == FPSR_CCB_NEGATIVE; - case 6: // OGL / GL - return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO)) == 0; - case 7: // OR / GLE - return (fpcc & FPSR_CCB_NAN) == 0; - case 8: // UN / NGLE - return (fpcc & FPSR_CCB_NAN) != 0; - case 9: // UEQ / NGL - return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO)) != 0; - case 10: // UGT / NLE - return (fpcc & FPSR_CCB_NAN) != 0 || (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_ZERO)) == 0; - case 11: // UGE / NLT - return (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_NAN | FPSR_CCB_ZERO)) != FPSR_CCB_NEGATIVE; - case 12: // ULT / NGE - return (fpcc & FPSR_CCB_NAN) != 0 || (fpcc & (FPSR_CCB_NEGATIVE | FPSR_CCB_ZERO)) == FPSR_CCB_NEGATIVE; - case 13: // ULE / NGT - return (fpcc & (FPSR_CCB_NAN | FPSR_CCB_ZERO | FPSR_CCB_NEGATIVE)) != 0; - case 14: // NE / SNE - return (fpcc & FPSR_CCB_ZERO) == 0; - case 15: // T / ST - return true; - default: - return false; - } -} - -void -fpuop_bcc (uae_u32 opcode, uaecptr pc, uae_u32 disp) -{ - if (check_fp_cond (opcode)) - { - if (!(opcode & (1 << 6))) - disp = (uae_s16) disp; - m68k_setpc (pc + disp); - } -} - -void -fpuop_scc (uae_u32 opcode, uae_u32 extra) -{ - uae_u32 addr; - int value = check_fp_cond (extra) ? 0xff : 0; - if ((opcode & 070) == 0) - { - int reg = opcode & 7; - m68k_dreg (regs, reg) = (m68k_dreg (regs, reg) & ~0xff) | value; - } - else if (!get_fp_addr (opcode, &addr, true)) - { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - } - else - { - switch (opcode & 070) - { - case 030: - m68k_areg (regs, opcode & 7) += (opcode & 7) == 7 ? 2 : 1; - break; - case 040: - addr -= (opcode & 7) == 7 ? 2 : 1; - m68k_areg (regs, opcode & 7) = addr; - } - put_byte (addr, value); - } -} - -void -fpuop_dbcc (uae_u32 opcode, uae_u32 extra) -{ - uaecptr pc = m68k_getpc (); - uae_s16 disp = next_iword (); - - if (!check_fp_cond (extra)) - { - int reg = opcode & 7; - uae_u16 cnt = (m68k_dreg (regs, reg) & 0xffff) - 1; - m68k_dreg (regs, reg) = (m68k_dreg (regs, reg) & ~0xffff) | cnt; - if (cnt != 0xffff) - m68k_setpc (pc + disp); - } -} - -void -fpuop_trapcc (uae_u32, uaecptr oldpc, uae_u32 extra) -{ - if (check_fp_cond (extra)) - Exception (7, oldpc - 2); -} - -void -fpuop_save (uae_u32 opcode) -{ - uae_u32 addr; - - if ((opcode & 070) == 030 - || !get_fp_addr (opcode, &addr, true)) - { - m68k_setpc (m68k_getpc () - 2); - op_illg (opcode); - return; - } - - if (fpu.is_integral) - { - // 4 byte 68040 IDLE frame - // FIXME: generate proper FPU stack frames that does not result - // in undefined behaviour from FPSP040 - if ((opcode & 070) == 040) - { - addr -= 4; - m68k_areg (regs, opcode & 7) = addr; - } - put_long (addr, 0x41000000); - } - else - { - // 28 byte 68881 IDLE frame - if ((opcode & 070) == 040) - { - addr -= 28; - m68k_areg (regs, opcode & 7) = addr; - } - put_long (addr, 0x1f180000); - for (int i = 0; i < 6; i++) - { - addr += 4; - put_long (addr, 0); - } - } -} - -void -fpuop_restore (uae_u32 opcode) -{ - uae_u32 addr; - uae_u32 format; - - if ((opcode & 070) == 040 - || !get_fp_addr (opcode, &addr, false)) - { - m68k_setpc (m68k_getpc () - 2); - op_illg (opcode); - return; - } - - format = get_long (addr); - addr += 4; - if ((format & 0xff000000) == 0) - // NULL frame - fpu_reset (); - else - addr += (format & 0xff0000) >> 16; - if ((opcode & 070) == 030) - m68k_areg (regs, opcode & 7) = addr; -} - -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(); -} diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp index 23efd8ef..ffc784a5 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp +++ b/BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp @@ -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 +#include #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 -# include -using namespace __gnu_cxx; -#undef _GLIBCPP_USE_C99 -#else -# include -# include -#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) diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_uae.h b/BasiliskII/src/uae_cpu/fpu/fpu_uae.h index d8930e32..7fc4ebbd 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_uae.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_uae.h @@ -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 diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp b/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp index a4c6af2d..70e59086 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp @@ -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 -# include +#include +#include +#include +#include #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�s MSB, the explicit +For extended-precision infinities, the mantissa’s MSB, the explicit integer bit, can be either one or zero. */ -PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f) +PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f) { uae_u8 * p = (uae_u8 *) &f; if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) { @@ -441,7 +439,7 @@ PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f) return(0); } -PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f) +PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f) { uae_u8 * p = (uae_u8 *) &f; if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) { @@ -452,7 +450,7 @@ PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f) return(0); } -PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f) +PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f) { uae_u8 * p = (uae_u8 *) &f; return *((uae_u32 *)p) == 0 && @@ -460,34 +458,34 @@ PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f) ( *((uae_u16 *)&p[8]) & 0x7FFF ) == 0; } -PRIVATE inline void FFPU MAKE_INF_POSITIVE (fpu_register & f) +PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f) { uae_u8 * p = (uae_u8 *) &f; memset( p, 0, sizeof(fpu_register)-2 ); *((uae_u16 *)&p[8]) = 0x7FFF; } -PRIVATE inline void FFPU MAKE_INF_NEGATIVE (fpu_register & f) +PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f) { uae_u8 * p = (uae_u8 *) &f; memset( p, 0, sizeof(fpu_register)-2 ); *((uae_u16 *)&p[8]) = 0xFFFF; } -PRIVATE inline void FFPU MAKE_ZERO_POSITIVE (fpu_register & f) +PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f) { uae_u32 * const p = (uae_u32 *) &f; memset( p, 0, sizeof(fpu_register) ); } -PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f) +PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f) { uae_u32 * const p = (uae_u32 *) &f; memset( p, 0, sizeof(fpu_register) ); *((uae_u32 *)&p[4]) = 0x80000000; } -PRIVATE inline uae_u32 FFPU IS_NEGATIVE (fpu_register const & f) +PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f) { uae_u8 * p = (uae_u8 *) &f; return( (p[9] & 0x80) != 0 ); @@ -902,34 +900,6 @@ PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fmove"); } -PRIVATE void FFPU do_fsmove ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - FPU_CONSISTENCY_CHECK_STOP("do_fsmove"); -} - -PRIVATE void FFPU do_fdmove ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - FPU_CONSISTENCY_CHECK_STOP("do_fdmove"); -} - /* PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src ) { @@ -1053,50 +1023,6 @@ PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fsqrt"); } -PRIVATE void FFPU do_fssqrt ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fsqrt \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fssqrt"); -} - -PRIVATE void FFPU do_fdsqrt ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fsqrt \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fdsqrt"); -} - PRIVATE void FFPU do_ftst ( fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -1385,48 +1311,6 @@ PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fabs"); } -PRIVATE void FFPU do_fsabs ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fabs \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - // x86 fabs should not rise any exceptions (except stack underflow) - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsabs"); -} - -PRIVATE void FFPU do_fdabs ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fabs \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - // x86 fabs should not rise any exceptions (except stack underflow) - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_fdabs"); -} - PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -1457,48 +1341,6 @@ PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fneg"); } -PRIVATE void FFPU do_fsneg ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fchs \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - // x86 fchs should not rise any exceptions (except stack underflow) - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsneg"); -} - -PRIVATE void FFPU do_fdneg ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fchs \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "=m" (dest) - : "m" (src) - ); - // x86 fchs should not rise any exceptions (except stack underflow) - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~SW_EXCEPTION_MASK; - } - FPU_CONSISTENCY_CHECK_STOP("do_fdneg"); -} - PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -1624,50 +1466,6 @@ PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fdiv"); } -PRIVATE void FFPU do_fsdiv ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fdiv %%st(1), %%st(0)\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsdiv"); -} - -PRIVATE void FFPU do_fddiv ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fdiv %%st(1), %%st(0)\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fddiv"); -} - // The sign of the quotient is the exclusive-OR of the sign bits // of the source and destination operands. // Quotient Byte is loaded with the sign and least significant @@ -2053,48 +1851,6 @@ PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fadd"); } -PRIVATE void FFPU do_fsadd ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fadd \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsadd"); -} - -PRIVATE void FFPU do_fdadd ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fadd \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fdadd"); -} - PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -2126,48 +1882,6 @@ PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fmul"); } -PRIVATE void FFPU do_fsmul ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fmul \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fsmul"); -} - -PRIVATE void FFPU do_fdmul ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fmul \n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fdmul"); -} - PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -2326,52 +2040,6 @@ PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src ) FPU_CONSISTENCY_CHECK_STOP("do_fsub"); } -PRIVATE void FFPU do_fssub ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fsub %%st(1), %%st(0)\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fssub"); -} - -PRIVATE void FFPU do_fdsub ( fpu_register & dest, fpu_register const & src ) -{ - FPU_CONSISTENCY_CHECK_START(); - __asm__ __volatile__( - "fldt %2\n" - "fldt %1\n" - "fsub %%st(1), %%st(0)\n" - "fxam \n" - "fnstsw %0\n" - "fstpt %1\n" - "fstp %%st(0)\n" - : "=m" (x86_status_word), "+m" (dest) - : "m" (src) - ); - if(x86_status_word & SW_EXCEPTION_MASK) { -// _asm FNCLEX - __asm__ __volatile__("fnclex"); - x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE); - x86_status_word_accrued |= x86_status_word; - } - FPU_CONSISTENCY_CHECK_STOP("do_fdsub"); -} - PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src ) { FPU_CONSISTENCY_CHECK_START(); @@ -2616,9 +2284,11 @@ PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src break; case 3: ad = m68k_areg (regs, reg); + m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; break; case 4: - ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]); + m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; + ad = m68k_areg (regs, reg); break; case 5: ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword(); @@ -2717,15 +2387,6 @@ PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src return 0; } - switch (mode) { - case 3: - m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; - break; - case 4: - m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; - break; - } - // D(bug("get_fp_value result = %.04f\r\n",(float)src)); return 1; @@ -2951,7 +2612,7 @@ PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) #define I ((x86_status_word & (SW_Z_I_NAN_MASK)) == (SW_I)) #define NotANumber ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN) - switch (condition & 0x1f) { + switch (condition) { // Common Tests, no BSUN case 0x01: CONDRET("Equal",Z); @@ -3096,11 +2757,11 @@ PUBLIC void REGPARAM2 FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra) } } -PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) +PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) { int cc; - D(bug("ftrapcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ())); + D(bug("ftrapcc_opp %X at %08lx\r\n", (uae_u32)opcode, m68k_getpc ())); #if I3_ON_FTRAPCC #error "FIXME: _asm int 3" @@ -3108,7 +2769,7 @@ PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 e #endif // This must be broken. - cc = fpp_cond(opcode, extra & 0x3f); + cc = fpp_cond(opcode, opcode & 0x3f); if (cc < 0) { m68k_setpc (oldpc); @@ -4985,249 +4646,6 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32 } -/* -------------------------- 040 ALU -------------------------- */ -PRIVATE void REGPARAM2 FFPU fpuop_do_fsmove( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSMOVE %s\r\n",etos(src))); - do_fsmove( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdmove( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDMOVE %s\r\n",etos(src))); - do_fdmove( FPU registers[reg], src ); - build_ex_status(); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fssqrt( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSSQRT %s\r\n",etos(src))); - do_fssqrt( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdsqrt( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDSQRT %s\r\n",etos(src))); - do_fdsqrt( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsabs( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSABS %s\r\n",etos(src))); - do_fsabs( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdabs( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDABS %s\r\n",etos(src))); - do_fdabs( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsneg( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSNEG %s\r\n",etos(src))); - do_fsneg( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdneg( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDNEG %s\r\n",etos(src))); - do_fdneg( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsdiv( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSDIV %s\r\n",etos(src))); - do_fsdiv( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fddiv( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDDIV %s\r\n",etos(src))); - do_fddiv( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsadd( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSADD %s\r\n",etos(src))); - do_fsadd( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdadd( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDADD %s\r\n",etos(src))); - do_fdadd( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fssub( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSSUB %s\r\n",etos(src))); - do_fssub( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdsub( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FDSUB %s\r\n",etos(src))); - do_fdsub( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fsmul( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSMUL %s\r\n",etos(src))); - do_fsmul( FPU registers[reg], src ); - dump_registers( "END "); -} - -PRIVATE void REGPARAM2 FFPU fpuop_do_fdmul( uae_u32 opcode, uae_u32 extra ) -{ - int reg = (extra >> 7) & 7; - fpu_register src; - if (get_fp_value (opcode, extra, src) == 0) { - m68k_setpc (m68k_getpc () - 4); - op_illg (opcode); - dump_registers( "END "); - return; - } - D(bug("FSMUL %s\r\n",etos(src))); - do_fsmul( FPU registers[reg], src ); - dump_registers( "END "); -} - /* ---------------------------- ALU ---------------------------- */ PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra ) @@ -6326,61 +5744,6 @@ PRIVATE void FFPU build_fpp_opp_lookup_table () } break; } - - if (FPU is_integral) { - switch (extra & 0x7f) { - case 0x40: - fpufunctbl[mask] = & FFPU fpuop_do_fsmove; - break; - case 0x44: - fpufunctbl[mask] = & FFPU fpuop_do_fdmove; - break; - case 0x41: - fpufunctbl[mask] = & FFPU fpuop_do_fssqrt; - break; - case 0x45: - fpufunctbl[mask] = & FFPU fpuop_do_fdsqrt; - break; - case 0x58: - fpufunctbl[mask] = & FFPU fpuop_do_fsabs; - break; - case 0x5c: - fpufunctbl[mask] = & FFPU fpuop_do_fdabs; - break; - case 0x5a: - fpufunctbl[mask] = & FFPU fpuop_do_fsneg; - break; - case 0x5e: - fpufunctbl[mask] = & FFPU fpuop_do_fdneg; - break; - case 0x60: - fpufunctbl[mask] = & FFPU fpuop_do_fsdiv; - break; - case 0x64: - fpufunctbl[mask] = & FFPU fpuop_do_fddiv; - break; - case 0x62: - fpufunctbl[mask] = & FFPU fpuop_do_fsadd; - break; - case 0x66: - fpufunctbl[mask] = & FFPU fpuop_do_fdadd; - break; - case 0x68: - fpufunctbl[mask] = & FFPU fpuop_do_fssub; - break; - case 0x6c: - fpufunctbl[mask] = & FFPU fpuop_do_fdsub; - break; - case 0x63: - fpufunctbl[mask] = & FFPU fpuop_do_fsmul; - break; - case 0x67: - fpufunctbl[mask] = & FFPU fpuop_do_fdmul; - break; - default: - break; - } - } switch (extra & 0x7f) { case 0x00: @@ -6670,26 +6033,6 @@ PRIVATE void FFPU do_fld1 ( fpu_register & dest ) } -void fpu_set_fpsr(uae_u32 new_fpsr) -{ - set_fpsr(new_fpsr); -} - -uae_u32 fpu_get_fpsr(void) -{ - return get_fpsr(); -} - -void fpu_set_fpcr(uae_u32 new_fpcr) -{ - set_fpcr(new_fpcr); -} - -uae_u32 fpu_get_fpcr(void) -{ - return get_fpcr(); -} - /* ---------------------------- MAIN INIT ---------------------------- */ #ifdef HAVE_SIGACTION @@ -6741,10 +6084,6 @@ PUBLIC void FFPU fpu_init( bool integral_68040 ) build_fpp_opp_lookup_table(); -/* _asm { - FNINIT - FLDCW x86_control_word - } */ __asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word)); do_fldpi( const_pi ); @@ -6772,10 +6111,6 @@ PUBLIC void FFPU fpu_init( bool integral_68040 ) set_constant( const_1e4096, "1.0e4096", 1.0e256, 10000 ); // Just in case. -/* _asm { - FNINIT - FLDCW x86_control_word - } */ __asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word)); } diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86.h b/BasiliskII/src/uae_cpu/fpu/fpu_x86.h index 52a2f310..96f1d959 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86.h @@ -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 ); diff --git a/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h b/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h index 6e5a3766..ecdecfbc 100644 --- a/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h +++ b/BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h @@ -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) diff --git a/BasiliskII/src/uae_cpu/fpu/impl.h b/BasiliskII/src/uae_cpu/fpu/impl.h index af7946a3..c79d1f3f 100644 --- a/BasiliskII/src/uae_cpu/fpu/impl.h +++ b/BasiliskII/src/uae_cpu/fpu/impl.h @@ -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; } /* -------------------------------------------------------------------------- */ diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.cpp b/BasiliskII/src/uae_cpu/fpu/mathlib.cpp index 46d43c95..eabb376e 100644 --- a/BasiliskII/src/uae_cpu/fpu/mathlib.cpp +++ b/BasiliskII/src/uae_cpu/fpu/mathlib.cpp @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/fpu/mathlib.h b/BasiliskII/src/uae_cpu/fpu/mathlib.h index c9a1951c..2363af56 100644 --- a/BasiliskII/src/uae_cpu/fpu/mathlib.h +++ b/BasiliskII/src/uae_cpu/fpu/mathlib.h @@ -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 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 diff --git a/BasiliskII/src/uae_cpu/fpu/rounding.cpp b/BasiliskII/src/uae_cpu/fpu/rounding.cpp index 9942d4e8..1f8b3618 100644 --- a/BasiliskII/src/uae_cpu/fpu/rounding.cpp +++ b/BasiliskII/src/uae_cpu/fpu/rounding.cpp @@ -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 diff --git a/BasiliskII/src/uae_cpu/fpu/rounding.h b/BasiliskII/src/uae_cpu/fpu/rounding.h index 60c4baff..67db5519 100644 --- a/BasiliskII/src/uae_cpu/fpu/rounding.h +++ b/BasiliskII/src/uae_cpu/fpu/rounding.h @@ -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 diff --git a/BasiliskII/src/uae_cpu/fpu/types.h b/BasiliskII/src/uae_cpu/fpu/types.h index afd3ab28..778567a9 100644 --- a/BasiliskII/src/uae_cpu/fpu/types.h +++ b/BasiliskII/src/uae_cpu/fpu/types.h @@ -1,33 +1,28 @@ /* - * fpu/types.h - basic types for fpu registers + * types.h - basic types for fpu registers * - * Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS) - * - * Inspired by Christian Bauer's Basilisk II + * Basilisk II (C) 1997-2008 Christian Bauer * - * This file is part of the ARAnyM project which builds a new and powerful - * TOS/FreeMiNT compatible virtual machine running on almost any hardware. + * MC68881/68040 fpu emulation + * + * Original UAE FPU, copyright 1996 Herman ten Brugge + * Rewrite for x86, copyright 1999-2000 Lauri Pesonen + * New framework, copyright 2000 Gwenole Beauchesne + * Adapted for JIT compilation (c) Bernd Meyer, 2000 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * MC68881/68040 fpu emulation + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Original UAE FPU, copyright 1996 Herman ten Brugge - * Rewrite for x86, copyright 1999-2001 Lauri Pesonen - * New framework, copyright 2000-2001 Gwenole Beauchesne - * Adapted for JIT compilation (c) Bernd Meyer, 2000-2001 - * - * ARAnyM is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * ARAnyM is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with ARAnyM; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef FPU_TYPES_H @@ -111,9 +106,9 @@ typedef uae_f32 fpu_single; #elif defined(FPU_IEEE) -#if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT -#error "No IEEE float format, you lose." -#endif +// #if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT +// #error "No IEEE float format, you lose." +// #endif /* 4-byte floats */ #if SIZEOF_FLOAT == 4 @@ -138,7 +133,7 @@ typedef long double uae_f64; typedef long double uae_f96; typedef uae_f96 fpu_register; #define USE_LONG_DOUBLE 1 -#elif SIZEOF_LONG_DOUBLE == 16 && (defined(CPU_i386) || defined(CPU_x86_64) || defined(CPU_ia64)) +#elif SIZEOF_LONG_DOUBLE == 16 && (defined(__i386__) || defined(__x86_64__)) /* Long doubles on x86-64 are really held in old x87 FPU stack. */ typedef long double uae_f128; typedef uae_f128 fpu_register; @@ -159,23 +154,6 @@ typedef fpu_register fpu_extended; typedef uae_f64 fpu_double; typedef uae_f32 fpu_single; -#elif defined(FPU_MPFR) - -#include - -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 */ diff --git a/BasiliskII/src/uae_cpu/gencpu.c b/BasiliskII/src/uae_cpu/gencpu.c index 8db74001..1653adab 100644 --- a/BasiliskII/src/uae_cpu/gencpu.c +++ b/BasiliskII/src/uae_cpu/gencpu.c @@ -1,27 +1,3 @@ -/* - * gencpu.c - m68k emulation generator - * - * Copyright (c) 2009 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 * @@ -38,26 +14,42 @@ * take care of this. * * 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 + * */ -#define CC_FOR_BUILD 1 - -#include "sysdeps.h" -#include "readcpu.h" - #include #include #include #include -#include -#undef abort + +#include "sysdeps.h" +#include "readcpu.h" + +#if defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY) +#define SPARC_ASSEMBLY 0 +#endif #define BOOL_TYPE "int" -#define VERIFY_MMU_GENAMODE 0 + +/* Define the minimal 680x0 where NV flags are not affected by xBCD instructions. */ +#define xBCD_KEEPS_NV_FLAGS 4 static FILE *headerfile; static FILE *stblfile; -static FILE *functblfile; static int using_prefetch; static int using_exception_3; @@ -73,23 +65,6 @@ static int *opcode_next_clev; static int *opcode_last_postfix; static unsigned long *counts; -#define GENA_GETV_NO_FETCH 0 -#define GENA_GETV_FETCH 1 -#define GENA_GETV_FETCH_ALIGN 2 -#define GENA_MOVEM_DO_INC 0 -#define GENA_MOVEM_NO_INC 1 -#define GENA_MOVEM_MOVE16 2 - -#define XLATE_LOG 0 -#define XLATE_PHYS 1 -#define XLATE_SFC 2 -#define XLATE_DFC 3 -static char * mem_prefix[4] = { "", "phys_", "sfc_", "dfc_" }; - -/* Define the minimal 680x0 where NV flags are not affected by xBCD instructions. */ -#define xBCD_KEEPS_N_FLAG 4 -#define xBCD_KEEPS_V_FLAG 3 - static void read_counts (void) { FILE *file; @@ -100,8 +75,7 @@ static void read_counts (void) file = fopen ("frequent.68k", "r"); if (file) { - int c = fscanf (file, "Total: %lu\n", &total); - assert(c == 1); + fscanf (file, "Total: %lu\n", &total); while (fscanf (file, "%lx: %lu %s\n", &opcode, &count, name) == 3) { opcode_next_clev[nr] = 4; opcode_last_postfix[nr] = -1; @@ -132,6 +106,7 @@ static int need_endlabel; static int n_braces = 0; static int m68k_pc_offset = 0; +static int insn_n_cycles; static void start_brace (void) { @@ -184,9 +159,10 @@ static const char *gen_nextilong (void) { static char buffer[80]; int r = m68k_pc_offset; - m68k_pc_offset += 4; + insn_n_cycles += 4; + if (using_prefetch) sprintf (buffer, "get_ilong_prefetch(%d)", r); else @@ -198,9 +174,10 @@ static const char *gen_nextiword (void) { static char buffer[80]; int r = m68k_pc_offset; - m68k_pc_offset += 2; + insn_n_cycles += 2; + if (using_prefetch) sprintf (buffer, "get_iword_prefetch(%d)", r); else @@ -214,6 +191,8 @@ static const char *gen_nextibyte (void) int r = m68k_pc_offset; m68k_pc_offset += 2; + insn_n_cycles += 2; + if (using_prefetch) sprintf (buffer, "get_ibyte_prefetch(%d)", r); else @@ -235,22 +214,9 @@ static void fill_prefetch_2 (void) static void swap_opcode (void) { - printf("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); - printf ("\topcode = do_byteswap_16(opcode);\n"); - printf("#endif\n"); -} - -static void real_opcode (int *have) -{ - if (!*have) - { - printf("#if defined(HAVE_GET_WORD_UNSWAPPED) && !defined(FULLMMU)\n"); - printf ("\tuae_u32 real_opcode = do_byteswap_16(opcode);\n"); - printf("#else\n"); - printf ("\tuae_u32 real_opcode = opcode;\n"); - printf("#endif\n"); - *have = 1; - } + printf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); + printf ("\topcode = ((opcode << 8) & 0xFF00) | ((opcode >> 8) & 0xFF);\n"); + printf ("#endif\n"); } static void sync_m68k_pc (void) @@ -272,49 +238,33 @@ static void sync_m68k_pc (void) m68k_pc_offset = 0; } -static void gen_set_fault_pc (void) -{ - sync_m68k_pc(); - printf ("regs.fault_pc = m68k_getpc ();\n"); - m68k_pc_offset = 0; -} - /* getv == 1: fetch data; getv != 0: check for odd address. If movem != 0, * the calling routine handles Apdi and Aipi modes. * gb-- movem == 2 means the same thing but for a MOVE16 instruction */ - -/* fixup indicates if we want to fix up adress registers in pre decrement - * or post increment mode now (0) or later (1). A value of 2 will then be - * used to do the actual fix up. This allows to do all memory readings - * before any register is modified, and so to rerun operation without - * side effect in case a bus fault is generated by any memory access. - * XJ - 2006/11/13 */ -static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int xlateflag, int fixup) +static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem) { - if (fixup != 2) - { start_brace (); switch (mode) { case Dreg: if (movem) abort (); - if (getv == GENA_GETV_FETCH) + if (getv == 1) switch (size) { case sz_byte: - printf("\n#if defined(AMIGA) && !defined(WARPUP)\n"); +#if defined(AMIGA) && !defined(WARPUP) /* sam: I don't know why gcc.2.7.2.1 produces a code worse */ /* if it is not done like that: */ printf ("\tuae_s8 %s = ((uae_u8*)&m68k_dreg(regs, %s))[3];\n", name, reg); - printf("#else\n"); +#else printf ("\tuae_s8 %s = m68k_dreg(regs, %s);\n", name, reg); - printf("#endif\n"); +#endif break; case sz_word: - printf("\n#if defined(AMIGA) && !defined(WARPUP)\n"); +#if defined(AMIGA) && !defined(WARPUP) printf ("\tuae_s16 %s = ((uae_s16*)&m68k_dreg(regs, %s))[1];\n", name, reg); - printf("#else\n"); +#else printf ("\tuae_s16 %s = m68k_dreg(regs, %s);\n", name, reg); - printf("#endif\n"); +#endif break; case sz_long: printf ("\tuae_s32 %s = m68k_dreg(regs, %s);\n", name, reg); @@ -326,7 +276,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g case Areg: if (movem) abort (); - if (getv == GENA_GETV_FETCH) + if (getv == 1) switch (size) { case sz_word: printf ("\tuae_s16 %s = m68k_areg(regs, %s);\n", name, reg); @@ -353,16 +303,10 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g printf ("\tuaecptr %sa = m68k_areg(regs, %s) - areg_byteinc[%s];\n", name, reg, reg); break; case sz_word: - if (movem) - printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg); - else - printf ("\tuaecptr %sa = m68k_areg(regs, %s) - 2;\n", name, reg); + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 2); break; case sz_long: - if (movem) - printf ("\tuaecptr %sa = m68k_areg(regs, %s);\n", name, reg); - else - printf ("\tuaecptr %sa = m68k_areg(regs, %s) - 4;\n", name, reg); + printf ("\tuaecptr %sa = m68k_areg(regs, %s) - %d;\n", name, reg, movem ? 0 : 4); break; default: abort (); @@ -407,7 +351,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g printf ("\tuaecptr %sa = %s;\n", name, gen_nextilong ()); break; case imm: - if (getv != GENA_GETV_FETCH) + if (getv != 1) abort (); switch (size) { case sz_byte: @@ -424,22 +368,22 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g } return; case imm0: - if (getv != GENA_GETV_FETCH) + if (getv != 1) abort (); printf ("\tuae_s8 %s = %s;\n", name, gen_nextibyte ()); return; case imm1: - if (getv != GENA_GETV_FETCH) + if (getv != 1) abort (); printf ("\tuae_s16 %s = %s;\n", name, gen_nextiword ()); return; case imm2: - if (getv != GENA_GETV_FETCH) + if (getv != 1) abort (); printf ("\tuae_s32 %s = %s;\n", name, gen_nextilong ()); return; case immi: - if (getv != GENA_GETV_FETCH) + if (getv != 1) abort (); printf ("\tuae_u32 %s = %s;\n", name, reg); return; @@ -450,7 +394,7 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g /* We get here for all non-reg non-immediate addressing modes to * actually fetch the value. */ - if (using_exception_3 && getv != GENA_GETV_NO_FETCH && size != sz_byte) { + if (using_exception_3 && getv != 0 && size != sz_byte) { printf ("\tif ((%sa & 1) != 0) {\n", name); printf ("\t\tlast_fault_for_exception_3 = %sa;\n", name); printf ("\t\tlast_op_for_exception_3 = opcode;\n"); @@ -462,29 +406,20 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g start_brace (); } - if (getv == GENA_GETV_FETCH) { + if (getv == 1) { switch (size) { - case sz_byte: break; - case sz_word: break; - case sz_long: break; + case sz_byte: insn_n_cycles += 2; break; + case sz_word: insn_n_cycles += 2; break; + case sz_long: insn_n_cycles += 4; break; default: abort (); } start_brace (); - printf("\n#ifdef FULLMMU\n"); switch (size) { - case sz_byte: printf ("\tuae_s8 %s = %sget_byte(%sa);\n", name, mem_prefix[xlateflag], name); break; - case sz_word: printf ("\tuae_s16 %s = %sget_word(%sa);\n", name, mem_prefix[xlateflag], name); break; - case sz_long: printf ("\tuae_s32 %s = %sget_long(%sa);\n", name, mem_prefix[xlateflag], name); break; + case sz_byte: printf ("\tuae_s8 %s = get_byte(%sa);\n", name, name); break; + case sz_word: printf ("\tuae_s16 %s = get_word(%sa);\n", name, name); break; + case sz_long: printf ("\tuae_s32 %s = get_long(%sa);\n", name, name); break; default: abort (); } - printf("#else\n"); - switch (size) { - case sz_byte: printf ("\tuae_s8 %s = phys_get_byte(%sa);\n", name, name); break; - case sz_word: printf ("\tuae_s16 %s = phys_get_word(%sa);\n", name, name); break; - case sz_long: printf ("\tuae_s32 %s = phys_get_long(%sa);\n", name, name); break; - default: abort (); - } - printf("#endif\n"); } /* We now might have to fix up the register for pre-dec or post-inc @@ -492,12 +427,6 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g if (!movem) switch (mode) { case Aipi: - if (fixup == 1) - { - printf ("\tfixup.flag = 1;\n"); - printf ("\tfixup.reg = %s;\n", reg); - printf ("\tfixup.value = m68k_areg(regs, %s);\n", reg); - } switch (size) { case sz_byte: printf ("\tm68k_areg(regs, %s) += areg_byteinc[%s];\n", reg, reg); @@ -513,39 +442,14 @@ static void genamode2 (amodes mode, char *reg, wordsizes size, char *name, int g } break; case Apdi: - if (fixup == 1) - { - printf ("\tfixup.flag = 1;\n"); - printf ("\tfixup.reg = %s;\n", reg); - printf ("\tfixup.value = m68k_areg(regs, %s);\n", reg); - } printf ("\tm68k_areg (regs, %s) = %sa;\n", reg, name); break; default: break; } - - } - else /* (fixup != 2) */ - { - if (!movem) - switch (mode) { - case Aipi: - case Apdi: - printf ("\tfixup.flag = 0;\n"); - break; - default: - break; - } - } } -static void genamode (amodes mode, char *reg, wordsizes size, char *name, int getv, int movem, int xlateflag) -{ - genamode2 (mode, reg, size, name, getv, movem, xlateflag, 0); -} - -static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to, int xlateflag) +static void genastore (char *from, amodes mode, char *reg, wordsizes size, char *to) { switch (mode) { case Dreg: @@ -585,32 +489,28 @@ static void genastore (char *from, amodes mode, char *reg, wordsizes size, char case absl: case PC16: case PC8r: - gen_set_fault_pc (); - printf("#ifdef FULLMMU\n"); + if (using_prefetch) + sync_m68k_pc (); switch (size) { case sz_byte: - printf ("\t%sput_byte(%sa,%s);\n", mem_prefix[xlateflag], to, from); - printf("#else\n"); + insn_n_cycles += 2; printf ("\tput_byte(%sa,%s);\n", to, from); break; case sz_word: + insn_n_cycles += 2; if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); - printf ("\t%sput_word(%sa,%s);\n", mem_prefix[xlateflag], to, from); - printf("#else\n"); printf ("\tput_word(%sa,%s);\n", to, from); break; case sz_long: + insn_n_cycles += 4; if (cpu_level < 2 && (mode == PC16 || mode == PC8r)) abort (); - printf ("\t%sput_long(%sa,%s);\n", mem_prefix[xlateflag], to, from); - printf("#else\n"); printf ("\tput_long(%sa,%s);\n", to, from); break; default: abort (); } - printf("#endif\n"); break; case imm: case imm0: @@ -626,33 +526,23 @@ static void genastore (char *from, amodes mode, char *reg, wordsizes size, char static void genmovemel (uae_u16 opcode) { - char getcode1[100]; - char getcode2[100]; + char getcode[100]; int size = table68k[opcode].size == sz_long ? 4 : 2; - + if (table68k[opcode].size == sz_long) { - strcpy (getcode1, ""); - strcpy (getcode2, "get_long(srca)"); + strcpy (getcode, "get_long(srca)"); } else { - strcpy (getcode1, "(uae_s32)(uae_s16)"); - strcpy (getcode2, "get_word(srca)"); + strcpy (getcode, "(uae_s32)(uae_s16)get_word(srca)"); } printf ("\tuae_u16 mask = %s;\n", gen_nextiword ()); printf ("\tunsigned int dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC, XLATE_LOG); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); start_brace (); - printf("\n#ifdef FULLMMU\n"); - printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s%s; srca += %d; dmask = movem_next[dmask]; }\n", - getcode1, getcode2, size); - printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s%s; srca += %d; amask = movem_next[amask]; }\n", - getcode1, getcode2, size); - printf("#else\n"); - printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %sphys_%s; srca += %d; dmask = movem_next[dmask]; }\n", - getcode1, getcode2, size); - printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %sphys_%s; srca += %d; amask = movem_next[amask]; }\n", - getcode1, getcode2, size); - printf("#endif\n"); + printf ("\twhile (dmask) { m68k_dreg(regs, movem_index1[dmask]) = %s; srca += %d; dmask = movem_next[dmask]; }\n", + getcode, size); + printf ("\twhile (amask) { m68k_areg(regs, movem_index1[amask]) = %s; srca += %d; amask = movem_next[amask]; }\n", + getcode, size); if (table68k[opcode].dmode == Aipi) printf ("\tm68k_areg(regs, dstreg) = srca;\n"); @@ -662,7 +552,6 @@ static void genmovemle (uae_u16 opcode) { char putcode[100]; int size = table68k[opcode].size == sz_long ? 4 : 2; - if (table68k[opcode].size == sz_long) { strcpy (putcode, "put_long(srca,"); } else { @@ -670,38 +559,24 @@ static void genmovemle (uae_u16 opcode) } printf ("\tuae_u16 mask = %s;\n", gen_nextiword ()); - genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", - GENA_GETV_FETCH_ALIGN, GENA_MOVEM_NO_INC, XLATE_LOG); - sync_m68k_pc (); + genamode (table68k[opcode].dmode, "dstreg", table68k[opcode].size, "src", 2, 1); + if (using_prefetch) + sync_m68k_pc (); start_brace (); if (table68k[opcode].dmode == Apdi) { printf ("\tuae_u16 amask = mask & 0xff, dmask = (mask >> 8) & 0xff;\n"); - printf("#ifdef FULLMMU\n"); printf ("\twhile (amask) { srca -= %d; %s m68k_areg(regs, movem_index2[amask])); amask = movem_next[amask]; }\n", size, putcode); printf ("\twhile (dmask) { srca -= %d; %s m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", size, putcode); - printf("#else\n"); - printf ("\twhile (amask) { srca -= %d; phys_%s m68k_areg(regs, movem_index2[amask])); amask = movem_next[amask]; }\n", - size, putcode); - printf ("\twhile (dmask) { srca -= %d; phys_%s m68k_dreg(regs, movem_index2[dmask])); dmask = movem_next[dmask]; }\n", - size, putcode); - printf("#endif\n"); printf ("\tm68k_areg(regs, dstreg) = srca;\n"); } else { printf ("\tuae_u16 dmask = mask & 0xff, amask = (mask >> 8) & 0xff;\n"); - printf("#ifdef FULLMMU\n"); printf ("\twhile (dmask) { %s m68k_dreg(regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", putcode, size); printf ("\twhile (amask) { %s m68k_areg(regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", putcode, size); - printf("#else\n"); - printf ("\twhile (dmask) { phys_%s m68k_dreg(regs, movem_index1[dmask])); srca += %d; dmask = movem_next[dmask]; }\n", - putcode, size); - printf ("\twhile (amask) { phys_%s m68k_areg(regs, movem_index1[amask])); srca += %d; amask = movem_next[amask]; }\n", - putcode, size); - printf("#endif\n"); } } @@ -774,10 +649,12 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * break; case flag_add: + start_brace (); printf ("uae_u32 %s = %s + %s;\n", value, dstr, sstr); break; case flag_sub: case flag_cmp: + start_brace (); printf ("uae_u32 %s = %s - %s;\n", value, dstr, sstr); break; } @@ -796,6 +673,7 @@ static void genflags_normal (flagtypes type, wordsizes size, char *value, char * case flag_cmp: case flag_av: case flag_sv: + start_brace (); printf ("\t" BOOL_TYPE " flgs = %s < 0;\n", sstr); printf ("\t" BOOL_TYPE " flgo = %s < 0;\n", dstr); printf ("\t" BOOL_TYPE " flgn = %s < 0;\n", vstr); @@ -863,13 +741,11 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch /* Temporarily deleted 68k/ARM flag optimizations. I'd prefer to have them in the appropriate m68k.h files and use just one copy of this code here. The API can be changed if necessary. */ - int done = 0; - - start_brace (); - printf("\n#ifdef OPTIMIZED_FLAGS\n"); +#ifdef OPTIMIZED_FLAGS switch (type) { case flag_add: case flag_sub: + start_brace (); printf ("\tuae_u32 %s;\n", value); break; default: @@ -891,9 +767,8 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch printf ("\tIOR_CZNV (oldcznv);\n"); } printf ("\t}\n"); - done = 1; - break; - + return; + case flag_logical: if (strcmp (value, "0") == 0) { printf ("\tSET_CZNV (FLAGVAL_Z);\n"); @@ -904,8 +779,7 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch case sz_long: printf ("\toptflag_testl ((uae_s32)(%s));\n", value); break; } } - done = 1; - break; + return; case flag_add: switch (size) { @@ -913,8 +787,7 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch case sz_word: printf ("\toptflag_addw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; case sz_long: printf ("\toptflag_addl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; } - done = 1; - break; + return; case flag_sub: switch (size) { @@ -922,8 +795,7 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch case sz_word: printf ("\toptflag_subw (%s, (uae_s16)(%s), (uae_s16)(%s));\n", value, src, dst); break; case sz_long: printf ("\toptflag_subl (%s, (uae_s32)(%s), (uae_s32)(%s));\n", value, src, dst); break; } - done = 1; - break; + return; case flag_cmp: switch (size) { @@ -931,19 +803,13 @@ static void genflags (flagtypes type, wordsizes size, char *value, char *src, ch case sz_word: printf ("\toptflag_cmpw ((uae_s16)(%s), (uae_s16)(%s));\n", src, dst); break; case sz_long: printf ("\toptflag_cmpl ((uae_s32)(%s), (uae_s32)(%s));\n", src, dst); break; } - done = 1; - break; + return; default: break; } - if (done) - printf("#else\n"); - else - printf("#endif\n"); +#endif genflags_normal (type, size, value, src, dst); - if (done) - printf("#endif\n"); } static void force_range_for_rox (const char *var, wordsizes size) @@ -971,7 +837,7 @@ static const char *cmask (wordsizes size) case sz_byte: return "0x80"; case sz_word: return "0x8000"; case sz_long: return "0x80000000"; - default: abort (); return NULL; + default: abort (); } } @@ -983,10 +849,11 @@ static int source_is_imm1_8 (struct instr *i) static void gen_opcode (unsigned long int opcode) { struct instr *curi = table68k + opcode; + insn_n_cycles = 2; start_brace (); #if 0 - printf ("uae_u8 *m68k_pc = m68k_getpc();\n"); + printf ("uae_u8 *m68k_pc = regs.pc_p;\n"); #endif m68k_pc_offset = 2; switch (curi->plev) { @@ -1016,16 +883,16 @@ static void gen_opcode (unsigned long int opcode) case i_OR: case i_AND: case i_EOR: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); printf ("\tsrc %c= dst;\n", curi->mnemo == i_OR ? '|' : curi->mnemo == i_AND ? '&' : '^'); genflags (flag_logical, curi->size, "src", "", ""); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); break; case i_ORSR: case i_EORSR: printf ("\tMakeSR();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); if (curi->size == sz_byte) { printf ("\tsrc &= 0xFF;\n"); } @@ -1034,7 +901,7 @@ static void gen_opcode (unsigned long int opcode) break; case i_ANDSR: printf ("\tMakeSR();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); if (curi->size == sz_byte) { printf ("\tsrc |= 0xFF00;\n"); } @@ -1042,33 +909,31 @@ static void gen_opcode (unsigned long int opcode) printf ("\tMakeFromSR();\n"); break; case i_SUB: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); genflags (flag_sub, curi->size, "newv", "src", "dst"); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_SUBA: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); start_brace (); printf ("\tuae_u32 newv = dst - src;\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); break; case i_SUBX: - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); printf ("\tuae_u32 newv = dst - src - (GET_XFLG ? 1 : 0);\n"); genflags (flag_subx, curi->size, "newv", "src", "dst"); genflags (flag_zn, curi->size, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_SBCD: - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); printf ("\tuae_u16 newv_lo = (dst & 0xF) - (src & 0xF) - (GET_XFLG ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = (dst & 0xF0) - (src & 0xF0);\n"); @@ -1079,50 +944,44 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif ((((dst & 0xFF) - (src & 0xFF) - (GET_XFLG ? 1 : 0)) & 0x100) > 0xFF) { newv -= 0x60; }\n"); printf ("\tSET_CFLG ((((dst & 0xFF) - (src & 0xFF) - bcd - (GET_XFLG ? 1 : 0)) & 0x300) > 0xFF);\n"); duplicate_carry (); - /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */ - if (cpu_level >= xBCD_KEEPS_N_FLAG) { - if (next_cpu_level < xBCD_KEEPS_N_FLAG) - next_cpu_level = xBCD_KEEPS_N_FLAG - 1; - genflags (flag_z, curi->size, "newv", "", ""); - } else { - genflags (flag_zn, curi->size, "newv", "", ""); + /* Manual says bits NV are undefined though a real 68040 don't change them */ + if (cpu_level >= xBCD_KEEPS_NV_FLAGS) { + if (next_cpu_level < xBCD_KEEPS_NV_FLAGS) + next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1; + genflags (flag_z, curi->size, "newv", "", ""); } - if (cpu_level >= xBCD_KEEPS_V_FLAG) { - if (next_cpu_level < xBCD_KEEPS_V_FLAG) - next_cpu_level = xBCD_KEEPS_V_FLAG - 1; - } else { - printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n"); + else { + genflags (flag_zn, curi->size, "newv", "", ""); + printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n"); } - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_ADD: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); genflags (flag_add, curi->size, "newv", "src", "dst"); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_ADDA: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); start_brace (); printf ("\tuae_u32 newv = dst + src;\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); break; case i_ADDX: - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); printf ("\tuae_u32 newv = dst + src + (GET_XFLG ? 1 : 0);\n"); genflags (flag_addx, curi->size, "newv", "src", "dst"); genflags (flag_zn, curi->size, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_ABCD: - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); printf ("\tuae_u16 newv_lo = (src & 0xF) + (dst & 0xF) + (GET_XFLG ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = (src & 0xF0) + (dst & 0xF0);\n"); @@ -1134,85 +993,75 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (cflg) newv += 0x60;\n"); printf ("\tSET_CFLG (cflg);\n"); duplicate_carry (); - /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */ - if (cpu_level >= xBCD_KEEPS_N_FLAG) { - if (next_cpu_level < xBCD_KEEPS_N_FLAG) - next_cpu_level = xBCD_KEEPS_N_FLAG - 1; - genflags (flag_z, curi->size, "newv", "", ""); - } else { - genflags (flag_zn, curi->size, "newv", "", ""); + /* Manual says bits NV are undefined though a real 68040 don't change them */ + if (cpu_level >= xBCD_KEEPS_NV_FLAGS) { + if (next_cpu_level < xBCD_KEEPS_NV_FLAGS) + next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1; + genflags (flag_z, curi->size, "newv", "", ""); } - if (cpu_level >= xBCD_KEEPS_V_FLAG) { - if (next_cpu_level < xBCD_KEEPS_V_FLAG) - next_cpu_level = xBCD_KEEPS_V_FLAG - 1; - } else { - printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n"); + else { + genflags (flag_zn, curi->size, "newv", "", ""); + printf ("\tSET_VFLG ((tmp_newv & 0x80) == 0 && (newv & 0x80) != 0);\n"); } - genastore ("newv", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", curi->size, "dst"); break; case i_NEG: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); genflags (flag_sub, curi->size, "dst", "src", "0"); - genastore ("dst", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("dst", curi->smode, "srcreg", curi->size, "src"); break; case i_NEGX: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); printf ("\tuae_u32 newv = 0 - src - (GET_XFLG ? 1 : 0);\n"); genflags (flag_subx, curi->size, "newv", "src", "0"); genflags (flag_zn, curi->size, "newv", "", ""); - genastore ("newv", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("newv", curi->smode, "srcreg", curi->size, "src"); break; case i_NBCD: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); printf ("\tuae_u16 newv_lo = - (src & 0xF) - (GET_XFLG ? 1 : 0);\n"); printf ("\tuae_u16 newv_hi = - (src & 0xF0);\n"); printf ("\tuae_u16 newv;\n"); - printf ("\tint cflg, tmp_newv;\n"); - printf ("\ttmp_newv = newv_hi + newv_lo;\n"); + printf ("\tint cflg;\n"); printf ("\tif (newv_lo > 9) { newv_lo -= 6; }\n"); printf ("\tnewv = newv_hi + newv_lo;\n"); printf ("\tcflg = (newv & 0x1F0) > 0x90;\n"); printf ("\tif (cflg) newv -= 0x60;\n"); printf ("\tSET_CFLG (cflg);\n"); duplicate_carry(); - /* Manual says bits NV are undefined though a real 68030 doesn't change V and 68040/060 don't change both */ - if (cpu_level >= xBCD_KEEPS_N_FLAG) { - if (next_cpu_level < xBCD_KEEPS_N_FLAG) - next_cpu_level = xBCD_KEEPS_N_FLAG - 1; - genflags (flag_z, curi->size, "newv", "", ""); - } else { - genflags (flag_zn, curi->size, "newv", "", ""); + /* Manual says bits NV are undefined though a real 68040 don't change them */ + if (cpu_level >= xBCD_KEEPS_NV_FLAGS) { + if (next_cpu_level < xBCD_KEEPS_NV_FLAGS) + next_cpu_level = xBCD_KEEPS_NV_FLAGS - 1; + genflags (flag_z, curi->size, "newv", "", ""); } - if (cpu_level >= xBCD_KEEPS_V_FLAG) { - if (next_cpu_level < xBCD_KEEPS_V_FLAG) - next_cpu_level = xBCD_KEEPS_V_FLAG - 1; - } else { - printf ("\tSET_VFLG ((tmp_newv & 0x80) != 0 && (newv & 0x80) == 0);\n"); + else { + genflags (flag_zn, curi->size, "newv", "", ""); } - genastore ("newv", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("newv", curi->smode, "srcreg", curi->size, "src"); break; case i_CLR: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); genflags (flag_logical, curi->size, "0", "", ""); - genastore ("0", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("0", curi->smode, "srcreg", curi->size, "src"); break; case i_NOT: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); printf ("\tuae_u32 dst = ~src;\n"); genflags (flag_logical, curi->size, "dst", "", ""); - genastore ("dst", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("dst", curi->smode, "srcreg", curi->size, "src"); break; case i_TST: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); genflags (flag_logical, curi->size, "src", "", ""); break; case i_BTST: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else @@ -1220,55 +1069,55 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); break; case i_BCHG: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else printf ("\tsrc &= 31;\n"); printf ("\tdst ^= (1 << src);\n"); printf ("\tSET_ZFLG (((uae_u32)dst & (1 << src)) >> src);\n"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); break; case i_BCLR: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else printf ("\tsrc &= 31;\n"); printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); printf ("\tdst &= ~(1 << src);\n"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); break; case i_BSET: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); if (curi->size == sz_byte) printf ("\tsrc &= 7;\n"); else printf ("\tsrc &= 31;\n"); printf ("\tSET_ZFLG (1 ^ ((dst >> src) & 1));\n"); printf ("\tdst |= (1 << src);\n"); - genastore ("dst", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("dst", curi->dmode, "dstreg", curi->size, "dst"); break; case i_CMPM: case i_CMP: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); genflags (flag_cmp, curi->size, "newv", "src", "dst"); break; case i_CMPA: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); start_brace (); genflags (flag_cmp, sz_long, "newv", "src", "dst"); break; /* The next two are coded a little unconventional, but they are doing * weird things... */ case i_MVPRM: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); printf ("\tuaecptr memp = m68k_areg(regs, dstreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ()); if (curi->size == sz_word) { @@ -1280,45 +1129,41 @@ static void gen_opcode (unsigned long int opcode) break; case i_MVPMR: printf ("\tuaecptr memp = m68k_areg(regs, srcreg) + (uae_s32)(uae_s16)%s;\n", gen_nextiword ()); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); if (curi->size == sz_word) { - printf ("\tuae_u16 val = get_byte(memp) << 8;\n"); - printf ("\t val |= get_byte(memp + 2);\n"); + printf ("\tuae_u16 val = (get_byte(memp) << 8) + get_byte(memp + 2);\n"); } else { - printf ("\tuae_u32 val = get_byte(memp) << 24;\n"); - printf ("\t val |= get_byte(memp + 2) << 16;\n"); - printf ("\t val |= get_byte(memp + 4) << 8;\n"); - printf ("\t val |= get_byte(memp + 6);\n"); + printf ("\tuae_u32 val = (get_byte(memp) << 24) + (get_byte(memp + 2) << 16)\n"); + printf (" + (get_byte(memp + 4) << 8) + get_byte(memp + 6);\n"); } - genastore ("val", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "dst"); break; case i_MOVE: - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode2 (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); genflags (flag_logical, curi->size, "src", "", ""); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); break; case i_MOVEA: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); if (curi->size == sz_word) { printf ("\tuae_u32 val = (uae_s32)(uae_s16)src;\n"); } else { printf ("\tuae_u32 val = src;\n"); } - genastore ("val", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", sz_long, "dst"); break; case i_MVSR2: - genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_word, "src", 2, 0); printf ("\tMakeSR();\n"); if (curi->size == sz_byte) - genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src", XLATE_LOG); + genastore ("regs.sr & 0xff", curi->smode, "srcreg", sz_word, "src"); else - genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src", XLATE_LOG); + genastore ("regs.sr", curi->smode, "srcreg", sz_word, "src"); break; case i_MV2SR: - genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); if (curi->size == sz_byte) printf ("\tMakeSR();\n\tregs.sr &= 0xFF00;\n\tregs.sr |= src & 0xFF;\n"); else { @@ -1327,84 +1172,66 @@ static void gen_opcode (unsigned long int opcode) printf ("\tMakeFromSR();\n"); break; case i_SWAP: - genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); start_brace (); printf ("\tuae_u32 dst = ((src >> 16)&0xFFFF) | ((src&0xFFFF)<<16);\n"); genflags (flag_logical, sz_long, "dst", "", ""); - genastore ("dst", curi->smode, "srcreg", sz_long, "src", XLATE_LOG); + genastore ("dst", curi->smode, "srcreg", sz_long, "src"); break; case i_EXG: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genastore ("dst", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); + genastore ("dst", curi->smode, "srcreg", curi->size, "src"); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); break; case i_EXT: - genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); start_brace (); switch (curi->size) { - case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break; - case sz_word: printf ("\tuae_u16 dst = (uae_s16)(uae_s8)src;\n"); break; - case sz_long: printf ("\tuae_u32 dst = (uae_s32)(uae_s16)src;\n"); break; - default: abort (); + case sz_byte: printf ("\tuae_u32 dst = (uae_s32)(uae_s8)src;\n"); break; + case sz_word: printf ("\tuae_u16 dst = (uae_s16)(uae_s8)src;\n"); break; + case sz_long: printf ("\tuae_u32 dst = (uae_s32)(uae_s16)src;\n"); break; + default: abort (); } genflags (flag_logical, curi->size == sz_word ? sz_word : sz_long, "dst", "", ""); genastore ("dst", curi->smode, "srcreg", - curi->size == sz_word ? sz_word : sz_long, "src", XLATE_LOG); + curi->size == sz_word ? sz_word : sz_long, "src"); break; case i_MVMEL: - genmovemel (opcode); + genmovemel ((uae_u16)opcode); break; case i_MVMLE: - genmovemle (opcode); + genmovemle ((uae_u16)opcode); break; case i_TRAP: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - gen_set_fault_pc (); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + sync_m68k_pc (); printf ("\tException(src+32,0);\n"); + m68k_pc_offset = 0; break; case i_MVR2USP: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); printf ("\tregs.usp = src;\n"); break; case i_MVUSP2R: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); - genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); + genastore ("regs.usp", curi->smode, "srcreg", curi->size, "src"); break; case i_RESET: - printf ("\tAtariReset();\n"); break; case i_NOP: break; case i_STOP: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - /* - * STOP undocumented features: - * if SR is not set: - * 68000 (68010?): Update SR, increase PC and then cause privilege violation exception (handled in newcpu) - * 68000 (68010?): Traced STOP also runs 4 cycles faster. - * 68020 68030: STOP works normally - * 68040 68060: Immediate privilege violation exception - */ - printf ("\tuae_u16 sr = src;\n"); - if (cpu_level >= 4) { - printf("\tif (!(sr & 0x2000)) {\n"); - printf ("m68k_incpc(%d);\n", m68k_pc_offset); - printf("\t\tException(8,0); goto %s;\n", endlabelstr); - printf("\t}\n"); - } - printf("\tregs.sr = sr;\n"); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + printf ("\tregs.sr = src;\n"); printf ("\tMakeFromSR();\n"); printf ("\tm68k_setstopped(1);\n"); - sync_m68k_pc (); - /* STOP does not prefetch anything */ - /* did_prefetch = -1; */ break; case i_RTE: if (cpu_level == 0) { - genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_word, "sr", 1, 0); + genamode (Aipi, "7", sz_long, "pc", 1, 0); printf ("\tregs.sr = sr; m68k_setpc_rte(pc);\n"); fill_prefetch_0 (); printf ("\tMakeFromSR();\n"); @@ -1413,14 +1240,15 @@ static void gen_opcode (unsigned long int opcode) if (next_cpu_level < 0) next_cpu_level = 0; printf ("\tuae_u16 newsr; uae_u32 newpc; for (;;) {\n"); - genamode (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Aipi, "7", sz_word, "format", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_word, "sr", 1, 0); + genamode (Aipi, "7", sz_long, "pc", 1, 0); + genamode (Aipi, "7", sz_word, "format", 1, 0); printf ("\tnewsr = sr; newpc = pc;\n"); printf ("\tif ((format & 0xF000) == 0x0000) { break; }\n"); printf ("\telse if ((format & 0xF000) == 0x1000) { ; }\n"); printf ("\telse if ((format & 0xF000) == 0x2000) { m68k_areg(regs, 7) += 4; break; }\n"); -// printf ("\telse if ((format & 0xF000) == 0x3000) { m68k_areg(regs, 7) += 4; break; }\n"); + /* gb-- the next two lines are deleted in Bernie's gencpu.c */ + printf ("\telse if ((format & 0xF000) == 0x3000) { m68k_areg(regs, 7) += 4; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x7000) { m68k_areg(regs, 7) += 52; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x8000) { m68k_areg(regs, 7) += 50; break; }\n"); printf ("\telse if ((format & 0xF000) == 0x9000) { m68k_areg(regs, 7) += 12; break; }\n"); @@ -1438,8 +1266,8 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_RTD: - genamode (curi->smode, "srcreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (Aipi, "7", sz_long, "pc", 1, 0); + genamode (curi->smode, "srcreg", curi->size, "offs", 1, 0); printf ("\tm68k_areg(regs, 7) += offs;\n"); printf ("\tm68k_setpc_rte(pc);\n"); fill_prefetch_0 (); @@ -1447,18 +1275,18 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_LINK: - genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Apdi, "7", sz_long, "old", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->smode, "srcreg", sz_long, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src", XLATE_LOG); + genamode (Apdi, "7", sz_long, "old", 2, 0); + genamode (curi->smode, "srcreg", sz_long, "src", 1, 0); + genastore ("src", Apdi, "7", sz_long, "old"); + genastore ("m68k_areg(regs, 7)", curi->smode, "srcreg", sz_long, "src"); + genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); printf ("\tm68k_areg(regs, 7) += offs;\n"); - genastore ("src", Apdi, "7", sz_long, "old", XLATE_LOG); break; case i_UNLK: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); printf ("\tm68k_areg(regs, 7) = src;\n"); - genamode (Aipi, "7", sz_long, "old", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genastore ("old", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genamode (Aipi, "7", sz_long, "old", 1, 0); + genastore ("old", curi->smode, "srcreg", curi->size, "src"); break; case i_RTS: printf ("\tm68k_do_rts();\n"); @@ -1466,16 +1294,14 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_TRAPV: - printf ("\tuaecptr oldpc = m68k_getpc();\n"); sync_m68k_pc (); - printf ("\tif (GET_VFLG) { Exception(7,oldpc); goto %s; }\n", endlabelstr); + printf ("\tif (GET_VFLG) { Exception(7,m68k_getpc()); goto %s; }\n", endlabelstr); need_endlabel = 1; break; case i_RTR: printf ("\tMakeSR();\n"); - genamode2 (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 1); - genamode (Aipi, "7", sz_long, "pc", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode2 (Aipi, "7", sz_word, "sr", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG, 2); + genamode (Aipi, "7", sz_word, "sr", 1, 0); + genamode (Aipi, "7", sz_long, "pc", 1, 0); printf ("\tregs.sr &= 0xFF00; sr &= 0xFF;\n"); printf ("\tregs.sr |= sr; m68k_setpc(pc);\n"); fill_prefetch_0 (); @@ -1483,19 +1309,19 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_JSR: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); + genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); printf ("\tm68k_do_jsr(m68k_getpc() + %d, srca);\n", m68k_pc_offset); fill_prefetch_0 (); m68k_pc_offset = 0; break; case i_JMP: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); + genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); printf ("\tm68k_setpc(srca);\n"); fill_prefetch_0 (); m68k_pc_offset = 0; break; case i_BSR: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); printf ("\tuae_s32 s = (uae_s32)src + 2;\n"); if (using_exception_3) { printf ("\tif (src & 1) {\n"); @@ -1510,6 +1336,18 @@ static void gen_opcode (unsigned long int opcode) m68k_pc_offset = 0; break; case i_Bcc: + if (0 && !using_prefetch && !using_exception_3 && (cpu_level >= 2)) { + /* gb-- variant probably more favorable to compiler optimizations + also assumes no prefetch buffer is used + Hmm, that would make sense with processors capable of conditional moves */ + if (curi->size == sz_long && next_cpu_level < 1) + next_cpu_level = 1; + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + printf ("\tm68k_incpc (cctrue(%d) ? ((uae_s32)src + 2) : %d);\n", curi->cc, m68k_pc_offset); + m68k_pc_offset = 0; + } + else { + /* original code for branch instructions */ if (curi->size == sz_long) { if (cpu_level < 2) { printf ("\tm68k_incpc(2);\n"); @@ -1523,8 +1361,8 @@ static void gen_opcode (unsigned long int opcode) next_cpu_level = 1; } } - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_PHYS); - printf ("\tif (!cctrue(%d)) goto didnt_jump_%lx;\n", curi->cc, opcode); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + printf ("\tif (!cctrue(%d)) goto didnt_jump;\n", curi->cc); if (using_exception_3) { printf ("\tif (src & 1) {\n"); printf ("\t\tlast_addr_for_exception_3 = m68k_getpc() + 2;\n"); @@ -1536,25 +1374,26 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_incpc ((uae_s32)src + 2);\n"); fill_prefetch_0 (); printf ("return;\n"); - printf ("didnt_jump_%lx:;\n", opcode); + printf ("didnt_jump:;\n"); need_endlabel = 1; + } break; case i_LEA: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); - genastore ("srca", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genastore ("srca", curi->dmode, "dstreg", curi->size, "dst"); break; case i_PEA: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_NO_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (Apdi, "7", sz_long, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); - genastore ("srca", Apdi, "7", sz_long, "dst", XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 0, 0); + genamode (Apdi, "7", sz_long, "dst", 2, 0); + genastore ("srca", Apdi, "7", sz_long, "dst"); break; case i_DBcc: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "offs", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "offs", 1, 0); printf ("\tif (!cctrue(%d)) {\n", curi->cc); - genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("(src-1)", curi->smode, "srcreg", curi->size, "src"); printf ("\t\tif (src) {\n"); if (using_exception_3) { @@ -1573,15 +1412,15 @@ static void gen_opcode (unsigned long int opcode) need_endlabel = 1; break; case i_Scc: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 2, 0); start_brace (); printf ("\tint val = cctrue(%d) ? 0xff : 0;\n", curi->cc); - genastore ("val", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "src"); break; case i_DIVU: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); sync_m68k_pc (); /* Clear V flag when dividing by zero - Alcatraz Odyssey demo depends * on this (actually, it's doing a DIVS). */ @@ -1593,15 +1432,16 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (newv > 0xffff) { SET_VFLG (1); SET_NFLG (1); SET_CFLG (0); } else\n\t{\n"); genflags (flag_logical, sz_word, "newv", "", ""); printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); printf ("\t}\n"); printf ("\t}\n"); + insn_n_cycles += 68; need_endlabel = 1; break; case i_DIVS: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0); sync_m68k_pc (); printf ("\tif (src == 0) { SET_VFLG (0); Exception(5,oldpc); goto %s; } else {\n", endlabelstr); printf ("\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n"); @@ -1610,31 +1450,34 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (((uae_s16)rem < 0) != ((uae_s32)dst < 0)) rem = -rem;\n"); genflags (flag_logical, sz_word, "newv", "", ""); printf ("\tnewv = (newv & 0xffff) | ((uae_u32)rem << 16);\n"); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); printf ("\t}\n"); printf ("\t}\n"); + insn_n_cycles += 72; need_endlabel = 1; break; case i_MULU: - genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); start_brace (); printf ("\tuae_u32 newv = (uae_u32)(uae_u16)dst * (uae_u32)(uae_u16)src;\n"); genflags (flag_logical, sz_long, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + insn_n_cycles += 32; break; case i_MULS: - genamode (curi->smode, "srcreg", sz_word, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_word, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", sz_word, "src", 1, 0); + genamode (curi->dmode, "dstreg", sz_word, "dst", 1, 0); start_brace (); printf ("\tuae_u32 newv = (uae_s32)(uae_s16)dst * (uae_s32)(uae_s16)src;\n"); genflags (flag_logical, sz_long, "newv", "", ""); - genastore ("newv", curi->dmode, "dstreg", sz_long, "dst", XLATE_LOG); + genastore ("newv", curi->dmode, "dstreg", sz_long, "dst"); + insn_n_cycles += 32; break; case i_CHK: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); printf ("\tif ((uae_s32)dst < 0) { SET_NFLG (1); Exception(6,oldpc); goto %s; }\n", endlabelstr); printf ("\telse if (dst > src) { SET_NFLG (0); Exception(6,oldpc); goto %s; }\n", endlabelstr); need_endlabel = 1; @@ -1642,8 +1485,8 @@ static void gen_opcode (unsigned long int opcode) case i_CHK2: printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); printf ("\t{uae_s32 upper,lower,reg = regs.regs[(extra >> 12) & 15];\n"); switch (curi->size) { case sz_byte: @@ -1667,8 +1510,8 @@ static void gen_opcode (unsigned long int opcode) break; case i_ASR: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1680,7 +1523,7 @@ static void gen_opcode (unsigned long int opcode) printf ("\tcnt &= 63;\n"); printf ("\tCLEAR_CZNV;\n"); printf ("\tif (cnt >= %d) {\n", bit_size (curi->size)); - printf ("\t\tval = %s & (uae_u32)-sign;\n", bit_mask (curi->size)); + printf ("\t\tval = %s & (uae_u32)-(uae_s32)sign;\n", bit_mask (curi->size)); printf ("\t\tSET_CFLG (sign);\n"); duplicate_carry (); if (source_is_imm1_8 (curi)) @@ -1691,17 +1534,17 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\tSET_CFLG (val & 1);\n"); duplicate_carry (); printf ("\t\tval >>= 1;\n"); - printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-sign;\n", + printf ("\t\tval |= (%s << (%d - cnt)) & (uae_u32)-(uae_s32)sign;\n", bit_mask (curi->size), bit_size (curi->size)); printf ("\t\tval &= %s;\n", bit_mask (curi->size)); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_ASL: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1733,11 +1576,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\tval &= %s;\n", bit_mask (curi->size)); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_LSR: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1762,11 +1605,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\t\tval >>= 1;\n"); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_LSL: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1792,11 +1635,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tval &= %s;\n", bit_mask (curi->size)); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_ROL: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1819,11 +1662,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_CFLG (val & 1);\n"); printf ("}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_ROR: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1846,11 +1689,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tSET_CFLG ((val & %s) >> %d);\n", cmask (curi->size), bit_size (curi->size) - 1); printf ("\t}\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_ROXL: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1876,11 +1719,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\t} }\n"); printf ("\tSET_CFLG (GET_XFLG);\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_ROXR: - genamode (curi->smode, "srcreg", curi->size, "cnt", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "cnt", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1909,10 +1752,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\t} }\n"); printf ("\tSET_CFLG (GET_XFLG);\n"); genflags (flag_logical_noclobber, curi->size, "val", "", ""); - genastore ("val", curi->dmode, "dstreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->dmode, "dstreg", curi->size, "data"); break; case i_ASRW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1926,10 +1769,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("\tSET_CFLG (cflg);\n"); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_ASLW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1946,10 +1789,10 @@ static void gen_opcode (unsigned long int opcode) duplicate_carry (); printf ("\tSET_VFLG (GET_VFLG | (sign2 != sign));\n"); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_LSRW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u32 val = (uae_u8)data;\n"); break; @@ -1962,10 +1805,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry);\n"); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_LSLW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -1978,10 +1821,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_ROLW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -1994,10 +1837,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (carry) val |= 1;\n"); genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_RORW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -2010,10 +1853,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\tif (carry) val |= %s;\n", cmask (curi->size)); genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry);\n"); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_ROXLW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -2027,10 +1870,10 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry >> %d);\n", bit_size (curi->size) - 1); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_ROXRW: - genamode (curi->smode, "srcreg", curi->size, "data", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "data", 1, 0); start_brace (); switch (curi->size) { case sz_byte: printf ("\tuae_u8 val = data;\n"); break; @@ -2044,129 +1887,103 @@ static void gen_opcode (unsigned long int opcode) genflags (flag_logical, curi->size, "val", "", ""); printf ("SET_CFLG (carry);\n"); duplicate_carry (); - genastore ("val", curi->smode, "srcreg", curi->size, "data", XLATE_LOG); + genastore ("val", curi->smode, "srcreg", curi->size, "data"); break; case i_MOVEC2: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); printf ("\tint regno = (src >> 12) & 15;\n"); printf ("\tuae_u32 *regp = regs.regs + regno;\n"); - printf ("\tif (!m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr); + printf ("\tif (! m68k_movec2(src & 0xFFF, regp)) goto %s;\n", endlabelstr); break; case i_MOVE2C: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); start_brace (); printf ("\tint regno = (src >> 12) & 15;\n"); printf ("\tuae_u32 *regp = regs.regs + regno;\n"); - printf ("\tif (!m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr); + printf ("\tif (! m68k_move2c(src & 0xFFF, regp)) goto %s;\n", endlabelstr); break; case i_CAS: { int old_brace_level; - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); start_brace (); printf ("\tint ru = (src >> 6) & 7;\n"); printf ("\tint rc = src & 7;\n"); genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc)", "dst"); - sync_m68k_pc (); printf ("\tif (GET_ZFLG)"); old_brace_level = n_braces; start_brace (); - genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst", XLATE_LOG); + genastore ("(m68k_dreg(regs, ru))", curi->dmode, "dstreg", curi->size, "dst"); pop_braces (old_brace_level); printf ("else"); start_brace (); - switch (curi->size) { - case sz_byte: - printf ("\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xff) | (dst & 0xff);\n"); - break; - case sz_word: - printf ("\tm68k_dreg(regs, rc) = (m68k_dreg(regs, rc) & ~0xffff) | (dst & 0xffff);\n"); - break; - default: - printf ("\tm68k_dreg(regs, rc) = dst;\n"); - break; - } + printf ("m68k_dreg(regs, rc) = dst;\n"); pop_braces (old_brace_level); } break; case i_CAS2: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); printf ("\tuae_u32 rn1 = regs.regs[(extra >> 28) & 15];\n"); printf ("\tuae_u32 rn2 = regs.regs[(extra >> 12) & 15];\n"); if (curi->size == sz_word) { int old_brace_level = n_braces; - printf ("\tuae_u32 rc1 = (extra >> 16) & 7;\n"); - printf ("\tuae_u32 rc2 = extra & 7;\n"); printf ("\tuae_u16 dst1 = get_word(rn1), dst2 = get_word(rn2);\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc1)", "dst1"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1"); printf ("\tif (GET_ZFLG) {\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc2)", "dst2"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2"); printf ("\tif (GET_ZFLG) {\n"); printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n"); - printf ("\tput_word(rn2, m68k_dreg(regs, (extra >> 6) & 7));\n"); + printf ("\tput_word(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n"); printf ("\t}}\n"); pop_braces (old_brace_level); printf ("\tif (! GET_ZFLG) {\n"); - printf ("\tm68k_dreg(regs, rc2) = (m68k_dreg(regs, rc2) & ~0xffff) | (dst2 & 0xffff);\n"); - printf ("\tm68k_dreg(regs, rc1) = (m68k_dreg(regs, rc1) & ~0xffff) | (dst1 & 0xffff);\n"); + printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = (m68k_dreg(regs, (extra >> 22) & 7) & ~0xffff) | (dst1 & 0xffff);\n"); + printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = (m68k_dreg(regs, (extra >> 6) & 7) & ~0xffff) | (dst2 & 0xffff);\n"); printf ("\t}\n"); } else { int old_brace_level = n_braces; - printf ("\tuae_u32 rc1 = (extra >> 16) & 7;\n"); - printf ("\tuae_u32 rc2 = extra & 7;\n"); printf ("\tuae_u32 dst1 = get_long(rn1), dst2 = get_long(rn2);\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc1)", "dst1"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, (extra >> 16) & 7)", "dst1"); printf ("\tif (GET_ZFLG) {\n"); - genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, rc2)", "dst2"); + genflags (flag_cmp, curi->size, "newv", "m68k_dreg(regs, extra & 7)", "dst2"); printf ("\tif (GET_ZFLG) {\n"); printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 22) & 7));\n"); - printf ("\tput_long(rn2, m68k_dreg(regs, (extra >> 6) & 7));\n"); + printf ("\tput_long(rn1, m68k_dreg(regs, (extra >> 6) & 7));\n"); printf ("\t}}\n"); pop_braces (old_brace_level); printf ("\tif (! GET_ZFLG) {\n"); - printf ("\tm68k_dreg(regs, rc2) = dst2;\n"); - printf ("\tm68k_dreg(regs, rc1) = dst1;\n"); + printf ("\tm68k_dreg(regs, (extra >> 22) & 7) = dst1;\n"); + printf ("\tm68k_dreg(regs, (extra >> 6) & 7) = dst2;\n"); printf ("\t}\n"); } break; - case i_MOVES: + case i_MOVES: /* ignore DFC and SFC because we have no MMU */ { - int old_brace_level; - - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - start_brace(); - printf ("\tif (extra & 0x0800)\n"); /* from reg to ea */ - { - int old_m68k_pc_offset = m68k_pc_offset; - /* use DFC */ - old_brace_level = n_braces; - start_brace (); - printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n"); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_DFC); - genastore ("src", curi->dmode, "dstreg", curi->size, "dst", XLATE_DFC); - pop_braces (old_brace_level); - m68k_pc_offset = old_m68k_pc_offset; - } - printf ("else"); /* from ea to reg */ - { - /* use SFC */ - start_brace (); - genamode (curi->dmode, "dstreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_SFC); - printf ("\tif (extra & 0x8000) {\n"); /* address/data */ - switch (curi->size) { - case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break; - case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break; - case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break; - default: abort (); - } - printf ("\t} else {\n"); - genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, "", XLATE_LOG); - printf ("\t}\n"); - sync_m68k_pc(); - pop_braces (old_brace_level); - } + int old_brace_level; + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + printf ("\tif (extra & 0x800)\n"); + old_brace_level = n_braces; + start_brace (); + printf ("\tuae_u32 src = regs.regs[(extra >> 12) & 15];\n"); + genamode (curi->dmode, "dstreg", curi->size, "dst", 2, 0); + genastore ("src", curi->dmode, "dstreg", curi->size, "dst"); + pop_braces (old_brace_level); + printf ("else"); + start_brace (); + genamode (curi->dmode, "dstreg", curi->size, "src", 1, 0); + printf ("\tif (extra & 0x8000) {\n"); + switch (curi->size) { + case sz_byte: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s8)src;\n"); break; + case sz_word: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = (uae_s32)(uae_s16)src;\n"); break; + case sz_long: printf ("\tm68k_areg(regs, (extra >> 12) & 7) = src;\n"); break; + default: abort (); + } + printf ("\t} else {\n"); + genastore ("src", Dreg, "(extra >> 12) & 7", curi->size, ""); + printf ("\t}\n"); + pop_braces (old_brace_level); } break; case i_BKPT: /* only needed for hardware emulators */ @@ -2182,23 +1999,23 @@ static void gen_opcode (unsigned long int opcode) printf ("\top_illg(opcode);\n"); break; case i_TRAPcc: - printf ("\tuaecptr oldpc = m68k_getpc();\n"); if (curi->smode != am_unknown && curi->smode != am_illg) - genamode (curi->smode, "srcreg", curi->size, "dummy", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - sync_m68k_pc (); - printf ("\tif (cctrue(%d)) { Exception(7,oldpc); goto %s; }\n", curi->cc, endlabelstr); + genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0); + printf ("\tif (cctrue(%d)) { Exception(7,m68k_getpc()); goto %s; }\n", curi->cc, endlabelstr); need_endlabel = 1; break; case i_DIVL: + sync_m68k_pc (); + start_brace (); printf ("\tuaecptr oldpc = m68k_getpc();\n"); - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); sync_m68k_pc (); printf ("\tm68k_divl(opcode, dst, extra, oldpc);\n"); break; case i_MULL: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "dst", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0); sync_m68k_pc (); printf ("\tm68k_mull(opcode, dst, extra);\n"); break; @@ -2210,37 +2027,34 @@ static void gen_opcode (unsigned long int opcode) case i_BFFFO: case i_BFSET: case i_BFINS: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); - genamode (curi->dmode, "dstreg", sz_long, "dst", GENA_GETV_FETCH_ALIGN, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); + genamode (curi->dmode, "dstreg", sz_long, "dst", 2, 0); start_brace (); - printf ("\tuae_u32 bdata[2];"); printf ("\tuae_s32 offset = extra & 0x800 ? m68k_dreg(regs, (extra >> 6) & 7) : (extra >> 6) & 0x1f;\n"); printf ("\tint width = (((extra & 0x20 ? m68k_dreg(regs, extra & 7) : extra) -1) & 0x1f) +1;\n"); if (curi->dmode == Dreg) { - printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg);\n"); - printf ("\toffset &= 0x1f;\n"); - printf ("\ttmp = (tmp << offset) | (tmp >> (32 - offset));\n"); - printf ("\tbdata[0] = tmp & ((1 << (32 - width)) - 1);\n"); + printf ("\tuae_u32 tmp = m68k_dreg(regs, dstreg) << (offset & 0x1f);\n"); } else { - printf ("\tuae_u32 tmp;\n"); - printf ("\tdsta += offset >> 3;\n"); - printf ("\ttmp = get_bitfield(dsta, bdata, offset, width);\n"); + printf ("\tuae_u32 tmp,bf0,bf1;\n"); + printf ("\tdsta += (offset >> 3) | (offset & 0x80000000 ? ~0x1fffffff : 0);\n"); + printf ("\tbf0 = get_long(dsta);bf1 = get_byte(dsta+4) & 0xff;\n"); + printf ("\ttmp = (bf0 << (offset & 7)) | (bf1 >> (8 - (offset & 7)));\n"); } - printf ("\tSET_NFLG_ALWAYS (((uae_s32)tmp) < 0 ? 1 : 0);\n"); - if (curi->mnemo == i_BFEXTS) - printf ("\ttmp = (uae_s32)tmp >> (32 - width);\n"); - else - printf ("\ttmp >>= (32 - width);\n"); + printf ("\ttmp >>= (32 - width);\n"); + printf ("\tSET_NFLG_ALWAYS (tmp & (1 << (width-1)) ? 1 : 0);\n"); printf ("\tSET_ZFLG (tmp == 0); SET_VFLG (0); SET_CFLG (0);\n"); switch (curi->mnemo) { case i_BFTST: break; case i_BFEXTU: - case i_BFEXTS: printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n"); break; case i_BFCHG: - printf ("\ttmp = tmp ^ (0xffffffffu >> (32 - width));\n"); + printf ("\ttmp = ~tmp;\n"); + break; + case i_BFEXTS: + printf ("\tif (GET_NFLG) tmp |= width == 32 ? 0 : (-1 << width);\n"); + printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = tmp;\n"); break; case i_BFCLR: printf ("\ttmp = 0;\n"); @@ -2251,11 +2065,10 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_dreg(regs, (extra >> 12) & 7) = offset;\n"); break; case i_BFSET: - printf ("\ttmp = 0xffffffffu >> (32 - width);\n"); + printf ("\ttmp = 0xffffffff;\n"); break; case i_BFINS: printf ("\ttmp = m68k_dreg(regs, (extra >> 12) & 7);\n"); - printf ("\ttmp = tmp & (0xffffffffu >> (32 - width));\n"); printf ("\tSET_NFLG_ALWAYS (tmp & (1 << (width - 1)) ? 1 : 0);\n"); printf ("\tSET_ZFLG (tmp == 0);\n"); break; @@ -2265,12 +2078,26 @@ static void gen_opcode (unsigned long int opcode) if (curi->mnemo == i_BFCHG || curi->mnemo == i_BFCLR || curi->mnemo == i_BFSET - || curi->mnemo == i_BFINS) { + || curi->mnemo == i_BFINS) + { + printf ("\ttmp <<= (32 - width);\n"); if (curi->dmode == Dreg) { - printf ("\ttmp = bdata[0] | (tmp << (32 - width));\n"); - printf ("\tm68k_dreg(regs, dstreg) = (tmp >> offset) | (tmp << (32 - offset));\n"); + printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & ((offset & 0x1f) == 0 ? 0 :\n"); + printf ("\t\t(0xffffffff << (32 - (offset & 0x1f))))) |\n"); + printf ("\t\t(tmp >> (offset & 0x1f)) |\n"); + printf ("\t\t(((offset & 0x1f) + width) >= 32 ? 0 :\n"); + printf (" (m68k_dreg(regs, dstreg) & ((uae_u32)0xffffffff >> ((offset & 0x1f) + width))));\n"); } else { - printf ("\tput_bitfield(dsta, bdata, tmp, offset, width);\n"); + printf ("\tbf0 = (bf0 & (0xff000000 << (8 - (offset & 7)))) |\n"); + printf ("\t\t(tmp >> (offset & 7)) |\n"); + printf ("\t\t(((offset & 7) + width) >= 32 ? 0 :\n"); + printf ("\t\t (bf0 & ((uae_u32)0xffffffff >> ((offset & 7) + width))));\n"); + printf ("\tput_long(dsta,bf0 );\n"); + printf ("\tif (((offset & 7) + width) > 32) {\n"); + printf ("\t\tbf1 = (bf1 & (0xff >> (width - 32 + (offset & 7)))) |\n"); + printf ("\t\t\t(tmp << (8 - (offset & 7)));\n"); + printf ("\t\tput_byte(dsta+4,bf1);\n"); + printf ("\t}\n"); } } break; @@ -2280,11 +2107,11 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffffff00) | ((val >> 4) & 0xf0) | (val & 0xf);\n"); } else { printf ("\tuae_u16 val;\n"); - printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg) - areg_byteinc[srcreg]);\n"); - printf ("\tval = (val | ((uae_u16)get_byte(m68k_areg(regs, srcreg) - 2 * areg_byteinc[srcreg]) << 8)) + %s;\n", gen_nextiword ()); - printf ("\tm68k_areg(regs, srcreg) -= 2;\n"); + printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); + printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n"); + printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); + printf ("\tval = (val | ((uae_u16)get_byte(m68k_areg(regs, srcreg)) << 8)) + %s;\n", gen_nextiword ()); printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n"); - gen_set_fault_pc (); printf ("\tput_byte(m68k_areg(regs, dstreg),((val >> 4) & 0xf0) | (val & 0xf));\n"); } break; @@ -2295,57 +2122,57 @@ static void gen_opcode (unsigned long int opcode) printf ("\tm68k_dreg(regs, dstreg) = (m68k_dreg(regs, dstreg) & 0xffff0000) | (val & 0xffff);\n"); } else { printf ("\tuae_u16 val;\n"); - printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg) - areg_byteinc[srcreg]);\n"); - printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ()); printf ("\tm68k_areg(regs, srcreg) -= areg_byteinc[srcreg];\n"); - printf ("\tm68k_areg(regs, dstreg) -= 2;\n"); - gen_set_fault_pc (); - printf ("\tput_word(m68k_areg(regs, dstreg), val);\n"); + printf ("\tval = (uae_u16)get_byte(m68k_areg(regs, srcreg));\n"); + printf ("\tval = (((val << 4) & 0xf00) | (val & 0xf)) + %s;\n", gen_nextiword ()); + printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n"); + printf ("\tput_byte(m68k_areg(regs, dstreg),val);\n"); + printf ("\tm68k_areg(regs, dstreg) -= areg_byteinc[dstreg];\n"); + printf ("\tput_byte(m68k_areg(regs, dstreg),val >> 8);\n"); } break; case i_TAS: - genamode (curi->smode, "srcreg", curi->size, "src", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "src", 1, 0); genflags (flag_logical, curi->size, "src", "", ""); printf ("\tsrc |= 0x80;\n"); - genastore ("src", curi->smode, "srcreg", curi->size, "src", XLATE_LOG); + genastore ("src", curi->smode, "srcreg", curi->size, "src"); break; case i_FPP: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); printf ("\tfpuop_arithmetic(opcode, extra);\n"); break; case i_FDBcc: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); printf ("\tfpuop_dbcc(opcode, extra);\n"); break; case i_FScc: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_scc(opcode, extra);\n"); + printf ("\tfpuop_scc(opcode,extra);\n"); break; case i_FTRAPcc: sync_m68k_pc (); start_brace (); printf ("\tuaecptr oldpc = m68k_getpc();\n"); - printf ("\tuae_u16 extra = %s;\n", gen_nextiword()); if (curi->smode != am_unknown && curi->smode != am_illg) - genamode (curi->smode, "srcreg", curi->size, "dummy", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "dummy", 1, 0); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_trapcc(opcode, oldpc, extra);\n"); + printf ("\tfpuop_trapcc(opcode,oldpc);\n"); break; case i_FBcc: sync_m68k_pc (); start_brace (); printf ("\tuaecptr pc = m68k_getpc();\n"); - genamode (curi->dmode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->dmode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); - printf ("\tfpuop_bcc(opcode, pc, extra);\n"); + printf ("\tfpuop_bcc(opcode,pc,extra);\n"); break; case i_FSAVE: sync_m68k_pc (); @@ -2358,104 +2185,67 @@ static void gen_opcode (unsigned long int opcode) printf ("\tfpuop_restore(opcode);\n"); break; case i_CINVL: - printf ("\tflush_internals();\n"); - printf("#ifdef USE_JIT\n"); - printf ("\tif (opcode&0x80)\n" - "\t\tflush_icache(31);\n"); - printf("#endif\n"); - break; case i_CINVP: - printf ("\tflush_internals();\n"); - printf("#ifdef USE_JIT\n"); - printf ("\tif (opcode&0x80)\n" - "\t\tflush_icache(32);\n"); - printf("#endif\n"); - break; case i_CINVA: - printf ("\tflush_internals();\n"); - printf("#ifdef USE_JIT\n"); - printf ("\tif (opcode&0x80)\n" - "\t\tflush_icache(33);\n"); - printf("#endif\n"); + /* gb-- srcreg now contains the cache field */ + printf ("\tif (srcreg&0x2)\n"); + printf ("\t\tflush_icache(%d);\n", 30 + ((opcode >> 3) & 3)); break; case i_CPUSHL: - printf ("\tflush_internals();\n"); - printf("#ifdef USE_JIT\n"); - printf ("\tif (opcode&0x80)\n" - "\t\tflush_icache(41);\n"); - printf("#endif\n"); - break; case i_CPUSHP: - printf ("\tflush_internals();\n"); - printf("#ifdef USE_JIT\n"); - printf ("\tif (opcode&0x80)\n" - "\t\tflush_icache(42);\n"); - printf("#endif\n"); - break; case i_CPUSHA: - printf ("\tflush_internals();\n"); - printf("#ifdef USE_JIT\n"); - printf ("\tif (opcode&0x80)\n" - "\t\tflush_icache(43);\n"); - printf("#endif\n"); + /* gb-- srcreg now contains the cache field */ + printf ("\tif (srcreg&0x2)\n"); + printf ("\t\tflush_icache(%d);\n", 40 + ((opcode >> 3) & 3)); break; case i_MOVE16: - if ((opcode & 0xfff8) == 0xf620) { - /* MOVE16 (Ax)+,(Ay)+ */ - printf ("\tuaecptr mems = m68k_areg(regs, srcreg) & ~15, memd;\n"); - printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword()); - printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n"); - printf ("\tput_long(memd, get_long(mems));\n"); - printf ("\tput_long(memd+4, get_long(mems+4));\n"); - printf ("\tput_long(memd+8, get_long(mems+8));\n"); - printf ("\tput_long(memd+12, get_long(mems+12));\n"); - printf ("\tif (srcreg != dstreg)\n"); - printf ("\tm68k_areg(regs, srcreg) += 16;\n"); - printf ("\tm68k_areg(regs, dstreg) += 16;\n"); - } else { - /* Other variants */ - genamode (curi->smode, "srcreg", curi->size, "mems", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16, XLATE_LOG); - genamode (curi->dmode, "dstreg", curi->size, "memd", GENA_GETV_NO_FETCH, GENA_MOVEM_MOVE16, XLATE_LOG); - printf ("\tmemsa &= ~15;\n"); - printf ("\tmemda &= ~15;\n"); - printf ("\tput_long(memda, get_long(memsa));\n"); - printf ("\tput_long(memda+4, get_long(memsa+4));\n"); - printf ("\tput_long(memda+8, get_long(memsa+8));\n"); - printf ("\tput_long(memda+12, get_long(memsa+12));\n"); - if ((opcode & 0xfff8) == 0xf600) - printf ("\tm68k_areg(regs, srcreg) += 16;\n"); - else if ((opcode & 0xfff8) == 0xf608) - printf ("\tm68k_areg(regs, dstreg) += 16;\n"); - } - break; + if ((opcode & 0xfff8) == 0xf620) { + /* MOVE16 (Ax)+,(Ay)+ */ + printf ("\tuaecptr mems = m68k_areg(regs, srcreg) & ~15, memd;\n"); + printf ("\tdstreg = (%s >> 12) & 7;\n", gen_nextiword()); + printf ("\tmemd = m68k_areg(regs, dstreg) & ~15;\n"); + printf ("\tput_long(memd, get_long(mems));\n"); + printf ("\tput_long(memd+4, get_long(mems+4));\n"); + printf ("\tput_long(memd+8, get_long(mems+8));\n"); + printf ("\tput_long(memd+12, get_long(mems+12));\n"); + printf ("\tif (srcreg != dstreg)\n"); + printf ("\tm68k_areg(regs, srcreg) += 16;\n"); + printf ("\tm68k_areg(regs, dstreg) += 16;\n"); + } + else { + /* Other variants */ + genamode (curi->smode, "srcreg", curi->size, "mems", 0, 2); + genamode (curi->dmode, "dstreg", curi->size, "memd", 0, 2); + printf ("\tmemsa &= ~15;\n"); + printf ("\tmemda &= ~15;\n"); + printf ("\tput_long(memda, get_long(memsa));\n"); + printf ("\tput_long(memda+4, get_long(memsa+4));\n"); + printf ("\tput_long(memda+8, get_long(memsa+8));\n"); + printf ("\tput_long(memda+12, get_long(memsa+12));\n"); + if ((opcode & 0xfff8) == 0xf600) + printf ("\tm68k_areg(regs, srcreg) += 16;\n"); + else if ((opcode & 0xfff8) == 0xf608) + printf ("\tm68k_areg(regs, dstreg) += 16;\n"); + } + break; case i_MMUOP: - genamode (curi->smode, "srcreg", curi->size, "extra", GENA_GETV_FETCH, GENA_MOVEM_DO_INC, XLATE_LOG); + genamode (curi->smode, "srcreg", curi->size, "extra", 1, 0); sync_m68k_pc (); swap_opcode (); printf ("\tmmu_op(opcode,extra);\n"); break; - - case i_EMULOP_RETURN: + + case i_EMULOP_RETURN: printf ("\tm68k_emulop_return();\n"); m68k_pc_offset = 0; break; - case i_EMULOP: + case i_EMULOP: printf ("\n"); swap_opcode (); printf ("\tm68k_emulop(opcode);\n"); break; - - case i_NATFEAT_ID: - printf ("\n"); - printf ("\tm68k_natfeat_id();\n"); - break; - - case i_NATFEAT_CALL: - printf ("\n"); - printf ("\tm68k_natfeat_call();\n"); - break; - + default: abort (); break; @@ -2467,92 +2257,73 @@ static void gen_opcode (unsigned long int opcode) static void generate_includes (FILE * f) { fprintf (f, "#include \"sysdeps.h\"\n"); + fprintf (f, "#include \"m68k.h\"\n"); fprintf (f, "#include \"memory.h\"\n"); fprintf (f, "#include \"readcpu.h\"\n"); fprintf (f, "#include \"newcpu.h\"\n"); - fprintf (f, "#ifdef USE_JIT\n"); fprintf (f, "#include \"compiler/compemu.h\"\n"); - fprintf (f, "#endif\n"); fprintf (f, "#include \"fpu/fpu.h\"\n"); fprintf (f, "#include \"cputbl.h\"\n"); - fprintf (f, "#include \"cpu_emulation.h\"\n"); - fprintf (f, "#include \"debug.h\"\n"); - - fprintf (f, "#define SET_CFLG_ALWAYS(x) SET_CFLG(x)\n"); - fprintf (f, "#define SET_NFLG_ALWAYS(x) SET_NFLG(x)\n"); - fprintf (f, "#define CPUFUNC_FF(x) x##_ff\n"); - fprintf (f, "#define CPUFUNC_NF(x) x##_nf\n"); - fprintf (f, "#define CPUFUNC(x) CPUFUNC_FF(x)\n"); - fprintf (f, "#ifdef NOFLAGS\n"); - fprintf (f, "# include \"noflags.h\"\n"); - fprintf (f, "#endif\n"); + fprintf (f, "#define SET_CFLG_ALWAYS(x) SET_CFLG(x)\n"); + fprintf (f, "#define SET_NFLG_ALWAYS(x) SET_NFLG(x)\n"); + fprintf (f, "#define CPUFUNC_FF(x) x##_ff\n"); + fprintf (f, "#define CPUFUNC_NF(x) x##_nf\n"); + fprintf (f, "#define CPUFUNC(x) CPUFUNC_FF(x)\n"); + + fprintf (f, "#ifdef NOFLAGS\n"); + fprintf (f, "# include \"noflags.h\"\n"); + fprintf (f, "#endif\n"); } static int postfix; -struct gencputbl { - char handler[80]; - uae_u16 specific; - uae_u16 opcode; - int namei; -}; -struct gencputbl cpustbl[65536]; -static int n_cpustbl; - static void generate_one_opcode (int rp) { - int i; uae_u16 smsk, dmsk; - int opcode = opcode_map[rp]; - int have_realopcode = 0; - - if (table68k[opcode].mnemo == i_ILLG - || table68k[opcode].clev > cpu_level) - return; + long int opcode = opcode_map[rp]; + const char *opcode_str; - for (i = 0; lookuptab[i].name[0]; i++) { - if (table68k[opcode].mnemo == lookuptab[i].mnemo) - break; - } + if (table68k[opcode].mnemo == i_ILLG + || table68k[opcode].clev > (unsigned)cpu_level) + return; if (table68k[opcode].handler != -1) return; - if (opcode_next_clev[rp] != cpu_level) { - sprintf(cpustbl[n_cpustbl].handler, "CPUFUNC(op_%x_%d)", opcode, opcode_last_postfix[rp]); - cpustbl[n_cpustbl].specific = 0; - cpustbl[n_cpustbl].opcode = opcode; - cpustbl[n_cpustbl].namei = i; - fprintf (stblfile, "{ %s, %d, %d }, /* %s */\n", cpustbl[n_cpustbl].handler, cpustbl[n_cpustbl].specific, opcode, lookuptab[i].name); - n_cpustbl++; - return; - } + opcode_str = get_instruction_string (opcode); + if (opcode_next_clev[rp] != cpu_level) { if (table68k[opcode].flagdead == 0) /* force to the "ff" variant since the instruction doesn't set at all the condition codes */ - sprintf (cpustbl[n_cpustbl].handler, "CPUFUNC_FF(op_%x_%d)", opcode, postfix); + fprintf (stblfile, "{ CPUFUNC_FF(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp], + opcode, opcode_str); else - sprintf (cpustbl[n_cpustbl].handler, "CPUFUNC(op_%x_%d)", opcode, postfix); - cpustbl[n_cpustbl].specific = 0; - cpustbl[n_cpustbl].opcode = opcode; - cpustbl[n_cpustbl].namei = i; - fprintf (stblfile, "{ %s, %d, %d }, /* %s */\n", cpustbl[n_cpustbl].handler, cpustbl[n_cpustbl].specific, opcode, lookuptab[i].name); - n_cpustbl++; + fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, opcode_last_postfix[rp], + opcode, opcode_str); + return; + } + + if (table68k[opcode].flagdead == 0) + /* force to the "ff" variant since the instruction doesn't set at all the condition codes */ + fprintf (stblfile, "{ CPUFUNC_FF(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, postfix, opcode, opcode_str); + else + fprintf (stblfile, "{ CPUFUNC(op_%lx_%d), 0, %ld }, /* %s */\n", opcode, postfix, opcode, opcode_str); - fprintf (headerfile, "extern cpuop_func op_%x_%d_nf;\n", opcode, postfix); - fprintf (headerfile, "extern cpuop_func op_%x_%d_ff;\n", opcode, postfix); - - printf ("void REGPARAM2 CPUFUNC(op_%x_%d)(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, lookuptab[i].name); - printf ("\tcpuop_begin();\n"); + fprintf (headerfile, "extern cpuop_func op_%lx_%d_nf;\n", opcode, postfix); + fprintf (headerfile, "extern cpuop_func op_%lx_%d_ff;\n", opcode, postfix); + /* gb-- The "nf" variant for an instruction that doesn't set the condition codes at all is the same as the "ff" variant, so we don't need the "nf" variant to be compiled since it is mapped to the "ff" variant in the smalltbl. */ - if (table68k[opcode].flagdead == 0) + if (table68k[opcode].flagdead == 0) printf ("#ifndef NOFLAGS\n"); + printf ("void REGPARAM2 CPUFUNC(op_%lx_%d)(uae_u32 opcode) /* %s */\n{\n", opcode, postfix, opcode_str); + printf ("\tcpuop_begin();\n"); + switch (table68k[opcode].stype) { case 0: smsk = 7; break; case 1: smsk = 255; break; @@ -2560,8 +2331,8 @@ static void generate_one_opcode (int rp) case 3: smsk = 7; break; case 4: smsk = 7; break; case 5: smsk = 63; break; - case 6: smsk = 255; break; - case 7: smsk = 3; break; + case 6: smsk = 255; break; + case 7: smsk = 3; break; default: abort (); } dmsk = 7; @@ -2592,17 +2363,38 @@ static void generate_one_opcode (int rp) if (pos < 8 && (smsk >> (8 - pos)) != 0) abort (); #endif - real_opcode(&have_realopcode); - if (pos) - sprintf (source, "((real_opcode >> %d) & %d)", pos, smsk); + printf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); + + if (pos < 8 && (smsk >> (8 - pos)) != 0) + sprintf (source, "(((opcode >> %d) | (opcode << %d)) & %d)", + pos ^ 8, 8 - pos, dmsk); + else if (pos != 8) + sprintf (source, "((opcode >> %d) & %d)", pos ^ 8, smsk); else - sprintf (source, "(real_opcode & %d)", smsk); + sprintf (source, "(opcode & %d)", smsk); + if (table68k[opcode].stype == 3) printf ("\tuae_u32 srcreg = imm8_table[%s];\n", source); else if (table68k[opcode].stype == 1) printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source); else printf ("\tuae_u32 srcreg = %s;\n", source); + + printf ("#else\n"); + + if (pos) + sprintf (source, "((opcode >> %d) & %d)", pos, smsk); + else + sprintf (source, "(opcode & %d)", smsk); + + if (table68k[opcode].stype == 3) + printf ("\tuae_u32 srcreg = imm8_table[%s];\n", source); + else if (table68k[opcode].stype == 1) + printf ("\tuae_u32 srcreg = (uae_s32)(uae_s8)%s;\n", source); + else + printf ("\tuae_u32 srcreg = %s;\n", source); + + printf ("#endif\n"); } } if (table68k[opcode].duse @@ -2622,13 +2414,27 @@ static void generate_one_opcode (int rp) /* Check that we can do the little endian optimization safely. */ if (pos < 8 && (dmsk >> (8 - pos)) != 0) abort (); -#endif - real_opcode(&have_realopcode); +#endif + printf ("#ifdef HAVE_GET_WORD_UNSWAPPED\n"); + + if (pos < 8 && (dmsk >> (8 - pos)) != 0) + printf ("\tuae_u32 dstreg = ((opcode >> %d) | (opcode << %d)) & %d;\n", + pos ^ 8, 8 - pos, dmsk); + else if (pos != 8) + printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", + pos ^ 8, dmsk); + else + printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk); + + printf ("#else\n"); + if (pos) - printf ("\tuae_u32 dstreg = (real_opcode >> %d) & %d;\n", + printf ("\tuae_u32 dstreg = (opcode >> %d) & %d;\n", pos, dmsk); else - printf ("\tuae_u32 dstreg = real_opcode & %d;\n", dmsk); + printf ("\tuae_u32 dstreg = opcode & %d;\n", dmsk); + + printf ("#endif\n"); } } need_endlabel = 0; @@ -2637,10 +2443,10 @@ static void generate_one_opcode (int rp) gen_opcode (opcode); if (need_endlabel) printf ("%s: ;\n", endlabelstr); - if (table68k[opcode].flagdead == 0) - printf ("\n#endif\n"); - printf ("\tcpuop_end();\n"); + printf ("\tcpuop_end();\n"); printf ("}\n"); + if (table68k[opcode].flagdead == 0) + printf ("\n#endif\n"); opcode_next_clev[rp] = next_cpu_level; opcode_last_postfix[rp] = postfix; } @@ -2651,18 +2457,36 @@ static void generate_func (void) using_prefetch = 0; using_exception_3 = 0; - - for (i = 0; i < 1; i++) { +#if !USE_PREFETCH_BUFFER + /* gb-- No need for a prefetch buffer, nor exception 3 handling */ + /* Anyway, Basilisk2 does not use the op_smalltbl_5 table... */ + for (i = 0; i <= 4; i++) { +#else + for (i = 0; i < 6; i++) { +#endif cpu_level = 4 - i; + if (i == 5) { + cpu_level = 0; + using_prefetch = 1; + using_exception_3 = 1; + for (rp = 0; rp < nr_cpuop_funcs; rp++) + opcode_next_clev[rp] = 0; + } postfix = i; - fprintf (stblfile, "const struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix); + fprintf (stblfile, "struct cputbl CPUFUNC(op_smalltbl_%d)[] = {\n", postfix); + + /* Disable spurious warnings. */ + printf ("\n" + "#ifdef _MSC_VER\n" + "#pragma warning(disable:4102) /* unreferenced label */\n" + "#endif\n"); /* sam: this is for people with low memory (eg. me :)) */ printf ("\n" - "#if !defined(PART_1) && !defined(PART_2) && " - "!defined(PART_3) && !defined(PART_4) && " - "!defined(PART_5) && !defined(PART_6) && " - "!defined(PART_7) && !defined(PART_8)" + "#if !defined(PART_1) && !defined(PART_2) && " + "!defined(PART_3) && !defined(PART_4) && " + "!defined(PART_5) && !defined(PART_6) && " + "!defined(PART_7) && !defined(PART_8)" "\n" "#define PART_1 1\n" "#define PART_2 1\n" @@ -2673,8 +2497,8 @@ static void generate_func (void) "#define PART_7 1\n" "#define PART_8 1\n" "#endif\n\n"); + rp = 0; - n_cpustbl = 0; for(j=1;j<=8;++j) { int k = (j*nr_cpuop_funcs)/8; printf ("#ifdef PART_%d\n",j); @@ -2682,89 +2506,14 @@ static void generate_func (void) generate_one_opcode (rp); printf ("#endif\n\n"); } + fprintf (stblfile, "{ 0, 0, 0 }};\n"); } } -static struct { - const char *handler; - const char *name; -} cpufunctbl[65536]; -static char const op_illg_1[] = "op_illg_1"; -static char const illegal[] = "ILLEGAL"; - -static void generate_functbl (void) -{ - int i; - unsigned int opcode; - int cpu_level = 4; - struct gencputbl *tbl = cpustbl; - - for (opcode = 0; opcode < 65536; opcode++) - { - cpufunctbl[opcode].handler = op_illg_1; - cpufunctbl[opcode].name = illegal; - } - for (i = 0; i < n_cpustbl; i++) - { - if (! tbl[i].specific) - { - cpufunctbl[tbl[i].opcode].handler = tbl[i].handler; - cpufunctbl[tbl[i].opcode].name = lookuptab[tbl[i].namei].name; - } - } - for (opcode = 0; opcode < 65536; opcode++) - { - const char *f; - - if (table68k[opcode].mnemo == i_ILLG || (unsigned)table68k[opcode].clev > (unsigned)cpu_level) - continue; - - if (table68k[opcode].handler != -1) - { - f = cpufunctbl[table68k[opcode].handler].handler; - if (f == op_illg_1) - abort(); - cpufunctbl[opcode].handler = f; - cpufunctbl[opcode].name = cpufunctbl[table68k[opcode].handler].name; - } - } - for (i = 0; i < n_cpustbl; i++) - { - if (tbl[i].specific) - { - cpufunctbl[tbl[i].opcode].handler = tbl[i].handler; - cpufunctbl[tbl[i].opcode].name = lookuptab[tbl[i].namei].name; - } - } - - fprintf(functblfile, "\n"); - fprintf(functblfile, "cpuop_func *cpufunctbl[65536] = {\n"); - fprintf(functblfile, "#if !defined(HAVE_GET_WORD_UNSWAPPED) || defined(FULLMMU)\n"); - for (opcode = 0; opcode < 65536; opcode++) - { - fprintf(functblfile, "\t%s%s /* %s */\n", cpufunctbl[opcode].handler, opcode < 65535 ? "," : "", cpufunctbl[opcode].name); - } - fprintf(functblfile, "#else\n"); - for (opcode = 0; opcode < 65536; opcode++) - { - unsigned int map = do_byteswap_16(opcode); - fprintf(functblfile, "\t%s%s /* %s */\n", cpufunctbl[map].handler, opcode < 65535 ? "," : "", cpufunctbl[map].name); - } - fprintf(functblfile, "#endif\n"); - fprintf(functblfile, "};\n"); -} - -#if (defined(OS_cygwin) || defined(OS_mingw)) && defined(EXTENDED_SIGSEGV) -void cygwin_mingw_abort() -{ -#undef abort - abort(); -} -#endif - -int main () +int main (int argc, char **argv) { + FILE *out; read_table68k (); do_merges (); @@ -2778,28 +2527,32 @@ int main () * cputbl.h that way), but cpuopti can't cope. That could be fixed, but * I don't dare to touch the 68k version. */ - if ((headerfile = fopen ("cputbl.h", "wb")) == NULL) - abort(); - if ((stblfile = fopen ("cpustbl.cpp", "wb")) == NULL) - abort(); - if ((functblfile = fopen ("cpufunctbl.cpp", "wb")) == NULL) - abort(); - if (freopen ("cpuemu.cpp", "wb", stdout) == NULL) - abort(); + headerfile = fopen ("cputbl.h", "w"); + stblfile = fopen ("cpustbl.cpp", "w"); + out = freopen ("cpuemu.cpp", "w", stdout); generate_includes (stdout); - fprintf(stdout, "#ifdef HAVE_CFLAG_NO_REDZONE\n"); - fprintf(stdout, "#ifndef NOFLAGS\n"); - fprintf(stdout, "#pragma GCC option \"-mno-red-zone\"\n"); - fprintf(stdout, "#endif\n"); - fprintf(stdout, "#endif\n"); generate_includes (stblfile); - generate_includes (functblfile); + generate_func (); - generate_functbl (); + free (table68k); - fclose(headerfile); - fclose(stblfile); - fclose(functblfile); + fclose (headerfile); + fclose (stblfile); + fflush (out); + + /* For build systems (IDEs mainly) that don't make it easy to compile the + * same file twice with different settings. */ + stblfile = fopen ("cpustbl_nf.cpp", "w"); + out = freopen ("cpuemu_nf.cpp", "w", stdout); + + fprintf (stblfile, "#define NOFLAGS\n"); + fprintf (stblfile, "#include \"cpustbl.cpp\"\n"); + fclose (stblfile); + + printf ("#define NOFLAGS\n"); + printf ("#include \"cpuemu.cpp\"\n"); + fflush (out); + return 0; } diff --git a/BasiliskII/src/uae_cpu/m68k.h b/BasiliskII/src/uae_cpu/m68k.h index dc79136b..f329cb3e 100644 --- a/BasiliskII/src/uae_cpu/m68k.h +++ b/BasiliskII/src/uae_cpu/m68k.h @@ -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 +#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 */ diff --git a/BasiliskII/src/uae_cpu/memory-uae.h b/BasiliskII/src/uae_cpu/memory-uae.h deleted file mode 100644 index c93aeb37..00000000 --- a/BasiliskII/src/uae_cpu/memory-uae.h +++ /dev/null @@ -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 - -// 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: -*/ diff --git a/BasiliskII/src/uae_cpu/memory.cpp b/BasiliskII/src/uae_cpu/memory.cpp index e56f993d..7483f506 100644 --- a/BasiliskII/src/uae_cpu/memory.cpp +++ b/BasiliskII/src/uae_cpu/memory.cpp @@ -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 +#include #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 */ diff --git a/BasiliskII/src/uae_cpu/memory.h b/BasiliskII/src/uae_cpu/memory.h index f7bab41d..26b3c5f1 100644 --- a/BasiliskII/src/uae_cpu/memory.h +++ b/BasiliskII/src/uae_cpu/memory.h @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/newcpu.cpp b/BasiliskII/src/uae_cpu/newcpu.cpp index ac1505f5..e9d0b88d 100644 --- a/BasiliskII/src/uae_cpu/newcpu.cpp +++ b/BasiliskII/src/uae_cpu/newcpu.cpp @@ -1,74 +1,51 @@ /* - * newcpu.cpp - CPU emulation + * UAE - The Un*x Amiga Emulator * - * Copyright (c) 2010 ARAnyM dev team (see AUTHORS) - * + * MC68000 emulation * - * Inspired by Christian Bauer's Basilisk II + * (c) 1995 Bernd Schmidt * - * 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 + * 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 - * - * (c) 1995 Bernd Schmidt - */ + +#include +#include +#include #include "sysdeps.h" -#include #include "cpu_emulation.h" #include "main.h" #include "emul_op.h" + +extern int intlev(void); // From baisilisk_glue.cpp + #include "m68k.h" #include "memory.h" #include "readcpu.h" #include "newcpu.h" -#ifdef USE_JIT -# include "compiler/compemu.h" -#endif +#include "compiler/compemu.h" #include "fpu/fpu.h" -#include "cpummu.h" -// #include "natfeats.h" -// #include "disasm-glue.h" -#include - -#define DEBUG 0 -#include "debug.h" - -#define SANITY_CHECK_ATC 1 - -struct fixup fixup = {0, 0, 0}; - -int quit_program = 0; - -// For instruction $7139 -bool cpu_debugging = false; +#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) +B2_mutex *spcflags_lock = NULL; +#endif +bool quit_program = false; struct flag_struct regflags; -/* LongJump buffers */ -#ifdef EXCEPTIONS_VIA_LONGJMP -JMP_BUF excep_env; -#endif /* Opcode of faulting instruction */ uae_u16 last_op_for_exception_3; /* PC at fault time */ @@ -83,34 +60,19 @@ int movem_index1[256]; int movem_index2[256]; int movem_next[256]; -#ifdef FLIGHT_RECORDER - -// feel free to edit the following defines to customize the dump -#define FRLOG_HOTKEY 1 /* 1 = dump only when hotkey is held down */ -#define FRLOG_ALL 1 /* 1 = dump continuously to ever growing log */ -#define FRLOG_IRQ 0 /* 1 = dump also CPU in interrupts */ -#define FRLOG_REGS 0 /* 1 = dump also all data/address registers */ -#define FRLOG_SIZE 8192 /* this many instructions in single dump */ +cpuop_func *cpufunctbl[65536]; +#if FLIGHT_RECORDER struct rec_step { + uae_u32 pc; +#if FLIGHT_RECORDER >= 2 uae_u32 d[8]; uae_u32 a[8]; - uae_u32 pc; - uae_u16 sr; - uae_u32 usp; - uae_u32 msp; - uae_u32 isp; - uae_u16 instr; +#endif }; -bool cpu_flight_recorder_active = false; - -#if FRLOG_ALL -const int LOG_SIZE = 10; -#else -const int LOG_SIZE = FRLOG_SIZE; -#endif -static rec_step frlog[LOG_SIZE]; +const int LOG_SIZE = 32768; +static rec_step log[LOG_SIZE]; static int log_ptr = -1; // First time initialization static const char *log_filename(void) @@ -119,580 +81,848 @@ static const char *log_filename(void) return name ? name : "log.68k"; } -void dump_flight_recorder(void) +void m68k_record_step(uaecptr pc) { -#if FRLOG_ALL - FILE *f = fopen(log_filename(), "a"); -#else - FILE *f = fopen(log_filename(), "w"); +#if FLIGHT_RECORDER >= 2 + /* XXX: if LSB is set, we are recording from generated code and we + don't support registers recording yet. */ + if ((pc & 1) == 0) { + for (int i = 0; i < 8; i++) { + log[log_ptr].d[i] = m68k_dreg(regs, i); + log[log_ptr].a[i] = m68k_areg(regs, i); + } + } #endif + log[log_ptr].pc = pc; + log_ptr = (log_ptr + 1) % LOG_SIZE; +} + +static void dump_log(void) +{ + FILE *f = fopen(log_filename(), "w"); if (f == NULL) return; for (int i = 0; i < LOG_SIZE; i++) { int j = (i + log_ptr) % LOG_SIZE; - fprintf(f, "pc %08x instr %04x sr %04x usp %08x msp %08x isp %08x\n", frlog[j].pc, frlog[j].instr, frlog[j].sr, frlog[j].usp, frlog[j].msp, frlog[j].isp); - // adding a simple opcode -> assembler conversion table would help -#if FRLOG_REGS - fprintf(f, "d0 %08x d1 %08x d2 %08x d3 %08x\n", frlog[j].d[0], frlog[j].d[1], frlog[j].d[2], frlog[j].d[3]); - fprintf(f, "d4 %08x d5 %08x d6 %08x d7 %08x\n", frlog[j].d[4], frlog[j].d[5], frlog[j].d[6], frlog[j].d[7]); - fprintf(f, "a0 %08x a1 %08x a2 %08x a3 %08x\n", frlog[j].a[0], frlog[j].a[1], frlog[j].a[2], frlog[j].a[3]); - fprintf(f, "a4 %08x a5 %08x a6 %08x a7 %08x\n", frlog[j].a[4], frlog[j].a[5], frlog[j].a[6], frlog[j].a[7]); + uae_u32 pc = log[j].pc & ~1; + fprintf(f, "pc %08x", pc); +#if FLIGHT_RECORDER >= 2 + fprintf(f, "\n"); + if ((log[j].pc & 1) == 0) { + fprintf(f, "d0 %08x d1 %08x d2 %08x d3 %08x\n", log[j].d[0], log[j].d[1], log[j].d[2], log[j].d[3]); + fprintf(f, "d4 %08x d5 %08x d6 %08x d7 %08x\n", log[j].d[4], log[j].d[5], log[j].d[6], log[j].d[7]); + fprintf(f, "a0 %08x a1 %08x a2 %08x a3 %08x\n", log[j].a[0], log[j].a[1], log[j].a[2], log[j].a[3]); + fprintf(f, "a4 %08x a5 %08x a6 %08x a7 %08x\n", log[j].a[4], log[j].a[5], log[j].a[6], log[j].a[7]); + } +#else + fprintf(f, " | "); +#endif +#if ENABLE_MON + disass_68k(f, pc); #endif } fclose(f); } +#endif -void m68k_record_step(uaecptr pc, int opcode) +#if ENABLE_MON +static void dump_regs(void) { - static bool last_state = false; - -#if FRLOG_HOTKEY - if (! cpu_flight_recorder_active) { - if (last_state) { - // dump log out - dump_flight_recorder(); - - // remember last state - last_state = false; - } - return; - } -#endif - - if (! last_state) { - // reset old log - log_ptr = 0; - memset(frlog, 0, sizeof(frlog)); - // remember last state - last_state = true; - } - -#if FRLOG_REGS - for (int i = 0; i < 8; i++) { - frlog[log_ptr].d[i] = m68k_dreg(regs, i); - frlog[log_ptr].a[i] = m68k_areg(regs, i); - } -#endif - frlog[log_ptr].pc = pc; - - MakeSR(); -#if ! FRLOG_IRQ - // is CPU in interrupt handler? Quit if should not be logged. - if (regs.s && !regs.m) return; -#endif - frlog[log_ptr].sr = regs.sr; - frlog[log_ptr].usp = regs.usp; - frlog[log_ptr].msp = regs.msp; - frlog[log_ptr].isp = regs.isp; - frlog[log_ptr].instr = opcode; - - log_ptr = (log_ptr + 1) % LOG_SIZE; -#if FRLOG_ALL - if (log_ptr == 0) dump_flight_recorder(); -#endif + m68k_dumpstate(NULL); } -#endif /* FLIGHT_RECORDER */ +#endif + +#define COUNT_INSTRS 0 + +#if COUNT_INSTRS +static unsigned long int instrcount[65536]; +static uae_u16 opcodenums[65536]; + +static int compfn (const void *el1, const void *el2) +{ + return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2]; +} + +static char *icountfilename (void) +{ + char *name = getenv ("INSNCOUNT"); + if (name) + return name; + return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount"; +} + +void dump_counts (void) +{ + FILE *f = fopen (icountfilename (), "w"); + unsigned long int total; + int i; + + write_log ("Writing instruction count file...\n"); + for (i = 0; i < 65536; i++) { + opcodenums[i] = i; + total += instrcount[i]; + } + qsort (opcodenums, 65536, sizeof(uae_u16), compfn); + + fprintf (f, "Total: %lu\n", total); + for (i=0; i < 65536; i++) { + unsigned long int cnt = instrcount[opcodenums[i]]; + struct instr *dp; + struct mnemolookup *lookup; + if (!cnt) + break; + dp = table68k + opcodenums[i]; + for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) + ; + fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name); + } + fclose (f); +} +#else +void dump_counts (void) +{ +} +#endif int broken_in; -static inline unsigned int cft_map (unsigned int f) +static __inline__ unsigned int cft_map (unsigned int f) { -#if !defined(HAVE_GET_WORD_UNSWAPPED) || defined(FULLMMU) - return f; +#ifndef HAVE_GET_WORD_UNSWAPPED + return f; #else - return do_byteswap_16(f); + return ((f >> 8) & 255) | ((f & 255) << 8); #endif } +void REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM; + void REGPARAM2 op_illg_1 (uae_u32 opcode) { - op_illg (cft_map (opcode)); + op_illg (cft_map (opcode)); } +static void build_cpufunctbl (void) +{ + int i; + unsigned long opcode; + unsigned int cpu_level = 0; // 68000 (default) + if (CPUType == 4) + cpu_level = 4; // 68040 with FPU + else { + if (FPUType) + cpu_level = 3; // 68020 with FPU + else if (CPUType >= 2) + cpu_level = 2; // 68020 + else if (CPUType == 1) + cpu_level = 1; + } + struct cputbl *tbl = ( + cpu_level == 4 ? op_smalltbl_0_ff + : cpu_level == 3 ? op_smalltbl_1_ff + : cpu_level == 2 ? op_smalltbl_2_ff + : cpu_level == 1 ? op_smalltbl_3_ff + : op_smalltbl_4_ff); + + for (opcode = 0; opcode < 65536; opcode++) + cpufunctbl[cft_map (opcode)] = op_illg_1; + for (i = 0; tbl[i].handler != NULL; i++) { + if (! tbl[i].specific) + cpufunctbl[cft_map (tbl[i].opcode)] = tbl[i].handler; + } + for (opcode = 0; opcode < 65536; opcode++) { + cpuop_func *f; + + if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level) + continue; + + if (table68k[opcode].handler != -1) { + f = cpufunctbl[cft_map (table68k[opcode].handler)]; + if (f == op_illg_1) + abort(); + cpufunctbl[cft_map (opcode)] = f; + } + } + for (i = 0; tbl[i].handler != NULL; i++) { + if (tbl[i].specific) + cpufunctbl[cft_map (tbl[i].opcode)] = tbl[i].handler; + } +} void init_m68k (void) { - int i; + int i; - for (i = 0 ; i < 256 ; i++) { - int j; - for (j = 0 ; j < 8 ; j++) { - if (i & (1 << j)) break; + for (i = 0 ; i < 256 ; i++) { + int j; + for (j = 0 ; j < 8 ; j++) { + if (i & (1 << j)) break; + } + movem_index1[i] = j; + movem_index2[i] = 7-j; + movem_next[i] = i & (~(1 << j)); + } +#if COUNT_INSTRS + { + FILE *f = fopen (icountfilename (), "r"); + memset (instrcount, 0, sizeof instrcount); + if (f) { + uae_u32 opcode, count, total; + char name[20]; + write_log ("Reading instruction count file...\n"); + fscanf (f, "Total: %lu\n", &total); + while (fscanf (f, "%lx: %lu %s\n", &opcode, &count, name) == 3) { + instrcount[opcode] = count; + } + fclose(f); + } } - movem_index1[i] = j; - movem_index2[i] = 7-j; - movem_next[i] = i & (~(1 << j)); - } -#ifdef USE_JIT - /* still needed by build_comp(); FIXME */ - read_table68k (); - do_merges (); #endif - fpu_init (CPUType == 4); + read_table68k (); + do_merges (); + + build_cpufunctbl (); + +#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) + spcflags_lock = B2_create_mutex(); +#endif + fpu_init(CPUType == 4); } void exit_m68k (void) { fpu_exit (); - - free(table68k); - table68k = NULL; +#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS) + B2_delete_mutex(spcflags_lock); +#endif } struct regstruct regs, lastint_regs; -// MJ static struct regstruct regs_backup[16]; -// MJ static int backup_pointer = 0; +static struct regstruct regs_backup[16]; +static int backup_pointer = 0; +static long int m68kpc_offset; int lastint_no; - -#ifdef FULLMMU -static inline uae_u8 get_ibyte_1(uae_u32 o) -{ - return get_ibyte(o); -} -static inline uae_u16 get_iword_1(uae_u32 o) -{ - return get_iword(o); -} -static inline uae_u32 get_ilong_1(uae_u32 o) -{ - return get_ilong(o); -} +#if REAL_ADDRESSING || DIRECT_ADDRESSING +#define get_ibyte_1(o) get_byte(get_virtual_address(regs.pc_p) + (o) + 1) +#define get_iword_1(o) get_word(get_virtual_address(regs.pc_p) + (o)) +#define get_ilong_1(o) get_long(get_virtual_address(regs.pc_p) + (o)) #else -# define get_ibyte_1(o) get_byte(m68k_getpc() + (o) + 1) -# define get_iword_1(o) get_word(m68k_getpc() + (o)) -# define get_ilong_1(o) get_long(m68k_getpc() + (o)) +#define get_ibyte_1(o) get_byte(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1) +#define get_iword_1(o) get_word(regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) +#define get_ilong_1(o) get_long(regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) #endif -/* - * extract bitfield data from memory and return it in the MSBs - * bdata caches the unmodified data for put_bitfield() - */ -uae_u32 get_bitfield(uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) +uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf) { - uae_u32 tmp, res, mask; + uae_u16 dp; + uae_s8 disp8; + uae_s16 disp16; + int r; + uae_u32 dispreg; + uaecptr addr; + uae_s32 offset = 0; + char buffer[80]; - offset &= 7; - mask = 0xffffffffu << (32 - width); - switch ((offset + width + 7) >> 3) { - case 1: - tmp = get_byte(src); - res = tmp << (24 + offset); - bdata[0] = tmp & ~(mask >> (24 + offset)); + switch (mode){ + case Dreg: + sprintf (buffer,"D%d", reg); break; - case 2: - tmp = get_word(src); - res = tmp << (16 + offset); - bdata[0] = tmp & ~(mask >> (16 + offset)); + case Areg: + sprintf (buffer,"A%d", reg); break; - case 3: - tmp = get_word(src); - res = tmp << (16 + offset); - bdata[0] = tmp & ~(mask >> (16 + offset)); - tmp = get_byte(src + 2); - res |= tmp << (8 + offset); - bdata[1] = tmp & ~(mask >> (8 + offset)); + case Aind: + sprintf (buffer,"(A%d)", reg); break; - case 4: - tmp = get_long(src); - res = tmp << offset; - bdata[0] = tmp & ~(mask >> offset); + case Aipi: + sprintf (buffer,"(A%d)+", reg); break; - case 5: - tmp = get_long(src); - res = tmp << offset; - bdata[0] = tmp & ~(mask >> offset); - tmp = get_byte(src + 4); - res |= tmp >> (8 - offset); - bdata[1] = tmp & ~(mask << (8 - offset)); + case Apdi: + sprintf (buffer,"-(A%d)", reg); + break; + case Ad16: + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + addr = m68k_areg(regs,reg) + (uae_s16)disp16; + sprintf (buffer,"(A%d,$%04x) == $%08lx", reg, disp16 & 0xffff, + (unsigned long)addr); + break; + case Ad8r: + dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + disp8 = dp & 0xFF; + r = (dp & 0x7000) >> 12; + dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r); + if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); + dispreg <<= (dp >> 9) & 3; + + if (dp & 0x100) { + uae_s32 outer = 0, disp = 0; + uae_s32 base = m68k_areg(regs,reg); + char name[10]; + sprintf (name,"A%d, ",reg); + if (dp & 0x80) { base = 0; name[0] = 0; } + if (dp & 0x40) dispreg = 0; + if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } + if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } + base += disp; + + if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } + if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } + + if (!(dp & 4)) base += dispreg; + if (dp & 3) base = get_long (base); + if (dp & 4) base += dispreg; + + addr = base + outer; + sprintf (buffer,"(%s%c%d.%c*%d+%d)+%d == $%08lx", name, + dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', + 1 << ((dp >> 9) & 3), + disp,outer, + (unsigned long)addr); + } else { + addr = m68k_areg(regs,reg) + (uae_s32)((uae_s8)disp8) + dispreg; + sprintf (buffer,"(A%d, %c%d.%c*%d, $%02x) == $%08lx", reg, + dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', + 1 << ((dp >> 9) & 3), disp8, + (unsigned long)addr); + } + break; + case PC16: + addr = m68k_getpc () + m68kpc_offset; + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + addr += (uae_s16)disp16; + sprintf (buffer,"(PC,$%04x) == $%08lx", disp16 & 0xffff,(unsigned long)addr); + break; + case PC8r: + addr = m68k_getpc () + m68kpc_offset; + dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + disp8 = dp & 0xFF; + r = (dp & 0x7000) >> 12; + dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r); + if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); + dispreg <<= (dp >> 9) & 3; + + if (dp & 0x100) { + uae_s32 outer = 0,disp = 0; + uae_s32 base = addr; + char name[10]; + sprintf (name,"PC, "); + if (dp & 0x80) { base = 0; name[0] = 0; } + if (dp & 0x40) dispreg = 0; + if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } + if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } + base += disp; + + if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } + if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } + + if (!(dp & 4)) base += dispreg; + if (dp & 3) base = get_long (base); + if (dp & 4) base += dispreg; + + addr = base + outer; + sprintf (buffer,"(%s%c%d.%c*%d+%d)+%d == $%08lx", name, + dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', + 1 << ((dp >> 9) & 3), + disp,outer, + (unsigned long)addr); + } else { + addr += (uae_s32)((uae_s8)disp8) + dispreg; + sprintf (buffer,"(PC, %c%d.%c*%d, $%02x) == $%08lx", dp & 0x8000 ? 'A' : 'D', + (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3), + disp8, (unsigned long)addr); + } + break; + case absw: + sprintf (buffer,"$%08lx", (unsigned long)(uae_s32)(uae_s16)get_iword_1 (m68kpc_offset)); + m68kpc_offset += 2; + break; + case absl: + sprintf (buffer,"$%08lx", (unsigned long)get_ilong_1 (m68kpc_offset)); + m68kpc_offset += 4; + break; + case imm: + switch (size){ + case sz_byte: + sprintf (buffer,"#$%02x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xff)); + m68kpc_offset += 2; + break; + case sz_word: + sprintf (buffer,"#$%04x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xffff)); + m68kpc_offset += 2; + break; + case sz_long: + sprintf (buffer,"#$%08lx", (unsigned long)(get_ilong_1 (m68kpc_offset))); + m68kpc_offset += 4; + break; + default: + break; + } + break; + case imm0: + offset = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset); + m68kpc_offset += 2; + sprintf (buffer,"#$%02x", (unsigned int)(offset & 0xff)); + break; + case imm1: + offset = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); + m68kpc_offset += 2; + sprintf (buffer,"#$%04x", (unsigned int)(offset & 0xffff)); + break; + case imm2: + offset = (uae_s32)get_ilong_1 (m68kpc_offset); + m68kpc_offset += 4; + sprintf (buffer,"#$%08lx", (unsigned long)offset); + break; + case immi: + offset = (uae_s32)(uae_s8)(reg & 0xff); + sprintf (buffer,"#$%08lx", (unsigned long)offset); break; default: - /* Panic? */ - res = 0; break; } - return res; + if (buf == 0) + printf ("%s", buffer); + else + strcat (buf, buffer); + return offset; } -/* - * write bitfield data (in the LSBs) back to memory, upper bits - * must be cleared already. - */ -void put_bitfield(uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width) +/* The plan is that this will take over the job of exception 3 handling - + * the CPU emulation functions will just do a longjmp to m68k_go whenever + * they hit an odd address. */ +static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val) { - offset = (offset & 7) + width; - switch ((offset + 7) >> 3) { - case 1: - put_byte(dst, bdata[0] | (val << (8 - offset))); + uae_u16 dp; + uae_s8 disp8; + uae_s16 disp16; + int r; + uae_u32 dispreg; + uaecptr addr; + uae_s32 offset = 0; + + switch (mode){ + case Dreg: + *val = m68k_dreg (regs, reg); + return 1; + case Areg: + *val = m68k_areg (regs, reg); + return 1; + + case Aind: + case Aipi: + addr = m68k_areg (regs, reg); break; - case 2: - put_word(dst, bdata[0] | (val << (16 - offset))); + case Apdi: + addr = m68k_areg (regs, reg); break; - case 3: - put_word(dst, bdata[0] | (val >> (offset - 16))); - put_byte(dst + 2, bdata[1] | (val << (24 - offset))); + case Ad16: + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + addr = m68k_areg(regs,reg) + (uae_s16)disp16; break; - case 4: - put_long(dst, bdata[0] | (val << (32 - offset))); + case Ad8r: + addr = m68k_areg (regs, reg); +d8r_common: + dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + disp8 = dp & 0xFF; + r = (dp & 0x7000) >> 12; + dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r); + if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg); + dispreg <<= (dp >> 9) & 3; + + if (dp & 0x100) { + uae_s32 outer = 0, disp = 0; + uae_s32 base = addr; + if (dp & 0x80) base = 0; + if (dp & 0x40) dispreg = 0; + if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } + if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } + base += disp; + + if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; } + if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; } + + if (!(dp & 4)) base += dispreg; + if (dp & 3) base = get_long (base); + if (dp & 4) base += dispreg; + + addr = base + outer; + } else { + addr += (uae_s32)((uae_s8)disp8) + dispreg; + } break; - case 5: - put_long(dst, bdata[0] | (val >> (offset - 32))); - put_byte(dst + 4, bdata[1] | (val << (40 - offset))); + case PC16: + addr = m68k_getpc () + m68kpc_offset; + disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; + addr += (uae_s16)disp16; + break; + case PC8r: + addr = m68k_getpc () + m68kpc_offset; + goto d8r_common; + case absw: + addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); + m68kpc_offset += 2; + break; + case absl: + addr = get_ilong_1 (m68kpc_offset); + m68kpc_offset += 4; + break; + case imm: + switch (size){ + case sz_byte: + *val = get_iword_1 (m68kpc_offset) & 0xff; + m68kpc_offset += 2; + break; + case sz_word: + *val = get_iword_1 (m68kpc_offset) & 0xffff; + m68kpc_offset += 2; + break; + case sz_long: + *val = get_ilong_1 (m68kpc_offset); + m68kpc_offset += 4; + break; + default: + break; + } + return 1; + case imm0: + *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset); + m68kpc_offset += 2; + return 1; + case imm1: + *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); + m68kpc_offset += 2; + return 1; + case imm2: + *val = get_ilong_1 (m68kpc_offset); + m68kpc_offset += 4; + return 1; + case immi: + *val = (uae_s32)(uae_s8)(reg & 0xff); + return 1; + default: + addr = 0; break; } + if ((addr & 1) == 0) + return 1; + + last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset; + last_fault_for_exception_3 = addr; + return 0; } uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp) { - int reg = (dp >> 12) & 15; - uae_s32 regd = regs.regs[reg]; - if ((dp & 0x800) == 0) - regd = (uae_s32)(uae_s16)regd; - regd <<= (dp >> 9) & 3; - if (dp & 0x100) { - uae_s32 outer = 0; - if (dp & 0x80) base = 0; - if (dp & 0x40) regd = 0; + int reg = (dp >> 12) & 15; + uae_s32 regd = regs.regs[reg]; + if ((dp & 0x800) == 0) + regd = (uae_s32)(uae_s16)regd; + regd <<= (dp >> 9) & 3; + if (dp & 0x100) { + uae_s32 outer = 0; + if (dp & 0x80) base = 0; + if (dp & 0x40) regd = 0; - if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16)next_iword(); - if ((dp & 0x30) == 0x30) base += next_ilong(); + if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16)next_iword(); + if ((dp & 0x30) == 0x30) base += next_ilong(); - if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)next_iword(); - if ((dp & 0x3) == 0x3) outer = next_ilong(); + if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)next_iword(); + if ((dp & 0x3) == 0x3) outer = next_ilong(); - if ((dp & 0x4) == 0) base += regd; - if (dp & 0x3) base = get_long (base); - if (dp & 0x4) base += regd; + if ((dp & 0x4) == 0) base += regd; + if (dp & 0x3) base = get_long (base); + if (dp & 0x4) base += regd; - return base + outer; - } else { - return base + (uae_s32)((uae_s8)dp) + regd; - } + return base + outer; + } else { + return base + (uae_s32)((uae_s8)dp) + regd; + } } uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp) { - int reg = (dp >> 12) & 15; - uae_s32 regd = regs.regs[reg]; + int reg = (dp >> 12) & 15; + uae_s32 regd = regs.regs[reg]; #if 1 - if ((dp & 0x800) == 0) - regd = (uae_s32)(uae_s16)regd; - return base + (uae_s8)dp + regd; + if ((dp & 0x800) == 0) + regd = (uae_s32)(uae_s16)regd; + return base + (uae_s8)dp + regd; #else - /* Branch-free code... benchmark this again now that - * things are no longer inline. */ - uae_s32 regd16; - uae_u32 mask; - mask = ((dp & 0x800) >> 11) - 1; - regd16 = (uae_s32)(uae_s16)regd; - regd16 &= mask; - mask = ~mask; - base += (uae_s8)dp; - regd &= mask; - regd |= regd16; - return base + regd; + /* Branch-free code... benchmark this again now that + * things are no longer inline. */ + uae_s32 regd16; + uae_u32 mask; + mask = ((dp & 0x800) >> 11) - 1; + regd16 = (uae_s32)(uae_s16)regd; + regd16 &= mask; + mask = ~mask; + base += (uae_s8)dp; + regd &= mask; + regd |= regd16; + return base + regd; #endif } void MakeSR (void) { #if 0 - assert((regs.t1 & 1) == regs.t1); - assert((regs.t0 & 1) == regs.t0); - assert((regs.s & 1) == regs.s); - assert((regs.m & 1) == regs.m); - assert((XFLG & 1) == XFLG); - assert((NFLG & 1) == NFLG); - assert((ZFLG & 1) == ZFLG); - assert((VFLG & 1) == VFLG); - assert((CFLG & 1) == CFLG); + assert((regs.t1 & 1) == regs.t1); + assert((regs.t0 & 1) == regs.t0); + assert((regs.s & 1) == regs.s); + assert((regs.m & 1) == regs.m); + assert((XFLG & 1) == XFLG); + assert((NFLG & 1) == NFLG); + assert((ZFLG & 1) == ZFLG); + assert((VFLG & 1) == VFLG); + assert((CFLG & 1) == CFLG); #endif - regs.sr = ((regs.t1 << 15) | (regs.t0 << 14) - | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8) - | (GET_XFLG << 4) | (GET_NFLG << 3) | (GET_ZFLG << 2) | (GET_VFLG << 1) - | GET_CFLG); + regs.sr = ((regs.t1 << 15) | (regs.t0 << 14) + | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8) + | (GET_XFLG << 4) | (GET_NFLG << 3) | (GET_ZFLG << 2) | (GET_VFLG << 1) + | GET_CFLG); } void MakeFromSR (void) { - int oldm = regs.m; - int olds = regs.s; + int oldm = regs.m; + int olds = regs.s; - regs.t1 = (regs.sr >> 15) & 1; - regs.t0 = (regs.sr >> 14) & 1; - regs.s = (regs.sr >> 13) & 1; - mmu_set_super(regs.s); - regs.m = (regs.sr >> 12) & 1; - regs.intmask = (regs.sr >> 8) & 7; - SET_XFLG ((regs.sr >> 4) & 1); - SET_NFLG ((regs.sr >> 3) & 1); - SET_ZFLG ((regs.sr >> 2) & 1); - SET_VFLG ((regs.sr >> 1) & 1); - SET_CFLG (regs.sr & 1); - if (olds != regs.s) { - if (olds) { - if (oldm) - regs.msp = m68k_areg(regs, 7); - else - regs.isp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.usp; - } else { - regs.usp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; - } - } else if (olds && oldm != regs.m) { - if (oldm) { - regs.msp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.isp; - } else { - regs.isp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.msp; - } + regs.t1 = (regs.sr >> 15) & 1; + regs.t0 = (regs.sr >> 14) & 1; + regs.s = (regs.sr >> 13) & 1; + regs.m = (regs.sr >> 12) & 1; + regs.intmask = (regs.sr >> 8) & 7; + SET_XFLG ((regs.sr >> 4) & 1); + SET_NFLG ((regs.sr >> 3) & 1); + SET_ZFLG ((regs.sr >> 2) & 1); + SET_VFLG ((regs.sr >> 1) & 1); + SET_CFLG (regs.sr & 1); + if (CPUType >= 2) { + if (olds != regs.s) { + if (olds) { + if (oldm) + regs.msp = m68k_areg(regs, 7); + else + regs.isp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.usp; + } else { + regs.usp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; + } + } else if (olds && oldm != regs.m) { + if (oldm) { + regs.msp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.isp; + } else { + regs.isp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.msp; + } + } + } else { + if (olds != regs.s) { + if (olds) { + regs.isp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.usp; + } else { + regs.usp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.isp; + } + } } - SPCFLAGS_SET( SPCFLAG_INT ); - if (regs.t1 || regs.t0) - SPCFLAGS_SET( SPCFLAG_TRACE ); - else - SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + SPCFLAGS_SET( SPCFLAG_INT ); + if (regs.t1 || regs.t0) + SPCFLAGS_SET( SPCFLAG_TRACE ); + else + /* Keep SPCFLAG_DOTRACE, we still want a trace exception for + SR-modifying instructions (including STOP). */ + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); } -/* for building exception frames */ -static inline void exc_push_word(uae_u16 w) -{ - m68k_areg(regs, 7) -= 2; - put_word(m68k_areg(regs, 7), w); -} -static inline void exc_push_long(uae_u32 l) -{ - m68k_areg(regs, 7) -= 4; - put_long (m68k_areg(regs, 7), l); -} - -static inline void exc_make_frame( - int format, - uae_u16 sr, - uae_u32 currpc, - int nr, - uae_u32 x0, - uae_u32 x1 -) -{ - switch(format) { - case 4: - exc_push_long(x1); - exc_push_long(x0); - break; - case 3: - case 2: - exc_push_long(x0); - break; - } - - exc_push_word((format << 12) + (nr * 4)); /* format | vector */ - exc_push_long(currpc); - exc_push_word(sr); -} - -#ifdef EXCEPTIONS_VIA_LONGJMP -static int building_bus_fault_stack_frame=0; -#endif - void Exception(int nr, uaecptr oldpc) { - uae_u32 currpc = m68k_getpc (); - MakeSR(); - - if (fixup.flag) - { - m68k_areg(regs, fixup.reg) = fixup.value; - fixup.flag = 0; - } - - if (!regs.s) { - regs.usp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; - regs.s = 1; - mmu_set_super(1); - } - - if (nr == 2) { - /* BUS ERROR handler begins */ -#ifdef ENABLE_EPSLIMITER - check_eps_limit(currpc); -#endif - // panicbug("Exception Nr. %d CPC: %08lx NPC: %08lx SP=%08lx Addr: %08lx", nr, currpc, get_long (regs.vbr + 4*nr), m68k_areg(regs, 7), regs.mmu_fault_addr); - -#ifdef EXCEPTIONS_VIA_LONGJMP - if (!building_bus_fault_stack_frame) -#else - try -#endif - { -#ifdef EXCEPTIONS_VIA_LONGJMP - building_bus_fault_stack_frame= 1; -#endif - /* 68040 */ - exc_push_long(0); /* PD3 */ - exc_push_long(0); /* PD2 */ - exc_push_long(0); /* PD1 */ - exc_push_long(0); /* PD0/WB1D */ - exc_push_long(0); /* WB1A */ - exc_push_long(0); /* WB2D */ - exc_push_long(0); /* WB2A */ - exc_push_long(regs.wb3_data); /* WB3D */ - exc_push_long(regs.mmu_fault_addr); /* WB3A */ - exc_push_long(regs.mmu_fault_addr); - exc_push_word(0); /* WB1S */ - exc_push_word(0); /* WB2S */ - exc_push_word(regs.wb3_status); /* WB3S */ - regs.wb3_status = 0; - exc_push_word(regs.mmu_ssw); - exc_push_long(regs.mmu_fault_addr); /* EA */ - exc_make_frame(7, regs.sr, regs.fault_pc, 2, 0, 0); - + uae_u32 currpc = m68k_getpc (); + MakeSR(); + if (!regs.s) { + regs.usp = m68k_areg(regs, 7); + if (CPUType >= 2) + m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp; + else + m68k_areg(regs, 7) = regs.isp; + regs.s = 1; } -#ifdef EXCEPTIONS_VIA_LONGJMP - else -#else - catch (m68k_exception) -#endif - { - report_double_bus_error(); -#ifdef EXCEPTIONS_VIA_LONGJMP - building_bus_fault_stack_frame= 0; -#endif - return; - } - -#ifdef EXCEPTIONS_VIA_LONGJMP - building_bus_fault_stack_frame= 0; -#endif - /* end of BUS ERROR handler */ - } else if (nr == 3) { - exc_make_frame(2, regs.sr, last_addr_for_exception_3, nr, - last_fault_for_exception_3 & 0xfffffffe, 0); - } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) { - /* div by zero, CHK, TRAP or TRACE */ - exc_make_frame(2, regs.sr, currpc, nr, oldpc, 0); - } else if (regs.m && nr >= 24 && nr < 32) { - /* interrupts! */ - exc_make_frame(0, regs.sr, currpc, nr, 0, 0); - regs.sr |= (1 << 13); - regs.msp = m68k_areg(regs, 7); - m68k_areg(regs, 7) = regs.isp; - - exc_make_frame(1, /* throwaway */ - regs.sr, currpc, nr, 0, 0); - } else { - exc_make_frame(0, regs.sr, currpc, nr, 0, 0); - } - m68k_setpc (get_long (regs.vbr + 4*nr)); - SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE ); - fill_prefetch_0 (); - regs.t1 = regs.t0 = regs.m = 0; - SPCFLAGS_CLEAR(SPCFLAG_TRACE | SPCFLAG_DOTRACE); + if (CPUType > 0) { + if (nr == 2 || nr == 3) { + int i; + /* @@@ this is probably wrong (?) */ + for (i = 0 ; i < 12 ; i++) { + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), 0); + } + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), 0xa000 + nr * 4); + } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) { + m68k_areg(regs, 7) -= 4; + put_long (m68k_areg(regs, 7), oldpc); + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), 0x2000 + nr * 4); + } else if (regs.m && nr >= 24 && nr < 32) { + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), nr * 4); + m68k_areg(regs, 7) -= 4; + put_long (m68k_areg(regs, 7), currpc); + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), regs.sr); + regs.sr |= (1 << 13); + regs.msp = m68k_areg(regs, 7); + m68k_areg(regs, 7) = regs.isp; + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), 0x1000 + nr * 4); + } else { + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), nr * 4); + } + } else { + if (nr == 2 || nr == 3) { + m68k_areg(regs, 7) -= 12; + /* ??????? */ + if (nr == 3) { + put_long (m68k_areg(regs, 7), last_fault_for_exception_3); + put_word (m68k_areg(regs, 7)+4, last_op_for_exception_3); + put_long (m68k_areg(regs, 7)+8, last_addr_for_exception_3); + } + write_log ("Exception!\n"); + goto kludge_me_do; + } + } + m68k_areg(regs, 7) -= 4; + put_long (m68k_areg(regs, 7), currpc); +kludge_me_do: + m68k_areg(regs, 7) -= 2; + put_word (m68k_areg(regs, 7), regs.sr); + m68k_setpc (get_long (regs.vbr + 4*nr)); + SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE ); + fill_prefetch_0 (); + regs.t1 = regs.t0 = regs.m = 0; + SPCFLAGS_CLEAR( SPCFLAG_TRACE | SPCFLAG_DOTRACE ); } static void Interrupt(int nr) { - assert(nr < 8 && nr >= 0); - lastint_regs = regs; - lastint_no = nr; - Exception(nr+24, 0); + assert(nr < 8 && nr >= 0); + lastint_regs = regs; + lastint_no = nr; + Exception(nr+24, 0); - regs.intmask = nr; - SPCFLAGS_SET( SPCFLAG_INT ); + regs.intmask = nr; + SPCFLAGS_SET( SPCFLAG_INT ); } -static void SCCInterrupt(int nr) +static int caar, cacr, tc, itt0, itt1, dtt0, dtt1, mmusr, urp, srp; + +static int movec_illg (int regno) { - // fprintf(stderr, "CPU: in SCCInterrupt\n"); - lastint_regs = regs; - lastint_no = 5;// ex 5 - Exception(nr, 0); - - regs.intmask = 5;// ex 5 -} - -static void MFPInterrupt(int nr) -{ - // fprintf(stderr, "CPU: in MFPInterrupt\n"); - lastint_regs = regs; - lastint_no = 6; - Exception(nr, 0); - - regs.intmask = 6; + switch (CPUType) { + case 1: + if ((regno & 0x7ff) <= 1) + return 0; + break; + case 2: + case 3: + if ((regno & 0x7ff) <= 2) + return 0; + if (regno == 3 || regno == 4) + return 0; + break; + case 4: + if ((regno & 0x7ff) <= 7) { + if (regno != 0x802) + return 0; + } + break; + } + return 1; } int m68k_move2c (int regno, uae_u32 *regp) { - switch (regno) { - case 0: regs.sfc = *regp & 7; break; - case 1: regs.dfc = *regp & 7; break; - case 2: regs.cacr = *regp & 0x80008000; -#ifdef USE_JIT - set_cache_state(regs.cacr & 0x8000); - if (*regp & 0x08) { /* Just to be on the safe side */ - flush_icache(2); - } + if (movec_illg (regno)) { + op_illg (0x4E7B); + return 0; + } else { + switch (regno) { + case 0: regs.sfc = *regp & 7; break; + case 1: regs.dfc = *regp & 7; break; + case 2: + cacr = *regp & (CPUType < 4 ? 0x3 : 0x80008000); +#if USE_JIT + set_cache_state(regs.cacr & 0x8000); + if (*regp & 0x08) { /* Just to be on the safe side */ + flush_icache(2); + } #endif - break; - case 3: mmu_set_tc(*regp & 0xc000); break; - case 4: - case 5: - case 6: - case 7: mmu_set_ttr(regno, *regp & 0xffffe364); break; - case 0x800: regs.usp = *regp; break; - case 0x801: regs.vbr = *regp; break; - case 0x802: regs.caar = *regp & 0xfc; break; - case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break; - case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break; - case 0x805: mmu_set_mmusr(*regp); break; - case 0x806: regs.urp = *regp & MMU_ROOT_PTR_ADDR_MASK; break; - case 0x807: regs.srp = *regp & MMU_ROOT_PTR_ADDR_MASK; break; - default: - op_illg (0x4E7B); - return 0; + break; + case 3: tc = *regp & 0xc000; break; + case 4: itt0 = *regp & 0xffffe364; break; + case 5: itt1 = *regp & 0xffffe364; break; + case 6: dtt0 = *regp & 0xffffe364; break; + case 7: dtt1 = *regp & 0xffffe364; break; + case 0x800: regs.usp = *regp; break; + case 0x801: regs.vbr = *regp; break; + case 0x802: caar = *regp &0xfc; break; + case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break; + case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break; + case 0x805: mmusr = *regp; break; + case 0x806: urp = *regp; break; + case 0x807: srp = *regp; break; + default: + op_illg (0x4E7B); + return 0; + } } - return 1; + return 1; } int m68k_movec2 (int regno, uae_u32 *regp) { - switch (regno) { - case 0: *regp = regs.sfc; break; - case 1: *regp = regs.dfc; break; - case 2: *regp = regs.cacr; break; - case 3: *regp = regs.tc; break; - case 4: *regp = regs.itt0; break; - case 5: *regp = regs.itt1; break; - case 6: *regp = regs.dtt0; break; - case 7: *regp = regs.dtt1; break; - case 0x800: *regp = regs.usp; break; - case 0x801: *regp = regs.vbr; break; - case 0x802: *regp = regs.caar; break; - case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break; - case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break; - case 0x805: *regp = regs.mmusr; break; - case 0x806: *regp = regs.urp; break; - case 0x807: *regp = regs.srp; break; - default: - op_illg (0x4E7A); - return 0; + if (movec_illg (regno)) + { + op_illg (0x4E7A); + return 0; + } else { + switch (regno) { + case 0: *regp = regs.sfc; break; + case 1: *regp = regs.dfc; break; + case 2: *regp = cacr; break; + case 3: *regp = tc; break; + case 4: *regp = itt0; break; + case 5: *regp = itt1; break; + case 6: *regp = dtt0; break; + case 7: *regp = dtt1; break; + case 0x800: *regp = regs.usp; break; + case 0x801: *regp = regs.vbr; break; + case 0x802: *regp = caar; break; + case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break; + case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break; + case 0x805: *regp = mmusr; break; + case 0x806: *regp = urp; break; + case 0x807: *regp = srp; break; + default: + op_illg (0x4E7A); + return 0; + } } - return 1; + return 1; } -#if !defined(uae_s64) -static inline int +static __inline__ int div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem) { uae_u32 q = 0, cbit = 0; int i; if (div <= src_hi) { - return 1; + return 1; } for (i = 0 ; i < 32 ; i++) { cbit = src_hi & 0x80000000ul; @@ -709,131 +939,129 @@ div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem = src_hi; return 0; } -#endif -void m68k_divl (uae_u32 /*opcode*/, uae_u32 src, uae_u16 extra, uaecptr oldpc) +void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc) { #if defined(uae_s64) - if (src == 0) { - Exception (5, oldpc); - return; - } - if (extra & 0x800) { - /* signed variant */ - uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7); - uae_s64 quot, rem; + if (src == 0) { + Exception (5, oldpc); + return; + } + if (extra & 0x800) { + /* signed variant */ + uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7); + uae_s64 quot, rem; - if (extra & 0x400) { - a &= 0xffffffffu; - a |= (uae_s64)m68k_dreg(regs, extra & 7) << 32; - } - rem = a % (uae_s64)(uae_s32)src; - quot = a / (uae_s64)(uae_s32)src; - if ((quot & UVAL64(0xffffffff80000000)) != 0 - && (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000)) - { - SET_VFLG (1); - SET_NFLG (1); - SET_CFLG (0); + if (extra & 0x400) { + a &= 0xffffffffu; + a |= (uae_s64)m68k_dreg(regs, extra & 7) << 32; + } + rem = a % (uae_s64)(uae_s32)src; + quot = a / (uae_s64)(uae_s32)src; + if ((quot & UVAL64(0xffffffff80000000)) != 0 + && (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000)) + { + SET_VFLG (1); + SET_NFLG (1); + SET_CFLG (0); + } else { + if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem; + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (((uae_s32)quot) == 0); + SET_NFLG (((uae_s32)quot) < 0); + m68k_dreg(regs, extra & 7) = (uae_u32)rem; + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)quot; + } } else { - if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem; - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (((uae_s32)quot) == 0); - SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = rem; - m68k_dreg(regs, (extra >> 12) & 7) = quot; - } - } else { - /* unsigned */ - uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7); - uae_u64 quot, rem; + /* unsigned */ + uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7); + uae_u64 quot, rem; - if (extra & 0x400) { - a &= 0xffffffffu; - a |= (uae_u64)m68k_dreg(regs, extra & 7) << 32; + if (extra & 0x400) { + a &= 0xffffffffu; + a |= (uae_u64)m68k_dreg(regs, extra & 7) << 32; + } + rem = a % (uae_u64)src; + quot = a / (uae_u64)src; + if (quot > 0xffffffffu) { + SET_VFLG (1); + SET_NFLG (1); + SET_CFLG (0); + } else { + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (((uae_s32)quot) == 0); + SET_NFLG (((uae_s32)quot) < 0); + m68k_dreg(regs, extra & 7) = (uae_u32)rem; + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)quot; + } } - rem = a % (uae_u64)src; - quot = a / (uae_u64)src; - if (quot > 0xffffffffu) { - SET_VFLG (1); - SET_NFLG (1); - SET_CFLG (0); - } else { - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (((uae_s32)quot) == 0); - SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = rem; - m68k_dreg(regs, (extra >> 12) & 7) = quot; - } - } #else - if (src == 0) { - Exception (5, oldpc); - return; - } - if (extra & 0x800) { - /* signed variant */ - uae_s32 lo = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7); - uae_s32 hi = lo < 0 ? -1 : 0; - uae_s32 save_high; - uae_u32 quot, rem; - uae_u32 sign; + if (src == 0) { + Exception (5, oldpc); + return; + } + if (extra & 0x800) { + /* signed variant */ + uae_s32 lo = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7); + uae_s32 hi = lo < 0 ? -1 : 0; + uae_s32 save_high; + uae_u32 quot, rem; + uae_u32 sign; - if (extra & 0x400) { - hi = (uae_s32)m68k_dreg(regs, extra & 7); - } - save_high = hi; - sign = (hi ^ src); - if (hi < 0) { - hi = ~hi; - lo = -lo; - if (lo == 0) hi++; - } - if ((uae_s32)src < 0) src = -src; - if (div_unsigned(hi, lo, src, ", &rem) || - (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) { - SET_VFLG (1); - SET_NFLG (1); - SET_CFLG (0); + if (extra & 0x400) { + hi = (uae_s32)m68k_dreg(regs, extra & 7); + } + save_high = hi; + sign = (hi ^ src); + if (hi < 0) { + hi = ~hi; + lo = -lo; + if (lo == 0) hi++; + } + if ((uae_s32)src < 0) src = -src; + if (div_unsigned(hi, lo, src, ", &rem) || + (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) { + SET_VFLG (1); + SET_NFLG (1); + SET_CFLG (0); + } else { + if (sign & 0x80000000) quot = -quot; + if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem; + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (((uae_s32)quot) == 0); + SET_NFLG (((uae_s32)quot) < 0); + m68k_dreg(regs, extra & 7) = rem; + m68k_dreg(regs, (extra >> 12) & 7) = quot; + } } else { - if (sign & 0x80000000) quot = -quot; - if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem; - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (((uae_s32)quot) == 0); - SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = rem; - m68k_dreg(regs, (extra >> 12) & 7) = quot; - } - } else { - /* unsigned */ - uae_u32 lo = (uae_u32)m68k_dreg(regs, (extra >> 12) & 7); - uae_u32 hi = 0; - uae_u32 quot, rem; + /* unsigned */ + uae_u32 lo = (uae_u32)m68k_dreg(regs, (extra >> 12) & 7); + uae_u32 hi = 0; + uae_u32 quot, rem; - if (extra & 0x400) { - hi = (uae_u32)m68k_dreg(regs, extra & 7); + if (extra & 0x400) { + hi = (uae_u32)m68k_dreg(regs, extra & 7); + } + if (div_unsigned(hi, lo, src, ", &rem)) { + SET_VFLG (1); + SET_NFLG (1); + SET_CFLG (0); + } else { + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (((uae_s32)quot) == 0); + SET_NFLG (((uae_s32)quot) < 0); + m68k_dreg(regs, extra & 7) = rem; + m68k_dreg(regs, (extra >> 12) & 7) = quot; + } } - if (div_unsigned(hi, lo, src, ", &rem)) { - SET_VFLG (1); - SET_NFLG (1); - SET_CFLG (0); - } else { - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (((uae_s32)quot) == 0); - SET_NFLG (((uae_s32)quot) < 0); - m68k_dreg(regs, extra & 7) = rem; - m68k_dreg(regs, (extra >> 12) & 7) = quot; - } - } #endif } -#if !defined(uae_s64) -static inline void +static __inline__ void mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo) { uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff); @@ -851,314 +1079,164 @@ mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo) *dst_lo = lo; *dst_hi = r3; } -#endif -void m68k_mull (uae_u32 /*opcode*/, uae_u32 src, uae_u16 extra) +void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra) { #if defined(uae_s64) - if (extra & 0x800) { - /* signed variant */ - uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7); + if (extra & 0x800) { + /* signed variant */ + uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7); - a *= (uae_s64)(uae_s32)src; - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (a == 0); - SET_NFLG (a < 0); - if (extra & 0x400) - m68k_dreg(regs, extra & 7) = a >> 32; - else if ((a & UVAL64(0xffffffff80000000)) != 0 - && (a & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000)) - { - SET_VFLG (1); - } - m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a; - } else { - /* unsigned */ - uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7); + a *= (uae_s64)(uae_s32)src; + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (a == 0); + SET_NFLG (a < 0); + if (extra & 0x400) + m68k_dreg(regs, extra & 7) = a >> 32; + else if ((a & UVAL64(0xffffffff80000000)) != 0 + && (a & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000)) + { + SET_VFLG (1); + } + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a; + } else { + /* unsigned */ + uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7); - a *= (uae_u64)src; - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (a == 0); - SET_NFLG (((uae_s64)a) < 0); - if (extra & 0x400) - m68k_dreg(regs, extra & 7) = a >> 32; - else if ((a & UVAL64(0xffffffff00000000)) != 0) { - SET_VFLG (1); + a *= (uae_u64)src; + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (a == 0); + SET_NFLG (((uae_s64)a) < 0); + if (extra & 0x400) + m68k_dreg(regs, extra & 7) = a >> 32; + else if ((a & UVAL64(0xffffffff00000000)) != 0) { + SET_VFLG (1); + } + m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a; } - m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a; - } #else - if (extra & 0x800) { - /* signed variant */ - uae_s32 src1,src2; - uae_u32 dst_lo,dst_hi; - uae_u32 sign; + if (extra & 0x800) { + /* signed variant */ + uae_s32 src1,src2; + uae_u32 dst_lo,dst_hi; + uae_u32 sign; - src1 = (uae_s32)src; - src2 = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7); - sign = (src1 ^ src2); - if (src1 < 0) src1 = -src1; - if (src2 < 0) src2 = -src2; - mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo); - if (sign & 0x80000000) { - dst_hi = ~dst_hi; - dst_lo = -dst_lo; - if (dst_lo == 0) dst_hi++; - } - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (dst_hi == 0 && dst_lo == 0); - SET_NFLG (((uae_s32)dst_hi) < 0); - if (extra & 0x400) - m68k_dreg(regs, extra & 7) = dst_hi; - else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0) - && ((dst_hi & 0xffffffff) != 0xffffffff - || (dst_lo & 0x80000000) != 0x80000000)) - { - SET_VFLG (1); - } - m68k_dreg(regs, (extra >> 12) & 7) = dst_lo; - } else { - /* unsigned */ - uae_u32 dst_lo,dst_hi; + src1 = (uae_s32)src; + src2 = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7); + sign = (src1 ^ src2); + if (src1 < 0) src1 = -src1; + if (src2 < 0) src2 = -src2; + mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo); + if (sign & 0x80000000) { + dst_hi = ~dst_hi; + dst_lo = -dst_lo; + if (dst_lo == 0) dst_hi++; + } + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (dst_hi == 0 && dst_lo == 0); + SET_NFLG (((uae_s32)dst_hi) < 0); + if (extra & 0x400) + m68k_dreg(regs, extra & 7) = dst_hi; + else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0) + && ((dst_hi & 0xffffffff) != 0xffffffff + || (dst_lo & 0x80000000) != 0x80000000)) + { + SET_VFLG (1); + } + m68k_dreg(regs, (extra >> 12) & 7) = dst_lo; + } else { + /* unsigned */ + uae_u32 dst_lo,dst_hi; - mul_unsigned(src,(uae_u32)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo); + mul_unsigned(src,(uae_u32)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo); - SET_VFLG (0); - SET_CFLG (0); - SET_ZFLG (dst_hi == 0 && dst_lo == 0); - SET_NFLG (((uae_s32)dst_hi) < 0); - if (extra & 0x400) - m68k_dreg(regs, extra & 7) = dst_hi; - else if (dst_hi != 0) { - SET_VFLG (1); + SET_VFLG (0); + SET_CFLG (0); + SET_ZFLG (dst_hi == 0 && dst_lo == 0); + SET_NFLG (((uae_s32)dst_hi) < 0); + if (extra & 0x400) + m68k_dreg(regs, extra & 7) = dst_hi; + else if (dst_hi != 0) { + SET_VFLG (1); + } + m68k_dreg(regs, (extra >> 12) & 7) = dst_lo; } - m68k_dreg(regs, (extra >> 12) & 7) = dst_lo; - } #endif } +static const char* ccnames[] = +{ "T ","F ","HI","LS","CC","CS","NE","EQ", + "VC","VS","PL","MI","GE","LT","GT","LE" }; // If value is greater than zero, this means we are still processing an EmulOp // because the counter is incremented only in m68k_execute(), i.e. interpretive // execution only -#ifdef USE_JIT static int m68k_execute_depth = 0; -#endif void m68k_reset (void) { - regs.s = 1; - regs.m = 0; - regs.stopped = 0; - regs.t1 = 0; - regs.t0 = 0; - SET_ZFLG (0); - SET_XFLG (0); - SET_CFLG (0); - SET_VFLG (0); - SET_NFLG (0); - SPCFLAGS_INIT( 0 ); - regs.intmask = 7; - regs.vbr = regs.sfc = regs.dfc = 0; + m68k_areg (regs, 7) = 0x2000; + m68k_setpc (ROMBaseMac + 0x2a); + fill_prefetch_0 (); + regs.s = 1; + regs.m = 0; + regs.stopped = 0; + regs.t1 = 0; + regs.t0 = 0; + SET_ZFLG (0); + SET_XFLG (0); + SET_CFLG (0); + SET_VFLG (0); + SET_NFLG (0); + SPCFLAGS_INIT( 0 ); + regs.intmask = 7; + regs.vbr = regs.sfc = regs.dfc = 0; + fpu_reset(); - // need to ensure the following order of initialization is correct - // (it is definitely better than what it was before this commit - // since it was reading from 0x00000000 in User mode and with active MMU) - mmu_set_tc(regs.tc & ~0x8000); /* disable mmu */ - m68k_areg (regs, 7) = phys_get_long(0x00000000); - m68k_setpc (phys_get_long(0x00000004)); - fill_prefetch_0 (); - - /* gb-- moved into {fpp,fpu_x86}.cpp::fpu_init() - regs.fpcr = regs.fpsr = regs.fpiar = 0; */ - fpu_reset(); - // MMU - mmu_reset(); - mmu_set_super(1); - // Cache - regs.cacr = 0; - regs.caar = 0; -#ifdef FLIGHT_RECORDER +#if FLIGHT_RECORDER log_ptr = 0; - memset(frlog, 0, sizeof(frlog)); + memset(log, 0, sizeof(log)); +#endif + +#if ENABLE_MON + static bool first_time = true; + if (first_time) { + first_time = false; + mon_add_command("regs", dump_regs, "regs Dump m68k emulator registers\n"); +#if FLIGHT_RECORDER + // Install "log" command in mon + mon_add_command("log", dump_log, "log Dump m68k emulation log\n"); +#endif + } #endif } void m68k_emulop_return(void) { SPCFLAGS_SET( SPCFLAG_BRK ); - quit_program = 1; -} - -static void save_regs(struct M68kRegisters &r) -{ - int i; - - for (i=0; i<8; i++) { - r.d[i] = m68k_dreg(regs, i); - r.a[i] = m68k_areg(regs, i); - } - r.pc = m68k_getpc(); - MakeSR(); - r.sr = regs.sr; - r.isp = regs.isp; - r.usp = regs.usp; - r.msp = regs.msp; - if ((r.sr & 0x2000) == 0) - r.usp = r.a[7]; - else if ((r.sr & 0x1000) != 0) - r.msp = r.a[7]; - else - r.isp = r.a[7]; -} - -static void restore_regs(struct M68kRegisters &r) -{ - int i; - - for (i=0; i<8; i++) { - m68k_dreg(regs, i) = r.d[i]; - m68k_areg(regs, i) = r.a[i]; - } - regs.isp = r.isp; - regs.usp = r.usp; - regs.msp = r.msp; - regs.sr = r.sr; - MakeFromSR(); + quit_program = true; } void m68k_emulop(uae_u32 opcode) { struct M68kRegisters r; - save_regs(r); + int i; + + for (i=0; i<8; i++) { + r.d[i] = m68k_dreg(regs, i); + r.a[i] = m68k_areg(regs, i); + } + MakeSR(); + r.sr = regs.sr; EmulOp(opcode, &r); - restore_regs(r); -} - -// void m68k_natfeat_id(void) -// { -// struct M68kRegisters r; - -// /* is it really necessary to save all registers? */ -// save_regs(r); - -// memptr stack = r.a[7] + 4; /* skip return address */ -// r.d[0] = nf_get_id(stack); - -// restore_regs(r); -// } - -// void m68k_natfeat_call(void) -// { -// struct M68kRegisters r; - -// /* is it really necessary to save all registers? */ -// save_regs(r); - -// memptr stack = r.a[7] + 4; /* skip return address */ -// bool isSupervisorMode = ((r.sr & 0x2000) == 0x2000); -// r.d[0] = nf_call(stack, isSupervisorMode); - -// restore_regs(r); -// } - -static int m68k_call(uae_u32 pc) -{ - VOLATILE int exc = 0; - m68k_setpc(pc); - TRY(prb) { -#ifdef USE_JIT - if (bx_options.jit.jit) { - exec_nostats(); - // m68k_do_compile_execute(); - // The above call to m68k_do_compile_execute fails with BadAccess in sigsegv_handler (MAC, if it is executed after the first compile_block) - // (NULL pointer to addr_instr). - // Call exec_nostats avoids calling compile_block, because stack modification is only temporary - // which will fill up compile cache with BOGUS data. - // we can call exec_nostats directly, do our code, and return back here. - } - else -#endif - m68k_do_execute(); - } - CATCH(prb) { - exc = int(prb); - } - return exc; -} - -static uae_u32 m68k_alloca(int size) -{ - uae_u32 sp = (m68k_areg(regs, 7) - size) & ~1; - m68k_areg(regs, 7) = sp; - if ((regs.sr & 0x2000) == 0) - regs.usp = sp; - else if ((regs.sr & 0x1000) != 0) - regs.msp = sp; - else - regs.isp = sp; - return sp; -} - -// uae_u32 linea68000(volatile uae_u16 opcode) -// { -// sigjmp_buf jmp; -// struct M68kRegisters r; -// volatile uae_u32 abase = 0; - -// SAVE_EXCEPTION; -// save_regs(r); - -// const int sz = 8 + sizeof(void *); -// volatile uae_u32 sp = 0; -// uae_u32 backup[(sz + 3) / 4]; - -// if (sigsetjmp(jmp, 1) == 0) -// { -// void *p = jmp; -// uae_u8 *sp_p; -// int exc; - -// sp = m68k_alloca(sz); -// memcpy(backup, phys_get_real_address(sp), sz); - -// WriteHWMemInt16(sp, opcode); -// WriteHWMemInt16(sp + 2, 0xa0ff); -// WriteHWMemInt32(sp + 4, 13); -// sp_p = phys_get_real_address(sp + 8); -// *((void **)sp_p) = p; -// if ((exc = m68k_call(sp)) != 0) -// { -// panicbug("exception %d in LINEA", exc); -// m68k_dreg(regs, 0) = 0; -// } -// } else -// { -// abase = m68k_dreg(regs, 0); -// } - -// if (sp) { -// memcpy(phys_get_real_address(sp), backup, sz); -// } -// restore_regs(r); -// m68k_setpc(r.pc); -// RESTORE_EXCEPTION; -// return abase; -// } - - -static void rts68000() -{ - uae_u32 SP = m68k_getpc() + 6; - sigjmp_buf *p; - uae_u8 *sp_p = phys_get_real_address(SP); - - p = (sigjmp_buf *)(*((void **)sp_p)); - SP += sizeof(void *); - m68k_areg(regs, 7) = SP; - siglongjmp(*p, 1); + for (i=0; i<8; i++) { + m68k_dreg(regs, i) = r.d[i]; + m68k_areg(regs, i) = r.a[i]; + } + regs.sr = r.sr; + MakeFromSR(); } void REGPARAM2 op_illg (uae_u32 opcode) @@ -1166,17 +1244,6 @@ void REGPARAM2 op_illg (uae_u32 opcode) uaecptr pc = m68k_getpc (); if ((opcode & 0xF000) == 0xA000) { - // if (opcode == 0xa0ff) - // { - // uae_u32 call = ReadHWMemInt32(pc + 2); - // switch (call) - // { - // case 13: - // rts68000(); - // return; - // } - // m68k_setpc(pc + 6); - // } Exception(0xA,0); return; } @@ -1186,8 +1253,8 @@ void REGPARAM2 op_illg (uae_u32 opcode) return; } - D(bug("Illegal instruction: %04x at %08x", opcode, pc)); -#if defined(USE_JIT) && defined(JIT_DEBUG) + write_log ("Illegal instruction: %04x at %08x\n", opcode, pc); +#if USE_JIT && JIT_DEBUG compiler_dumpstate(); #endif @@ -1195,115 +1262,59 @@ void REGPARAM2 op_illg (uae_u32 opcode) return; } +void mmu_op(uae_u32 opcode, uae_u16 extra) +{ + if ((opcode & 0xFE0) == 0x0500) { + /* PFLUSH */ + mmusr = 0; + } else if ((opcode & 0x0FD8) == 0x548) { + /* PTEST */ + } else + op_illg (opcode); +} + +static int n_insns = 0, n_spcinsns = 0; + static uaecptr last_trace_ad = 0; static void do_trace (void) { - if (regs.t0) { - uae_u16 opcode; - /* should also include TRAP, CHK, SR modification FPcc */ - /* probably never used so why bother */ - /* We can afford this to be inefficient... */ - m68k_setpc (m68k_getpc ()); - fill_prefetch_0 (); - opcode = get_word(m68k_getpc()); - if (opcode == 0x4e72 /* RTE */ - || opcode == 0x4e74 /* RTD */ - || opcode == 0x4e75 /* RTS */ - || opcode == 0x4e77 /* RTR */ - || opcode == 0x4e76 /* TRAPV */ - || (opcode & 0xffc0) == 0x4e80 /* JSR */ - || (opcode & 0xffc0) == 0x4ec0 /* JMP */ - || (opcode & 0xff00) == 0x6100 /* BSR */ - || ((opcode & 0xf000) == 0x6000 /* Bcc */ - && cctrue((opcode >> 8) & 0xf)) - || ((opcode & 0xf0f0) == 0x5050 /* DBcc */ - && !cctrue((opcode >> 8) & 0xf) - && (uae_s16)m68k_dreg(regs, opcode & 7) != 0)) - { - last_trace_ad = m68k_getpc (); - SPCFLAGS_CLEAR( SPCFLAG_TRACE ); - SPCFLAGS_SET( SPCFLAG_DOTRACE ); + if (regs.t0 && CPUType >= 2) { + uae_u16 opcode; + /* should also include TRAP, CHK, SR modification FPcc */ + /* probably never used so why bother */ + /* We can afford this to be inefficient... */ + m68k_setpc (m68k_getpc ()); + fill_prefetch_0 (); + opcode = get_word(m68k_getpc()); + if (opcode == 0x4e72 /* RTE */ + || opcode == 0x4e74 /* RTD */ + || opcode == 0x4e75 /* RTS */ + || opcode == 0x4e77 /* RTR */ + || opcode == 0x4e76 /* TRAPV */ + || (opcode & 0xffc0) == 0x4e80 /* JSR */ + || (opcode & 0xffc0) == 0x4ec0 /* JMP */ + || (opcode & 0xff00) == 0x6100 /* BSR */ + || ((opcode & 0xf000) == 0x6000 /* Bcc */ + && cctrue((opcode >> 8) & 0xf)) + || ((opcode & 0xf0f0) == 0x5050 /* DBcc */ + && !cctrue((opcode >> 8) & 0xf) + && (uae_s16)m68k_dreg(regs, opcode & 7) != 0)) + { + last_trace_ad = m68k_getpc (); + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + SPCFLAGS_SET( SPCFLAG_DOTRACE ); + } + } else if (regs.t1) { + last_trace_ad = m68k_getpc (); + SPCFLAGS_CLEAR( SPCFLAG_TRACE ); + SPCFLAGS_SET( SPCFLAG_DOTRACE ); } - } else if (regs.t1) { - last_trace_ad = m68k_getpc (); - SPCFLAGS_CLEAR( SPCFLAG_TRACE ); - SPCFLAGS_SET( SPCFLAG_DOTRACE ); - } } -// #define SERVE_VBL_MFP(resetStop) \ -// { \ -// if (SPCFLAGS_TEST( SPCFLAG_INT3|SPCFLAG_VBL|SPCFLAG_INT5|SPCFLAG_SCC|SPCFLAG_MFP )) { \ -// if (SPCFLAGS_TEST( SPCFLAG_INT3 )) { \ -// if (3 > regs.intmask) { \ -// Interrupt(3); \ -// regs.stopped = 0; \ -// SPCFLAGS_CLEAR( SPCFLAG_INT3 ); \ -// if (resetStop) \ -// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ -// } \ -// } \ -// if (SPCFLAGS_TEST( SPCFLAG_VBL )) { \ -// if (4 > regs.intmask) { \ -// Interrupt(4); \ -// regs.stopped = 0; \ -// SPCFLAGS_CLEAR( SPCFLAG_VBL ); \ -// if (resetStop) \ -// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ -// } \ -// } \ -// if (SPCFLAGS_TEST( SPCFLAG_INT5 )) { \ -// if (5 > regs.intmask) { \ -// Interrupt(5); \ -// regs.stopped = 0; \ -// SPCFLAGS_CLEAR( SPCFLAG_INT5 ); \ -// if (resetStop) \ -// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ -// } \ -// } \ -// if (SPCFLAGS_TEST( SPCFLAG_SCC )) { \ -// if (5 > regs.intmask) { \ -// int vector_number=SCCdoInterrupt(); \ -// if(vector_number){ \ -// SCCInterrupt(vector_number); \ -// regs.stopped = 0; \ -// SPCFLAGS_CLEAR( SPCFLAG_SCC); \ -// if (resetStop) \ -// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ -// } \ -// else \ -// SPCFLAGS_CLEAR( SPCFLAG_SCC ); \ -// } \ -// } \ -// if (SPCFLAGS_TEST( SPCFLAG_MFP )) { \ -// if (6 > regs.intmask) { \ -// int vector_number = MFPdoInterrupt(); \ -// if (vector_number) { \ -// MFPInterrupt(vector_number); \ -// regs.stopped = 0; \ -// if (resetStop) \ -// SPCFLAGS_CLEAR( SPCFLAG_STOP ); \ -// } \ -// else \ -// SPCFLAGS_CLEAR( SPCFLAG_MFP ); \ -// } \ -// } \ -// } \ -// } - -// #define SERVE_INTERNAL_IRQ() \ -// { \ -// if (SPCFLAGS_TEST( SPCFLAG_INTERNAL_IRQ )) { \ -// SPCFLAGS_CLEAR( SPCFLAG_INTERNAL_IRQ ); \ -// invoke200HzInterrupt(); \ -// } \ -// } - -int m68k_do_specialties(void) +int m68k_do_specialties (void) { - // SERVE_INTERNAL_IRQ(); -#ifdef USE_JIT +#if USE_JIT // Block was compiled SPCFLAGS_CLEAR( SPCFLAG_JIT_END_COMPILE ); @@ -1314,35 +1325,11 @@ int m68k_do_specialties(void) if ((m68k_execute_depth == 0) && SPCFLAGS_TEST( SPCFLAG_JIT_EXEC_RETURN )) SPCFLAGS_CLEAR( SPCFLAG_JIT_EXEC_RETURN ); #endif - /*n_spcinsns++;*/ + if (SPCFLAGS_TEST( SPCFLAG_DOTRACE )) { Exception (9,last_trace_ad); } -#if 0 /* not for ARAnyM; emulating 040 only */ - if ((regs.spcflags & SPCFLAG_STOP) && regs.s == 0 && currprefs.cpu_model <= 68010) { - // 68000/68010 undocumented special case: - // if STOP clears S-bit and T was not set: - // cause privilege violation exception, PC pointing to following instruction. - // If T was set before STOP: STOP works as documented. - m68k_unset_stop(); - Exception(8, 0); - } -#endif while (SPCFLAGS_TEST( SPCFLAG_STOP )) { - //TODO: Check - if ((regs.sr & 0x700) == 0x700) - { - // panicbug("STOPed with interrupts disabled, exiting; pc=$%08x", m68k_getpc()); - m68k_dumpstate (stderr, NULL); -#if 0 - quit_program = 1; -#endif -#ifdef FULL_HISTORY - ndebug::showHistory(20, false); - m68k_dumpstate (stderr, NULL); -#endif - return 1; - } if (SPCFLAGS_TEST( SPCFLAG_INT | SPCFLAG_DOINT )){ SPCFLAGS_CLEAR( SPCFLAG_INT | SPCFLAG_DOINT ); int intr = intlev (); @@ -1352,17 +1339,10 @@ int m68k_do_specialties(void) SPCFLAGS_CLEAR( SPCFLAG_STOP ); } } - - // SERVE_INTERNAL_IRQ(); - // SERVE_VBL_MFP(true); - if (SPCFLAGS_TEST( SPCFLAG_BRK )) - break; } if (SPCFLAGS_TEST( SPCFLAG_TRACE )) do_trace (); - // SERVE_VBL_MFP(false); - if (SPCFLAGS_TEST( SPCFLAG_DOINT )) { SPCFLAGS_CLEAR( SPCFLAG_DOINT ); int intr = intlev (); @@ -1371,213 +1351,159 @@ int m68k_do_specialties(void) regs.stopped = 0; } } - if (SPCFLAGS_TEST( SPCFLAG_INT )) { SPCFLAGS_CLEAR( SPCFLAG_INT ); SPCFLAGS_SET( SPCFLAG_DOINT ); } - - if (SPCFLAGS_TEST( SPCFLAG_BRK /*| SPCFLAG_MODE_CHANGE*/ )) { - SPCFLAGS_CLEAR( SPCFLAG_BRK /*| SPCFLAG_MODE_CHANGE*/ ); + if (SPCFLAGS_TEST( SPCFLAG_BRK )) { + SPCFLAGS_CLEAR( SPCFLAG_BRK ); return 1; } - return 0; } void m68k_do_execute (void) { - uae_u32 pc; - uae_u32 opcode; - for (;;) { - regs.fault_pc = pc = m68k_getpc(); -#ifdef FULL_HISTORY -#ifdef NEED_TO_DEBUG_BADLY - history[lasthist] = regs; - historyf[lasthist] = regflags; -#else - history[lasthist] = m68k_getpc(); + for (;;) { + uae_u32 opcode = GET_OPCODE; +#if FLIGHT_RECORDER + m68k_record_step(m68k_getpc()); #endif - if (++lasthist == MAX_HIST) lasthist = 0; - if (lasthist == firsthist) { - if (++firsthist == MAX_HIST) firsthist = 0; + (*cpufunctbl[opcode])(opcode); + cpu_check_ticks(); + if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) { + if (m68k_do_specialties()) + return; + } } -#endif - -#ifndef FULLMMU -#ifdef ARAM_PAGE_CHECK - if (((pc ^ pc_page) > ARAM_PAGE_MASK)) { - check_ram_boundary(pc, 2, false); - pc_page = pc; - pc_offset = (uintptr)get_real_address(pc, 0, sz_word) - pc; - } -#else - check_ram_boundary(pc, 2, false); -#endif -#endif - opcode = GET_OPCODE; -#ifdef FLIGHT_RECORDER - m68k_record_step(m68k_getpc(), opcode); -#endif - (*cpufunctbl[opcode])(opcode); - cpu_check_ticks(); - regs.fault_pc = m68k_getpc(); - - if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) { - if (m68k_do_specialties()) - return; - } - } } void m68k_execute (void) { -#ifdef USE_JIT - m68k_execute_depth++; +#if USE_JIT + ++m68k_execute_depth; #endif -#ifdef DEBUGGER - VOLATILE bool after_exception = false; -#endif - -setjmpagain: - TRY(prb) { for (;;) { - if (quit_program > 0) { - if (quit_program == 1) { -#ifdef FLIGHT_RECORDER - dump_flight_recorder(); + if (quit_program) + break; + m68k_do_execute(); + } +#if USE_JIT + --m68k_execute_depth; #endif - break; +} + +static void m68k_verify (uaecptr addr, uaecptr *nextpc) +{ + uae_u32 opcode, val; + struct instr *dp; + + opcode = get_iword_1(0); + last_op_for_exception_3 = opcode; + m68kpc_offset = 2; + + if (cpufunctbl[cft_map (opcode)] == op_illg_1) { + opcode = 0x4AFC; + } + dp = table68k + opcode; + + if (dp->suse) { + if (!verify_ea (dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, &val)) { + Exception (3, 0); + return; } - quit_program = 0; - m68k_reset (); - } -#ifdef DEBUGGER - if (debugging && !after_exception) debug(); - after_exception = false; -#endif - m68k_do_execute(); } - } - CATCH(prb) { - Exception(prb, 0); -#ifdef DEBUGGER - after_exception = true; -#endif - goto setjmpagain; - } - -#ifdef USE_JIT - m68k_execute_depth--; -#endif -} - -void m68k_disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt) -{ -#ifdef HAVE_DISASM_M68K - char buf[256]; - int size; - - disasm_info.memory_vma = addr; - while (cnt-- > 0) { - size = m68k_disasm_to_buf(&disasm_info, buf); - fprintf(f, "%s\n", buf); - if (size < 0) - break; + if (dp->duse) { + if (!verify_ea (dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, &val)) { + Exception (3, 0); + return; + } } - if (nextpc) - *nextpc = disasm_info.memory_vma; -#else - if (nextpc) - *nextpc = addr; - (void) f; - (void) cnt; -#endif } -#ifdef DEBUGGER -void newm68k_disasm(FILE *f, uaecptr addr, uaecptr *nextpc, unsigned int cnt) +void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt) { -#ifdef HAVE_DISASM_M68K - char buf[256]; + uaecptr newpc = 0; + m68kpc_offset = addr - m68k_getpc (); + while (cnt-- > 0) { + char instrname[20],*ccpt; + int opwords; + uae_u32 opcode; + struct mnemolookup *lookup; + struct instr *dp; + printf ("%08lx: ", m68k_getpc () + m68kpc_offset); + for (opwords = 0; opwords < 5; opwords++){ + printf ("%04x ", get_iword_1 (m68kpc_offset + opwords*2)); + } + opcode = get_iword_1 (m68kpc_offset); + m68kpc_offset += 2; + if (cpufunctbl[cft_map (opcode)] == op_illg_1) { + opcode = 0x4AFC; + } + dp = table68k + opcode; + for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) + ; - disasm_info.memory_vma = addr; - if (cnt == 0) { - m68k_disasm_to_buf(&disasm_info, buf); - } else { - while (cnt-- > 0) { - m68k_disasm_to_buf(&disasm_info, buf); - fprintf(f, "%s\n", buf); - } - } - if (nextpc) - *nextpc = disasm_info.memory_vma; -#else - if (nextpc) - *nextpc = addr; - (void) cnt; -#endif + strcpy (instrname, lookup->name); + ccpt = strstr (instrname, "cc"); + if (ccpt != 0) { + strncpy (ccpt, ccnames[dp->cc], 2); + } + printf ("%s", instrname); + switch (dp->size){ + case sz_byte: printf (".B "); break; + case sz_word: printf (".W "); break; + case sz_long: printf (".L "); break; + default: printf (" "); break; + } + + if (dp->suse) { + newpc = m68k_getpc () + m68kpc_offset; + newpc += ShowEA (dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, 0); + } + if (dp->suse && dp->duse) + printf (","); + if (dp->duse) { + newpc = m68k_getpc () + m68kpc_offset; + newpc += ShowEA (dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 0); + } + if (ccpt != 0) { + if (cctrue(dp->cc)) + printf (" == %08x (TRUE)", newpc); + else + printf (" == %08x (FALSE)", newpc); + } else if ((opcode & 0xff00) == 0x6100) /* BSR */ + printf (" == %08x", newpc); + printf ("\n"); + } + if (nextpc) + *nextpc = m68k_getpc () + m68kpc_offset; } -#endif /* DEBUGGER */ - -#ifdef FULL_HISTORY -void showDisasm(uaecptr addr) { -#ifdef HAVE_DISASM_M68K - char buf[256]; - - disasm_info.memory_vma = addr; - m68k_disasm_to_buf(&disasm_info, buf); - bug("%s", buf); -#else - (void) addr; -#endif -} -#endif /* FULL_HISTORY */ - -void m68k_dumpstate (FILE *out, uaecptr *nextpc) +void m68k_dumpstate (uaecptr *nextpc) { - int i; - for (i = 0; i < 8; i++){ - fprintf (out, "D%d: %08lx ", i, (unsigned long)m68k_dreg(regs, i)); - if ((i & 3) == 3) fprintf (out, "\n"); - } - for (i = 0; i < 8; i++){ - fprintf (out, "A%d: %08lx ", i, (unsigned long)m68k_areg(regs, i)); - if ((i & 3) == 3) fprintf (out, "\n"); - } - if (regs.s == 0) regs.usp = m68k_areg(regs, 7); - if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7); - if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7); - fprintf (out, "USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n", - (unsigned long)regs.usp, (unsigned long)regs.isp, - (unsigned long)regs.msp, (unsigned long)regs.vbr); - fprintf (out, "T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d TCE=%d TCP=%d\n", - regs.t1, regs.t0, regs.s, regs.m, - (int)GET_XFLG, (int)GET_NFLG, (int)GET_ZFLG, (int)GET_VFLG, (int)GET_CFLG, regs.intmask, - regs.mmu_enabled, regs.mmu_pagesize_8k); - fprintf (out, "CACR=%08lx CAAR=%08lx URP=%08lx SRP=%08lx\n", - (unsigned long)regs.cacr, - (unsigned long)regs.caar, - (unsigned long)regs.urp, - (unsigned long)regs.srp); - fprintf (out, "DTT0=%08lx DTT1=%08lx ITT0=%08lx ITT1=%08lx\n", - (unsigned long)regs.dtt0, - (unsigned long)regs.dtt1, - (unsigned long)regs.itt0, - (unsigned long)regs.itt1); - for (i = 0; i < 8; i++){ - fprintf (out, "FP%d: %g ", i, (double)fpu.registers[i]); - if ((i & 3) == 3) fprintf (out, "\n"); - } -#if 0 - fprintf (out, "N=%d Z=%d I=%d NAN=%d\n", - (regs.fpsr & 0x8000000) != 0, - (regs.fpsr & 0x4000000) != 0, - (regs.fpsr & 0x2000000) != 0, - (regs.fpsr & 0x1000000) != 0); -#endif - m68k_disasm(out, m68k_getpc (), nextpc, 1); - if (nextpc) - fprintf (out, "next PC: %08lx\n", (unsigned long)*nextpc); + int i; + for (i = 0; i < 8; i++){ + printf ("D%d: %08x ", i, m68k_dreg(regs, i)); + if ((i & 3) == 3) printf ("\n"); + } + for (i = 0; i < 8; i++){ + printf ("A%d: %08x ", i, m68k_areg(regs, i)); + if ((i & 3) == 3) printf ("\n"); + } + if (regs.s == 0) regs.usp = m68k_areg(regs, 7); + if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7); + if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7); + printf ("USP=%08x ISP=%08x MSP=%08x VBR=%08x\n", + regs.usp,regs.isp,regs.msp,regs.vbr); + printf ("T=%d%d S=%d M=%d X=%ld N=%ld Z=%ld V=%ld C=%ld IMASK=%d\n", + regs.t1, regs.t0, regs.s, regs.m, + GET_XFLG, GET_NFLG, GET_ZFLG, GET_VFLG, GET_CFLG, regs.intmask); + + fpu_dump_registers(); + fpu_dump_flags(); + + m68k_disasm(m68k_getpc (), nextpc, 1); + if (nextpc) + printf ("next PC: %08x\n", *nextpc); } diff --git a/BasiliskII/src/uae_cpu/newcpu.h b/BasiliskII/src/uae_cpu/newcpu.h index 13a51b82..97731f59 100644 --- a/BasiliskII/src/uae_cpu/newcpu.h +++ b/BasiliskII/src/uae_cpu/newcpu.h @@ -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 +#if ENABLE_MON +#include "mon.h" +#include "mon_disass.h" +#endif -extern struct fixup { - int flag; - uae_u32 reg; - uaecptr value; -}fixup; extern int areg_byteinc[]; extern int imm8_table[]; @@ -67,25 +57,27 @@ extern int broken_in; #endif #define cpuop_begin() do { cpuop_tag("begin"); } while (0) -#define cpuop_end() do { cpuop_tag("end"); } while (0) +#define cpuop_end() do { cpuop_tag("end"); } while (0) typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM; - + struct cputbl { cpuop_func *handler; uae_u16 specific; uae_u16 opcode; }; -extern cpuop_func *cpufunctbl[65536]; +extern cpuop_func *cpufunctbl[65536] ASM_SYM("cpufunctbl"); -#ifdef USE_JIT +#if USE_JIT typedef void compop_func (uae_u32) REGPARAM; +//NOTE: The "opcode" and "specific" fields were switched in the original source code! + struct comptbl { compop_func *handler; - uae_u32 opcode; - uae_u32 specific; + uae_u32 opcode; + uae_u32 specific; #define COMP_OPCODE_ISJUMP 0x0001 #define COMP_OPCODE_LONG_OPCODE 0x0002 #define COMP_OPCODE_CMOV 0x0004 @@ -96,84 +88,151 @@ struct comptbl { #endif extern void REGPARAM2 op_illg (uae_u32) REGPARAM; +extern void m68k_dumpstate(uaecptr *nextpc); + +typedef char flagtype; + +// struct regstruct { +// uae_u32 regs[16]; + +// uae_u32 pc; +// uae_u8 * pc_p; +// uae_u8 * pc_oldp; + +// spcflags_t spcflags; +// int intmask; + +// uae_u32 vbr, sfc, dfc; +// uaecptr usp, isp, msp; +// uae_u16 sr; +// flagtype t1; +// flagtype t0; +// flagtype s; +// flagtype m; +// flagtype x; +// flagtype stopped; + +// #if USE_PREFETCH_BUFFER +// /* Fellow sources say this is 4 longwords. That's impossible. It needs +// * to be at least a longword. The HRM has some cryptic comment about two +// * instructions being on the same longword boundary. +// * The way this is implemented now seems like a good compromise. +// */ +// uae_u32 prefetch; +// #endif +// }; + +struct regstruct +{ + uae_u32 regs[16]; + uaecptr usp,isp,msp; + uae_u16 sr; + flagtype t1; + flagtype t0; + flagtype s; + flagtype m; + flagtype x; + flagtype stopped; + int intmask; + + uae_u32 pc; + uae_u32 fault_pc; + uae_u8 *pc_p; + uae_u8 *pc_oldp; + + uae_u32 vbr,sfc,dfc; + + volatile uae_u32 spcflags; + +#if 1 + uae_u32 kick_mask; + + /* Fellow sources say this is 4 longwords. That's impossible. It needs + * to be at least a longword. The HRM has some cryptic comment about two + * instructions being on the same longword boundary. + * The way this is implemented now seems like a good compromise. + */ + uae_u32 prefetch; +#endif + + /* MMU reg*/ + uae_u32 urp,srp; + uae_u32 tc; + + int mmu_enabled; /* flagtype tce; */ + int mmu_pagesize_8k; /* flagtype tcp; */ + + uae_u32 dtt0,dtt1,itt0,itt1; + uae_u32 mmusr; + + uae_u32 mmu_fslw, mmu_fault_addr; + uae_u16 mmu_ssw; + uae_u32 wb3_data; + uae_u16 wb3_status; + + /* Cache reg*/ + uae_u32 cacr,caar; +}; + +extern regstruct regs, lastint_regs; #define m68k_dreg(r,num) ((r).regs[(num)]) #define m68k_areg(r,num) (((r).regs + 8)[(num)]) -#ifdef FULLMMU -static ALWAYS_INLINE uae_u8 get_ibyte(uae_u32 o) -{ - return mmu_get_byte(m68k_getpc() + o + 1, 0, sz_byte); -} -static ALWAYS_INLINE uae_u16 get_iword(uae_u32 o) -{ - return mmu_get_word(m68k_getpc() + o, 0, sz_word); -} -static ALWAYS_INLINE uae_u32 get_ilong(uae_u32 o) -{ - uaecptr addr = m68k_getpc() + o; - - if (unlikely(is_unaligned(addr, 4))) - return mmu_get_long_unaligned(addr, 0); - return mmu_get_long(addr, 0, sz_long); -} +#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1)) +#define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o))) +#define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (o))) +#ifdef HAVE_GET_WORD_UNSWAPPED +#define GET_OPCODE (do_get_mem_word_unswapped (regs.pc_p)) #else -#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(get_real_address(m68k_getpc(), 0, sz_byte) + (o) + 1)) -#define get_iword(o) do_get_mem_word((uae_u16 *)(get_real_address(m68k_getpc(), 0, sz_word) + (o))) -#define get_ilong(o) do_get_mem_long((uae_u32 *)(get_real_address(m68k_getpc(), 0, sz_long) + (o))) +#define GET_OPCODE (get_iword (0)) #endif -#if 0 -static inline uae_u32 get_ibyte_prefetch (uae_s32 o) +#if USE_PREFETCH_BUFFER +static __inline__ uae_u32 get_ibyte_prefetch (uae_s32 o) { if (o > 3 || o < 0) - return do_get_mem_byte((uae_u8 *)(do_get_real_address(regs.pcp, false, false) + o + 1)); + return do_get_mem_byte((uae_u8 *)(regs.pc_p + o + 1)); return do_get_mem_byte((uae_u8 *)(((uae_u8 *)®s.prefetch) + o + 1)); } -static inline uae_u32 get_iword_prefetch (uae_s32 o) +static __inline__ uae_u32 get_iword_prefetch (uae_s32 o) { if (o > 3 || o < 0) - return do_get_mem_word((uae_u16 *)(do_get_real_address(regs.pcp, false, false) + o)); + return do_get_mem_word((uae_u16 *)(regs.pc_p + o)); return do_get_mem_word((uae_u16 *)(((uae_u8 *)®s.prefetch) + o)); } -static inline uae_u32 get_ilong_prefetch (uae_s32 o) +static __inline__ uae_u32 get_ilong_prefetch (uae_s32 o) { if (o > 3 || o < 0) - return do_get_mem_long((uae_u32 *)(do_get_real_address(regs.pcp, false, false) + o)); + return do_get_mem_long((uae_u32 *)(regs.pc_p + o)); if (o == 0) return do_get_mem_long(®s.prefetch); - return (do_get_mem_word (((uae_u16 *)®s.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(do_get_real_address(regs.pcp, false, false) + 4)); + return (do_get_mem_word (((uae_u16 *)®s.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(regs.pc_p + 4)); } #endif -#ifdef FULLMMU -#define m68k_incpc(o) (regs.pc += (o)) -#else -#define m68k_incpc(o) (regs.pc_p += (o)) -#endif - -static inline void fill_prefetch_0 (void) +static __inline__ void fill_prefetch_0 (void) { #if USE_PREFETCH_BUFFER uae_u32 r; #ifdef UNALIGNED_PROFITABLE - r = *(uae_u32 *)do_get_real_address(m68k_getpc(), false, false); + r = *(uae_u32 *)regs.pc_p; regs.prefetch = r; #else - r = do_get_mem_long ((uae_u32 *)do_get_real_address(m68k_getpc(), false, false)); + r = do_get_mem_long ((uae_u32 *)regs.pc_p); do_put_mem_long (®s.prefetch, r); #endif #endif } #if 0 -static inline void fill_prefetch_2 (void) +static __inline__ void fill_prefetch_2 (void) { uae_u32 r = do_get_mem_long (®s.prefetch) << 16; - uae_u32 r2 = do_get_mem_word (((uae_u16 *)do_get_real_address(regs.pcp, false, false)) + 1); + uae_u32 r2 = do_get_mem_word (((uae_u16 *)regs.pc_p) + 1); r |= r2; do_put_mem_long (®s.prefetch, r); } @@ -181,92 +240,115 @@ static inline void fill_prefetch_2 (void) #define fill_prefetch_2 fill_prefetch_0 #endif +static __inline__ uaecptr m68k_getpc (void) +{ +#if REAL_ADDRESSING || DIRECT_ADDRESSING + return get_virtual_address(regs.pc_p); +#else + return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp); +#endif +} + +static __inline__ void m68k_setpc (uaecptr newpc) +{ +#if ENABLE_MON + uae_u32 previous_pc = m68k_getpc(); +#endif + +#if REAL_ADDRESSING || DIRECT_ADDRESSING + regs.pc_p = get_real_address(newpc); +#else + regs.pc_p = regs.pc_oldp = get_real_address(newpc); + regs.pc = newpc; +#endif + +#if ENABLE_MON + if (IS_BREAK_POINT(newpc)) { + printf("Stopped at break point address: %08x. Last PC: %08x\n", newpc, previous_pc); + m68k_dumpstate(NULL); + const char *arg[4] = {"mon", "-m", "-r", NULL}; + mon(3, arg); + } +#endif // end of #if ENABLE_MON +} + +static __inline__ void m68k_incpc (uae_s32 delta) +{ +#if ENABLE_MON + uae_u32 previous_pc = m68k_getpc(); +#endif + regs.pc_p += (delta); +#if ENABLE_MON + uaecptr next_pc = m68k_getpc(); + if (IS_BREAK_POINT(next_pc)) { + printf("Stopped at break point address: %08x. Last PC: %08x\n", next_pc, previous_pc); + m68k_dumpstate(NULL); + const char *arg[4] = {"mon", "-m", "-r", NULL}; + mon(3, arg); + } +#endif // end of #if ENABLE_MON +} + /* These are only used by the 68020/68881 code, and therefore don't * need to handle prefetch. */ -static inline uae_u32 next_ibyte (void) +static __inline__ uae_u32 next_ibyte (void) { uae_u32 r = get_ibyte (0); m68k_incpc (2); return r; } -static inline uae_u32 next_iword (void) +static __inline__ uae_u32 next_iword (void) { uae_u32 r = get_iword (0); m68k_incpc (2); return r; } -static inline uae_u32 next_ilong (void) +static __inline__ uae_u32 next_ilong (void) { uae_u32 r = get_ilong (0); m68k_incpc (4); return r; } -static inline void m68k_setpc (uaecptr newpc) -{ -#ifndef FULLMMU - regs.pc_p = regs.pc_oldp = get_real_address(newpc, 0, sz_word); -#endif - regs.fault_pc = regs.pc = newpc; -} - #define m68k_setpc_fast m68k_setpc #define m68k_setpc_bcc m68k_setpc #define m68k_setpc_rte m68k_setpc -static inline void m68k_do_rts(void) +static __inline__ void m68k_do_rts(void) { - m68k_setpc(get_long(m68k_areg(regs, 7))); - m68k_areg(regs, 7) += 4; + m68k_setpc(get_long(m68k_areg(regs, 7))); + m68k_areg(regs, 7) += 4; } -static inline void m68k_do_bsr(uaecptr oldpc, uae_s32 offset) +static __inline__ void m68k_do_bsr(uaecptr oldpc, uae_s32 offset) { - put_long(m68k_areg(regs, 7) - 4, oldpc); - m68k_areg(regs, 7) -= 4; - m68k_incpc(offset); + m68k_areg(regs, 7) -= 4; + put_long(m68k_areg(regs, 7), oldpc); + m68k_incpc(offset); } -static inline void m68k_do_jsr(uaecptr oldpc, uaecptr dest) +static __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest) { - put_long(m68k_areg(regs, 7) - 4, oldpc); - m68k_areg(regs, 7) -= 4; - m68k_setpc(dest); + m68k_areg(regs, 7) -= 4; + put_long(m68k_areg(regs, 7), oldpc); + m68k_setpc(dest); } -static inline void m68k_setstopped (int stop) +static __inline__ void m68k_setstopped (int stop) { regs.stopped = stop; /* A traced STOP instruction drops through immediately without actually stopping. */ - if (stop && !( SPCFLAGS_TEST( SPCFLAG_DOTRACE ))) - SPCFLAGS_SET( SPCFLAG_STOP ); + if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0) + SPCFLAGS_SET( SPCFLAG_STOP ); } -#ifdef FULLMMU -# define GET_OPCODE (get_iword (0)) -#elif defined ARAM_PAGE_CHECK -# ifdef HAVE_GET_WORD_UNSWAPPED -# define GET_OPCODE (do_get_mem_word_unswapped((uae_u16*)(pc + pc_offset))); -# else -# define GET_OPCODE (do_get_mem_word((uae_u16*)(pc + pc_offset))); -# endif -#else -# ifdef HAVE_GET_WORD_UNSWAPPED -# define GET_OPCODE (do_get_mem_word_unswapped ((uae_u16*)get_real_address(m68k_getpc(), 0, sz_word))) -# else -# define GET_OPCODE (get_iword (0)) -# endif -#endif - -extern REGPARAM uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp); -extern REGPARAM uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp); -extern REGPARAM uae_u32 get_bitfield(uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width); -extern REGPARAM void put_bitfield(uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width); - +extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp); +extern uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp); +extern uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf); extern void MakeSR (void); extern void MakeFromSR (void); @@ -278,19 +360,15 @@ extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr); extern void m68k_mull (uae_u32, uae_u32, uae_u16); extern void m68k_emulop (uae_u32); extern void m68k_emulop_return (void); -extern void m68k_natfeat_id(void); -extern void m68k_natfeat_call(void); extern void init_m68k (void); extern void exit_m68k (void); -extern void m68k_dumpstate (FILE *, uaecptr *); -extern void m68k_disasm (FILE *, uaecptr, uaecptr *, int); -extern void newm68k_disasm(FILE *, uaecptr, uaecptr *, unsigned int); -extern void showDisasm(uaecptr); +extern void m68k_dumpstate (uaecptr *); +extern void m68k_disasm (uaecptr, uaecptr *, int); extern void m68k_reset (void); extern void m68k_enter_debugger(void); extern int m68k_do_specialties(void); -extern void m68k_instr_set(void); -uae_u32 linea68000(uae_u16 opcode); + +extern void mmu_op (uae_u32, uae_u16); /* Opcode of faulting instruction */ extern uae_u16 last_op_for_exception_3; @@ -301,19 +379,24 @@ extern uaecptr last_fault_for_exception_3; #define CPU_OP_NAME(a) op ## a -/* 68040+ 68881 */ -extern const struct cputbl op_smalltbl_0_ff[]; -extern const struct cputbl op_smalltbl_0_nf[]; +/* 68020 + 68881 */ +extern struct cputbl op_smalltbl_0_ff[]; +/* 68020 */ +extern struct cputbl op_smalltbl_1_ff[]; +/* 68010 */ +extern struct cputbl op_smalltbl_2_ff[]; +/* 68000 */ +extern struct cputbl op_smalltbl_3_ff[]; +/* 68000 slow but compatible. */ +extern struct cputbl op_smalltbl_4_ff[]; -#ifdef FLIGHT_RECORDER -extern void m68k_record_step(uaecptr, int); +#if FLIGHT_RECORDER +extern void m68k_record_step(uaecptr) REGPARAM; #endif - extern void m68k_do_execute(void); extern void m68k_execute(void); -#ifdef USE_JIT +#if USE_JIT extern void m68k_compile_execute(void); -extern void m68k_do_compile_execute(void); #endif #ifdef USE_CPU_EMUL_SERVICES extern int32 emulated_ticks; @@ -328,7 +411,5 @@ static inline void cpu_check_ticks(void) #define cpu_check_ticks() #define cpu_do_check_ticks() #endif - -cpuop_func op_illg_1; - + #endif /* NEWCPU_H */ diff --git a/BasiliskII/src/uae_cpu/noflags.h b/BasiliskII/src/uae_cpu/noflags.h index d680b200..eacbc214 100644 --- a/BasiliskII/src/uae_cpu/noflags.h +++ b/BasiliskII/src/uae_cpu/noflags.h @@ -33,13 +33,13 @@ #define NOFLAGS_CMP 0 #undef SET_NFLG_ALWAYS -static inline void SET_NFLG_ALWAYS(uae_u32 x) +static __inline__ void SET_NFLG_ALWAYS(uae_u32 x) { SET_NFLG(x); /* This has not yet been redefined */ } #undef SET_CFLG_ALWAYS -static inline void SET_CFLG_ALWAYS(uae_u32 x) +static __inline__ void SET_CFLG_ALWAYS(uae_u32 x) { SET_CFLG(x); /* This has not yet been redefined */ } diff --git a/BasiliskII/src/uae_cpu/readcpu.cpp b/BasiliskII/src/uae_cpu/readcpu.cpp index 1c385b98..3fccdfb7 100644 --- a/BasiliskII/src/uae_cpu/readcpu.cpp +++ b/BasiliskII/src/uae_cpu/readcpu.cpp @@ -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 +#include +#include +#include + #include "sysdeps.h" #include "readcpu.h" -#include -#include -#include -#include - -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,"#.B"); + break; + case sz_word: + strcpy (buffer,"#.W"); + break; + case sz_long: + strcpy (buffer,"#.L"); + break; + default: + break; + } + break; + case imm0: + strcpy (buffer,"#.B"); + break; + case imm1: + strcpy (buffer,"#.W"); + break; + case imm2: + strcpy (buffer,"#.L"); + break; + case immi: + strcpy (buffer,"#"); + 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; } diff --git a/BasiliskII/src/uae_cpu/readcpu.h b/BasiliskII/src/uae_cpu/readcpu.h index 7855ecc7..6fba3c39 100644 --- a/BasiliskII/src/uae_cpu/readcpu.h +++ b/BasiliskII/src/uae_cpu/readcpu.h @@ -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 */ diff --git a/BasiliskII/src/uae_cpu/readcpua.cpp b/BasiliskII/src/uae_cpu/readcpua.cpp deleted file mode 100644 index 521c241f..00000000 --- a/BasiliskII/src/uae_cpu/readcpua.cpp +++ /dev/null @@ -1,5 +0,0 @@ -/* - * readcpu.cpp must be compiled twice, once for the generator program - * and once for the actual executable - */ -#include "readcpu.cpp" diff --git a/BasiliskII/src/uae_cpu/registers.h b/BasiliskII/src/uae_cpu/registers.h deleted file mode 100644 index f7daef1f..00000000 --- a/BasiliskII/src/uae_cpu/registers.h +++ /dev/null @@ -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 diff --git a/BasiliskII/src/uae_cpu/spcflags.h b/BasiliskII/src/uae_cpu/spcflags.h index b2084372..3c3fc032 100644 --- a/BasiliskII/src/uae_cpu/spcflags.h +++ b/BasiliskII/src/uae_cpu/spcflags.h @@ -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) \ diff --git a/BasiliskII/src/uae_cpu/table68k b/BasiliskII/src/uae_cpu/table68k index 4445cb50..ab9eabe1 100644 --- a/BasiliskII/src/uae_cpu/table68k +++ b/BasiliskII/src/uae_cpu/table68k @@ -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