mirror of
https://github.com/pruten/shoebill.git
synced 2025-02-05 16:31:54 +00:00
Speed improvements + little fixes + 0.0.2 release
- Converted condition-code + physical_get/set switch statements to jump tables - Moved the pmmu_cache lookup code out of translate_logical_addr - Broke MOVE into move-to-datareg, -from-datareg, and datareg-to-datareg - Fixed UFS code to ignore high 32 bits of inode size (it sometimes contains garbage) - Support for zero-length reads in scsi.c + 256kb read/write buffer - pushing interrupt stack frames now actually changes the priority mask - Updated the READMEs, screencaps for 0.0.2
This commit is contained in:
parent
cc2bb3c605
commit
9f0e6ed115
7
Makefile
7
Makefile
@ -1,10 +1,13 @@
|
||||
|
||||
all: shoebill
|
||||
|
||||
shoebill: make_core
|
||||
shoebill: make_gui
|
||||
|
||||
make_gui: make_core
|
||||
xcodebuild -project gui/Shoebill.xcodeproj SYMROOT=build
|
||||
|
||||
make_core:
|
||||
$(MAKE) -C core -j 4
|
||||
|
||||
clean:
|
||||
rm -rf intermediates
|
||||
rm -rf intermediates gui/build
|
||||
|
10
README.md
10
README.md
@ -5,13 +5,17 @@ A Macintosh II emulator that runs A/UX (and A/UX only).
|
||||
|
||||
Shoebill is an all-new, BSD-licensed Macintosh II emulator designed from the ground up with the singular goal of running A/UX.
|
||||
|
||||
A/UX 1.x.x through 2.0.0 are supported currently, and 3.x.x support is in progress.
|
||||
|
||||
Shoebill requires a OS X, a Macintosh II or IIx ROM, a disk image with A/UX installed, and an A/UX kernel.
|
||||
Shoebill requires a OS X, a Macintosh II, IIx or IIcx ROM, and a disk image with A/UX installed.
|
||||
|
||||
[Download the latest release], and then see the [getting started] wiki.
|
||||
Also check out [screenshots].
|
||||
|
||||
__Update (April 26, 2014): Shoebill 0.0.2 is available, and it supports A/UX 3.0.0! And you no longer need to supply your own kernel.__
|
||||
|
||||
|
||||
####Supports
|
||||
* A/UX 1.1.1 through 3.0.0 (but not 3.0.1 or higher, yet)
|
||||
|
||||
####Currently Implements
|
||||
* 68020 CPU (mostly)
|
||||
* 68881 FPU (a little)
|
||||
|
31
README.txt
31
README.txt
@ -1,17 +1,13 @@
|
||||
|
||||
Shoebill - a Macintosh II emulator that runs A/UX
|
||||
(except A/UX 3.x.x currently)
|
||||
|
||||
|
||||
See the wiki on https://github.com/pruten/shoebill for better
|
||||
documentation on building and running Shoebill.
|
||||
|
||||
*** KEEP IN MIND ***
|
||||
|
||||
* Shoebill v.first-terrible-code-drop (a.k.a. version 0.0.1)
|
||||
* Shoebill v.0.0.2
|
||||
* ONLY RUNS A/UX
|
||||
* BUT NOT 3.x.x (I’m working on it)
|
||||
* Only 1.x.x and 2.x.x
|
||||
* Shoebill has broken, ultra-minimalist support for
|
||||
* 68020 (CPU) + 68851 (MMU) + 68881 (FPU)
|
||||
* Some instructions for ‘020 and most for the MMU and FPU are unimplemented
|
||||
@ -26,14 +22,11 @@ documentation on building and running Shoebill.
|
||||
*** RUNNING ***
|
||||
|
||||
You will need
|
||||
* OS X and a 64-bit Intel Macintosh
|
||||
(32-bit builds are possible by twiddling the makefiles)
|
||||
* A Macintosh II or IIx ROM
|
||||
* A disk image with A/UX 1.x.x or 2.x.x installed
|
||||
* OS X 10.8 or 10.9
|
||||
* A Macintosh II, IIx, or IIcx ROM
|
||||
* A disk image with A/UX 1.x.x or 2.x.x, or 3.0.0 installed
|
||||
* Note: 3.0.1 and 3.1.x do not work!
|
||||
* If you happen to have an installation CD image for A/UX, that will work
|
||||
* The kernel on that image (/unix). Shoebill can’t read
|
||||
SVFS or UFS file sytems yet to load the kernel directly
|
||||
from the disk image.
|
||||
|
||||
|
||||
To boot A/UX
|
||||
@ -42,15 +35,21 @@ To boot A/UX
|
||||
will very likely be corrupted - sometimes so severely
|
||||
that A/UX can’t even boot enough to run fsck.
|
||||
* Open Shoebill.app and select Preferences menu item
|
||||
* Set the paths for your ROM, kernel, and disk image(s).
|
||||
* Set the paths for your ROM and disk image(s).
|
||||
* Do use SCSI ID #0 for your A/UX boot image.
|
||||
* Press “Apply and Run”
|
||||
* Press “Apply and Run”
|
||||
* Note: As of 0.0.2, you no longer need to provide your own kernel file
|
||||
|
||||
|
||||
*** BUILDING ***
|
||||
|
||||
1) cd to shoebill/
|
||||
2) make # to build shoebill_core
|
||||
3) xcodebuild -project gui/Shoebill.xcodeproj # to build the Cocoa GUI
|
||||
2) make
|
||||
3) The resulting app will be in gui/build
|
||||
|
||||
|
||||
|
||||
*** ETC. ***
|
||||
Props to Jared Falter for technical and emotional support!
|
||||
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
|
||||
CC = clang
|
||||
CFLAGS = -O3 -flto -ggdb -Wno-deprecated-declarations
|
||||
# CFLAGS = -O0 -ggdb -Wno-deprecated-declarations
|
||||
|
||||
|
||||
DEPS = core_api.h coff.h mc68851.h redblack.h shoebill.h Makefile macro.pl
|
||||
NEED_DECODER = cpu dis
|
||||
NEED_PREPROCESSING = adb fpu mc68851 mem via
|
||||
NEED_NOTHING = atrap_tab coff exception floppy macii_symbols redblack scsi toby_frame_buffer video core_api filesystem debug_server
|
||||
NEED_NOTHING = atrap_tab coff exception floppy macii_symbols redblack scsi toby_frame_buffer video core_api filesystem debug_server alloc_pool
|
||||
|
||||
# Object files that can be compiled directly from the source
|
||||
OBJ_NEED_NOTHING = $(patsubst %,$(TEMP)/%.o,$(NEED_NOTHING))
|
||||
|
95
core/alloc_pool.c
Normal file
95
core/alloc_pool.c
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Peter Rutenbar <pruten@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include "../core/shoebill.h"
|
||||
|
||||
/*typedef struct _alloc_pool_t {
|
||||
struct _alloc_pool_t *prev, *next;
|
||||
uint32_t size, magic;
|
||||
} alloc_pool_t;*/
|
||||
|
||||
void* p_alloc(alloc_pool_t *pool, uint64_t size)
|
||||
{
|
||||
alloc_pool_t *buf = calloc(sizeof(alloc_pool_t) + size, 1);
|
||||
buf->size = size;
|
||||
buf->magic = 'moof';
|
||||
|
||||
buf->next = pool->next;
|
||||
buf->prev = pool;
|
||||
|
||||
if (pool->next)
|
||||
pool->next->prev = buf;
|
||||
pool->next = buf;
|
||||
|
||||
return &buf[1];
|
||||
}
|
||||
|
||||
void* p_realloc(void *ptr, uint64_t size)
|
||||
{
|
||||
alloc_pool_t *header = &((alloc_pool_t*)ptr)[-1];
|
||||
alloc_pool_t *new_header = realloc(header, size + sizeof(alloc_pool_t));
|
||||
|
||||
if (new_header)
|
||||
return &new_header[1];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void p_free(void *ptr)
|
||||
{
|
||||
alloc_pool_t *header = &((alloc_pool_t*)ptr)[-1];
|
||||
assert(header->magic == 'moof');
|
||||
|
||||
if (header->next)
|
||||
header->next->prev = header->prev;
|
||||
|
||||
if (header->prev)
|
||||
header->prev->next = header->next;
|
||||
|
||||
free(header);
|
||||
}
|
||||
|
||||
void p_free_pool(alloc_pool_t *pool)
|
||||
{
|
||||
while (pool->prev)
|
||||
pool = pool->prev;
|
||||
|
||||
while (pool) {
|
||||
alloc_pool_t *cur = pool;
|
||||
pool = cur->next;
|
||||
assert(cur->magic == 'moof');
|
||||
free(cur);
|
||||
}
|
||||
}
|
||||
|
||||
alloc_pool_t* p_new_pool(void)
|
||||
{
|
||||
alloc_pool_t *pool = calloc(sizeof(alloc_pool_t), 1);
|
||||
pool->magic = 'moof';
|
||||
return pool;
|
||||
}
|
113
core/core_api.c
113
core/core_api.c
@ -34,12 +34,10 @@
|
||||
#include "coff.h"
|
||||
#include "core_api.h"
|
||||
|
||||
static uint64_t sub_tv (const struct timeval a, const struct timeval b)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
char *ring, *ring_tmp;
|
||||
const uint32_t ring_len = 64 * 1024 * 1024;
|
||||
uint32_t ring_i = 0;
|
||||
|
||||
void print_mmu_rp(uint64_t rp)
|
||||
{
|
||||
@ -48,11 +46,11 @@ void print_mmu_rp(uint64_t rp)
|
||||
|
||||
void printregs()
|
||||
{
|
||||
printf("[d0]%08x [d1]%08x [d2]%08x [d3]%08x\n", shoe.d[0], shoe.d[1], shoe.d[2], shoe.d[3]);
|
||||
printf("[d4]%08x [d5]%08x [d6]%08x [d7]%08x\n", shoe.d[4], shoe.d[5], shoe.d[6], shoe.d[7]);
|
||||
printf("[a0]%08x [a1]%08x [a2]%08x [a3]%08x\n", shoe.a[0], shoe.a[1], shoe.a[2], shoe.a[3]);
|
||||
printf("[a4]%08x [a5]%08x [a6]%08x [a7]%08x\n", shoe.a[4], shoe.a[5], shoe.a[6], shoe.a[7]);
|
||||
printf("[pc]%08x [sr]%c%c%c%c%c%c%c [tc]%08x\n", shoe.pc,
|
||||
sprintf(ring_tmp+strlen(ring_tmp), "[d0]%08x [d1]%08x [d2]%08x [d3]%08x\n", shoe.d[0], shoe.d[1], shoe.d[2], shoe.d[3]);
|
||||
sprintf(ring_tmp+strlen(ring_tmp), "[d4]%08x [d5]%08x [d6]%08x [d7]%08x\n", shoe.d[4], shoe.d[5], shoe.d[6], shoe.d[7]);
|
||||
sprintf(ring_tmp+strlen(ring_tmp), "[a0]%08x [a1]%08x [a2]%08x [a3]%08x\n", shoe.a[0], shoe.a[1], shoe.a[2], shoe.a[3]);
|
||||
sprintf(ring_tmp+strlen(ring_tmp), "[a4]%08x [a5]%08x [a6]%08x [a7]%08x\n", shoe.a[4], shoe.a[5], shoe.a[6], shoe.a[7]);
|
||||
sprintf(ring_tmp+strlen(ring_tmp), "[pc]%08x [sr]%c%c%c%c%c%c%c [tc]%08x\n", shoe.pc,
|
||||
sr_s()?'S':'s',
|
||||
sr_m()?'M':'m',
|
||||
sr_x()?'X':'x',
|
||||
@ -63,24 +61,42 @@ void printregs()
|
||||
shoe.tc
|
||||
);
|
||||
|
||||
printf("[vbr]%08x\n", shoe.vbr);
|
||||
sprintf(ring_tmp+strlen(ring_tmp), "[vbr]%08x\n", shoe.vbr);
|
||||
|
||||
printf("srp: ");
|
||||
print_mmu_rp(shoe.srp);
|
||||
//printf("srp: ");
|
||||
//print_mmu_rp(shoe.srp);
|
||||
|
||||
printf("crp: ");
|
||||
print_mmu_rp(shoe.crp);
|
||||
|
||||
printf("tc: e=%u sre=%u fcl=%u ps=%u is=%u (tia=%u tib=%u tic=%u tid=%u)\n",
|
||||
//printf("crp: ");
|
||||
//print_mmu_rp(shoe.crp);
|
||||
|
||||
sprintf(ring_tmp+strlen(ring_tmp), "tc: e=%u sre=%u fcl=%u ps=%u is=%u (tia=%u tib=%u tic=%u tid=%u)\n\n",
|
||||
tc_enable(), tc_sre(), tc_fcl(), tc_ps(), tc_is(), tc_tia(), tc_tib(), tc_tic(), tc_tid());
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void dump_ring()
|
||||
{
|
||||
uint32_t i = ring_i+1;
|
||||
|
||||
while (i != ring_i) {
|
||||
fwrite(&ring[i], 1, 1, stdout);
|
||||
i = (i+1) % ring_len;
|
||||
}
|
||||
}
|
||||
|
||||
void ring_print(const char *str)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i=0; str[i]; i++) {
|
||||
ring[ring_i] = str[i];
|
||||
ring_i = (ring_i+1) % ring_len;
|
||||
}
|
||||
}
|
||||
|
||||
void print_pc()
|
||||
{
|
||||
char str[1024];
|
||||
uint8_t binary[32];
|
||||
uint8_t binary[64];
|
||||
uint32_t i;
|
||||
uint32_t len;
|
||||
const char *name = NULL;
|
||||
@ -99,22 +115,13 @@ void print_pc()
|
||||
if (symb && strlen(symb->name))
|
||||
name = symb->name;
|
||||
}
|
||||
else {
|
||||
if ((shoe.pc >= 0x10000000) && (shoe.pc < 0x20000000)) {
|
||||
uint32_t i, addr = shoe.pc % (shoe.physical_rom_size);
|
||||
for (i=0; macii_rom_symbols[i].name; i++) {
|
||||
if (macii_rom_symbols[i].addr > addr) {
|
||||
break;
|
||||
}
|
||||
name = macii_rom_symbols[i].name;
|
||||
}
|
||||
}
|
||||
/*else {
|
||||
coff_symbol *symb = coff_find_func(shoe.launch, shoe.pc);
|
||||
if (symb)
|
||||
name = symb->name;
|
||||
}*/
|
||||
}
|
||||
else
|
||||
name = "";
|
||||
|
||||
if ((name == NULL) || (name[0] == 0))
|
||||
return;
|
||||
if (strncmp("scsi", name, 4) != 0)
|
||||
return ;
|
||||
|
||||
const uint16_t old_abort = shoe.abort;
|
||||
shoe.suppress_exceptions = 1;
|
||||
@ -125,30 +132,38 @@ void print_pc()
|
||||
|
||||
disassemble_inst(binary, shoe.pc, str, &len);
|
||||
|
||||
printf("*0x%08x %s [ ", shoe.pc, name ? name : "");
|
||||
sprintf(ring_tmp, "*0x%08x %s [ ", shoe.pc, name ? name : "");
|
||||
for (i=0; i<len; i+=2) {
|
||||
printf("%02x%02x ", binary[i], binary[i+1]);
|
||||
sprintf(ring_tmp+strlen(ring_tmp), "%02x%02x ", binary[i], binary[i+1]);
|
||||
}
|
||||
sprintf(ring_tmp+strlen(ring_tmp), "] %s\n", str);
|
||||
|
||||
printregs();
|
||||
|
||||
for (i=0; ring_tmp[i]; i++) {
|
||||
ring[ring_i] = ring_tmp[i];
|
||||
ring_i = (ring_i+1) % ring_len;
|
||||
}
|
||||
printf("] %s\n", str);
|
||||
|
||||
shoe.abort = old_abort;
|
||||
shoe.suppress_exceptions = 0;
|
||||
|
||||
if (name && strcmp(name, "ui_ioctl")==0)
|
||||
printregs();
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
void shoebill_start()
|
||||
{
|
||||
pthread_mutex_unlock(&shoe.cpu_thread_lock);
|
||||
pthread_mutex_unlock(&shoe.via_clock_thread_lock);
|
||||
}
|
||||
|
||||
|
||||
void *_cpu_thread (void *arg) {
|
||||
|
||||
pthread_mutex_lock(&shoe.cpu_thread_lock);
|
||||
|
||||
// ring = calloc(ring_len, 1);
|
||||
// ring_tmp = malloc(128 * 1024);
|
||||
|
||||
while (1) {
|
||||
if (shoe.cpu_thread_notifications) {
|
||||
|
||||
@ -162,7 +177,7 @@ void *_cpu_thread (void *arg) {
|
||||
continue; // FIXME: yield or block on a condition variable here
|
||||
}
|
||||
}
|
||||
|
||||
// print_pc();
|
||||
cpu_step();
|
||||
}
|
||||
}
|
||||
@ -499,6 +514,9 @@ static uint32_t _load_rom (shoebill_control_t *control, uint8_t **_rom_data, uin
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rom_data = realloc(rom_data, rom_size);
|
||||
assert(rom_data);
|
||||
|
||||
*_rom_size = rom_size;
|
||||
*_rom_data = rom_data;
|
||||
|
||||
@ -644,9 +662,12 @@ uint32_t shoebill_initialize(shoebill_control_t *control)
|
||||
uint8_t *rom_data = NULL, *kernel_data = NULL;
|
||||
uint32_t rom_size = 0, kernel_size;
|
||||
|
||||
|
||||
memset(&disks[0], 0, 8 * sizeof(scsi_device_t));
|
||||
memset(&shoe, 0, sizeof(global_shoebill_context_t));
|
||||
|
||||
shoe.pool = p_new_pool();
|
||||
|
||||
fpu_setup_jump_table();
|
||||
|
||||
// Try to load the ROM
|
||||
@ -697,13 +718,13 @@ uint32_t shoebill_initialize(shoebill_control_t *control)
|
||||
}
|
||||
|
||||
shoe.physical_rom_size = rom_size;
|
||||
shoe.physical_rom_base = valloc(rom_size);
|
||||
shoe.physical_rom_base = valloc(rom_size+8); // +8 because of physical_get hack
|
||||
memcpy(shoe.physical_rom_base, rom_data, rom_size);
|
||||
free(rom_data);
|
||||
rom_data = NULL;
|
||||
|
||||
shoe.physical_mem_size = control->ram_size;
|
||||
shoe.physical_mem_base = valloc(control->ram_size);
|
||||
shoe.physical_mem_base = valloc(control->ram_size+8); // +8 because of physical_get hack
|
||||
memset(shoe.physical_mem_base, 0, shoe.physical_mem_size);
|
||||
|
||||
// Initialize Macintosh lomem variables that A/UX actually cares about
|
||||
|
460
core/cpu.c
460
core/cpu.c
@ -31,9 +31,32 @@
|
||||
#include "../core/mc68851.h"
|
||||
|
||||
global_shoebill_context_t shoe;
|
||||
//struct dbg_state_t dbg_state;
|
||||
|
||||
static _Bool _cc_t() {return 1;}
|
||||
static _Bool _cc_f() {return 0;}
|
||||
static _Bool _cc_hi() {return !sr_c() && !sr_z();}
|
||||
static _Bool _cc_ls() {return sr_c() || sr_z();}
|
||||
static _Bool _cc_cc() {return !sr_c();}
|
||||
static _Bool _cc_cs() {return sr_c();}
|
||||
static _Bool _cc_ne() {return !sr_z();}
|
||||
static _Bool _cc_eq() {return sr_z();}
|
||||
static _Bool _cc_vc() {return !sr_v();}
|
||||
static _Bool _cc_vs() {return sr_v();}
|
||||
static _Bool _cc_pl() {return !sr_n();}
|
||||
static _Bool _cc_mi() {return sr_n();}
|
||||
static _Bool _cc_ge() {return (sr_n() && sr_v()) || (!sr_n() && !sr_v());}
|
||||
static _Bool _cc_lt() {return (sr_n() && !sr_v()) || (!sr_n() && sr_v());}
|
||||
static _Bool _cc_gt() {return (sr_n() && sr_v() && !sr_z()) || (!sr_n() && !sr_v() && !sr_z());}
|
||||
static _Bool _cc_le() {return sr_z() || (sr_n() && !sr_v()) || (!sr_n() && sr_v());}
|
||||
typedef _Bool (*_cc_func)();
|
||||
static const _cc_func evaluate_cc[16] = {
|
||||
_cc_t, _cc_f, _cc_hi, _cc_ls, _cc_cc, _cc_cs, _cc_ne, _cc_eq,
|
||||
_cc_vc, _cc_vs, _cc_pl, _cc_mi, _cc_ge, _cc_lt, _cc_gt, _cc_le
|
||||
};
|
||||
|
||||
|
||||
#define nextword() ({const uint16_t w=lget(shoe.pc,2); if (shoe.abort) {return;}; shoe.pc+=2; w;})
|
||||
#define nextlong() ({const uint32_t L=lget(shoe.pc,4); if (shoe.abort) {return;}; shoe.pc+=4; L;})
|
||||
#define verify_supervisor() {if (!sr_s()) {throw_privilege_violation(); return;}}
|
||||
|
||||
~newmacro(inst, 2, {
|
||||
@ -75,67 +98,9 @@ global_shoebill_context_t shoe;
|
||||
// (xyz) == (010) -> sz=2
|
||||
// (xyz) == (011) -> sz=4
|
||||
const uint32_t sz = y << (z+1); // too clever
|
||||
const uint32_t next_pc = shoe.orig_pc + 2 + sz;
|
||||
const uint32_t next_pc = shoe.pc + sz;
|
||||
|
||||
const uint8_t C = sr_c();
|
||||
const uint8_t Z = sr_z();
|
||||
const uint8_t V = sr_v();
|
||||
const uint8_t N = sr_n();
|
||||
|
||||
uint8_t set = 0;
|
||||
|
||||
switch (c) {
|
||||
case 0: // trapt
|
||||
set = 1; // FIXME: do-trap unconditionally?
|
||||
break;
|
||||
case 1: // trapf
|
||||
set = 0; // FIXME: do-not-trap unconditionally?
|
||||
break;
|
||||
case 2:
|
||||
if (!C && !Z) set = 1; // traphi
|
||||
break;
|
||||
case 3:
|
||||
if (C || Z) set = 1; // trapls
|
||||
break;
|
||||
case 4:
|
||||
if (!C) set = 1; // trapcc
|
||||
break;
|
||||
case 5:
|
||||
if (C) set = 1; // trapcs
|
||||
break;
|
||||
case 6:
|
||||
if (!Z) set = 1; // trapne
|
||||
break;
|
||||
case 7:
|
||||
if (Z) set = 1; // trapeq
|
||||
break;
|
||||
case 8:
|
||||
if (!V) set = 1; // trapvc
|
||||
break;
|
||||
case 9:
|
||||
if (V) set = 1; // trapvs
|
||||
break;
|
||||
case 10:
|
||||
if (!N) set = 1; // trappl
|
||||
break;
|
||||
case 11:
|
||||
if (N) set = 1; // trapmi
|
||||
break;
|
||||
case 12:
|
||||
if ( (N && V) || (!N && !V) ) set = 1; // trapge
|
||||
break;
|
||||
case 13:
|
||||
if ( (N && !V) || (!N && V) ) set = 1; // traplt
|
||||
break;
|
||||
case 14:
|
||||
if ( (N && V && !Z) || (!N && !V && !Z) ) set = 1; // trapgt
|
||||
break;
|
||||
case 15:
|
||||
if ( (Z || (N && !V) || (!N && V) ) ) set = 1; // traple
|
||||
break;
|
||||
}
|
||||
|
||||
if (set)
|
||||
if (evaluate_cc[c]())
|
||||
throw_frame_two(shoe.sr, next_pc, 7, shoe.orig_pc);
|
||||
else
|
||||
shoe.pc = next_pc;
|
||||
@ -638,7 +603,7 @@ global_shoebill_context_t shoe;
|
||||
const uint16_t format_word = lget(shoe.a[7]+6, 2);
|
||||
if (shoe.abort) return ;
|
||||
|
||||
printf("rte: sr=0x%04x pc=0x%08x format=0x%04x, post-pop a7=0x%08x\n", sr, pc, format_word, shoe.a[7]+8);
|
||||
// printf("rte: sr=0x%04x pc=0x%08x format=0x%04x, post-pop a7=0x%08x\n", sr, pc, format_word, shoe.a[7]+8);
|
||||
|
||||
switch (format_word >> 12) {
|
||||
case 0:
|
||||
@ -900,8 +865,7 @@ global_shoebill_context_t shoe;
|
||||
if (s < 2) {
|
||||
immed = chop(nextword(), sz);
|
||||
} else {
|
||||
immed = nextword();
|
||||
immed = (immed << 16) | nextword();
|
||||
immed = nextlong();
|
||||
}
|
||||
|
||||
call_ea_read(M, sz);
|
||||
@ -1155,25 +1119,64 @@ global_shoebill_context_t shoe;
|
||||
|
||||
~inst(movea, {
|
||||
~decompose(shoe.op, 00 ab rrr 001 MMMMMM);
|
||||
if (a == 0) { // only word and long sizes are supported for movea
|
||||
throw_illegal_instruction();
|
||||
return ;
|
||||
}
|
||||
const uint8_t sz = b ? 2 : 4; // 1<<(1+(!b)); // (3=word, 2=long)
|
||||
|
||||
const uint8_t sz = b ? 2 : 4;
|
||||
|
||||
call_ea_read(M, sz);
|
||||
call_ea_read_commit(M, sz);
|
||||
if (b) { // word-size, sign extend shoe.dat
|
||||
int16_t dat = shoe.dat;
|
||||
const int16_t dat = shoe.dat;
|
||||
shoe.a[r] = (int32_t)dat;
|
||||
} else {
|
||||
// printf("r = %u, dat=0x%llx\n", r, shoe.dat);
|
||||
shoe.a[r] = shoe.dat;
|
||||
}
|
||||
})
|
||||
|
||||
~inst(move_d_to_d, {
|
||||
~decompose(shoe.op, 00 ab RRR 000 000 rrr); // r=source, R=dest
|
||||
|
||||
const uint8_t sz = 1<<(a+(!b)); // (1=byte, 3=word, 2=long)
|
||||
const uint32_t val = chop(shoe.d[r], sz);
|
||||
|
||||
set_d(R, val, sz);
|
||||
|
||||
set_sr_v(0);
|
||||
set_sr_c(0);
|
||||
set_sr_n(mib(val, sz));
|
||||
set_sr_z(val == 0);
|
||||
})
|
||||
|
||||
~inst(move_from_d, {
|
||||
~decompose(shoe.op, 00 ab RRR MMM 000 rrr); // r=source, MR=dest
|
||||
|
||||
const uint8_t sz = 1<<(a+(!b)); // (1=byte, 3=word, 2=long)
|
||||
const uint32_t val = chop(shoe.d[r], sz);
|
||||
|
||||
set_sr_v(0);
|
||||
set_sr_c(0);
|
||||
set_sr_n(mib(val, sz));
|
||||
set_sr_z(val == 0);
|
||||
|
||||
shoe.dat = val;
|
||||
call_ea_write((M << 3) | R, sz);
|
||||
})
|
||||
|
||||
~inst(move_to_d, {
|
||||
~decompose(shoe.op, 00 ab rrr 000 mmmmmm); // m=source, r=dest
|
||||
const uint8_t sz = 1<<(a+(!b)); // (1=byte, 3=word, 2=long)
|
||||
|
||||
call_ea_read(m, sz);
|
||||
call_ea_read_commit(m, sz);
|
||||
|
||||
set_sr_v(0);
|
||||
set_sr_c(0);
|
||||
set_sr_n(ea_n(sz));
|
||||
set_sr_z(ea_z(sz));
|
||||
set_d(r, shoe.dat, sz);
|
||||
})
|
||||
|
||||
~inst(move, {
|
||||
~decompose(shoe.op, 00 ab RRR MMM mmm rrr); // o=source, MR=dest
|
||||
~decompose(shoe.op, 00 ab RRR MMM mmm rrr); // mr=source, MR=dest
|
||||
const uint8_t sz = 1<<(a+(!b)); // (1=byte, 3=word, 2=long)
|
||||
|
||||
call_ea_read((m<<3) | r, sz);
|
||||
@ -1567,12 +1570,12 @@ global_shoebill_context_t shoe;
|
||||
} else if (s==1) {
|
||||
immed = (int16_t)nextword();
|
||||
} else {
|
||||
immed = nextword();
|
||||
immed = (immed << 16) | nextword();
|
||||
immed = nextlong();
|
||||
}
|
||||
|
||||
// fetch the destination operand
|
||||
call_ea_read(M, sz);
|
||||
|
||||
// do the subtraction
|
||||
const uint32_t result = shoe.dat - immed;
|
||||
// find the MIBs for source, dest, and result
|
||||
@ -1602,8 +1605,7 @@ global_shoebill_context_t shoe;
|
||||
} else if (s==1) {
|
||||
immed = (int16_t)nextword();
|
||||
} else {
|
||||
immed = nextword();
|
||||
immed = (immed << 16) | nextword();
|
||||
immed = nextlong();
|
||||
}
|
||||
|
||||
call_ea_read(M, sz);
|
||||
@ -1633,8 +1635,7 @@ global_shoebill_context_t shoe;
|
||||
} else if (s==1) {
|
||||
immed = (int16_t)nextword();
|
||||
} else {
|
||||
immed = nextword();
|
||||
immed = (immed << 16) | nextword();
|
||||
immed = nextlong();
|
||||
}
|
||||
|
||||
call_ea_read(M, sz);
|
||||
@ -1660,8 +1661,7 @@ global_shoebill_context_t shoe;
|
||||
} else if (s==1) {
|
||||
immed = (int16_t)nextword();
|
||||
} else {
|
||||
immed = nextword();
|
||||
immed = (immed << 16) | nextword();
|
||||
immed = nextlong();
|
||||
}
|
||||
|
||||
// fetch the destination operand
|
||||
@ -1689,8 +1689,7 @@ global_shoebill_context_t shoe;
|
||||
} else if (s==1) {
|
||||
immed = (int16_t)nextword();
|
||||
} else {
|
||||
immed = nextword();
|
||||
immed = (immed << 16) | nextword();
|
||||
immed = nextlong();
|
||||
}
|
||||
|
||||
// fetch the destination operand
|
||||
@ -1813,33 +1812,15 @@ global_shoebill_context_t shoe;
|
||||
|
||||
~inst(dbcc, {
|
||||
~decompose(shoe.op, 0101 cccc 11001 rrr);
|
||||
const uint32_t orig_pc = shoe.pc;
|
||||
const int16_t disp = nextword();
|
||||
const uint8_t C = sr_c();
|
||||
const uint8_t Z = sr_z();
|
||||
const uint8_t V = sr_v();
|
||||
const uint8_t N = sr_n();
|
||||
switch (c) {
|
||||
case 0: return ; // dbt (what a useless instruction: c==0 => condition=true => return without doing anything)
|
||||
case 1: break ; // dbf (or dbra)
|
||||
case 2: if (!C && !Z) return; break; // dbhi
|
||||
case 3: if (C || Z) return; break; // dbls
|
||||
case 4: if (!C) return; break; // dbcc
|
||||
case 5: if (C) return; break; // dbcs
|
||||
case 6: if (!Z) return; break; // dbne
|
||||
case 7: if (Z) return; break; // dbeq
|
||||
case 8: if (!V) return; break; // dbvc
|
||||
case 9: if (V) return; break; // dbvs
|
||||
case 10: if (!N) return; break; // dbpl
|
||||
case 11: if (N) return; break; // dbmi
|
||||
case 12: if ( (N && V) || (!N && !V) ) return; break; // dbge
|
||||
case 13: if ( (N && !V) || (!N && V) ) return; break; // dblt
|
||||
case 14: if ( (N && V && !Z) || (!N && !V && !Z) ) return; break; // dbgt
|
||||
case 15: if ( (Z || (N && !V) || (!N && V) ) ) return; break; // dble
|
||||
if (evaluate_cc[c]()) {
|
||||
shoe.pc += 2;
|
||||
}
|
||||
set_d(r, get_d(r, 2)-1, 2);
|
||||
if (get_d(r, 2) != 0xffff) {
|
||||
shoe.pc = orig_pc + disp;
|
||||
else {
|
||||
const int16_t disp = nextword();
|
||||
const uint16_t newd = get_d(r, 2) - 1;
|
||||
set_d(r, newd, 2);
|
||||
if (newd != 0xffff)
|
||||
shoe.pc = shoe.pc + disp - 2;
|
||||
}
|
||||
})
|
||||
|
||||
@ -1849,14 +1830,11 @@ global_shoebill_context_t shoe;
|
||||
|
||||
// find the new PC
|
||||
if ((d==0) || (d==0xff)) {
|
||||
const uint16_t ext = nextword();
|
||||
if (d==0xff) {
|
||||
uint32_t mylong = ((uint32_t)ext)<<16;
|
||||
mylong |= nextword();
|
||||
new_pc += mylong;
|
||||
new_pc += nextlong();
|
||||
}
|
||||
else
|
||||
new_pc += ((int16_t)ext);
|
||||
new_pc += ((int16_t)nextword());
|
||||
}
|
||||
else {
|
||||
uint8_t tmp = d;
|
||||
@ -1870,137 +1848,43 @@ global_shoebill_context_t shoe;
|
||||
})
|
||||
|
||||
~inst(bcc, {
|
||||
uint32_t new_pc = shoe.pc;
|
||||
const uint32_t orig_pc = shoe.pc;
|
||||
~decompose(shoe.op, 0110 cccc dddddddd);
|
||||
// find the new PC
|
||||
if ((d==0) || (d==0xff)) {
|
||||
const uint16_t ext = nextword();
|
||||
if (d==0xff) {
|
||||
uint32_t mylong = ((uint32_t)ext)<<16;
|
||||
mylong |= nextword();
|
||||
new_pc += mylong;
|
||||
|
||||
if (evaluate_cc[c]()) {
|
||||
if (d == 0) {
|
||||
const int16_t ext = (int16_t)nextword();
|
||||
shoe.pc = orig_pc + ext;
|
||||
}
|
||||
else if (d == 0xff) {
|
||||
shoe.pc = orig_pc + nextlong();
|
||||
}
|
||||
else {
|
||||
const int8_t tmp = (int8_t)d;
|
||||
shoe.pc = orig_pc + tmp;
|
||||
}
|
||||
else
|
||||
new_pc += ((int16_t)ext);
|
||||
}
|
||||
else {
|
||||
uint8_t tmp = d;
|
||||
new_pc += ((int8_t)d);
|
||||
}
|
||||
|
||||
// we'll use these control codes
|
||||
const uint8_t C = sr_c();
|
||||
const uint8_t Z = sr_z();
|
||||
const uint8_t V = sr_v();
|
||||
const uint8_t N = sr_n();
|
||||
|
||||
// branch conditionally
|
||||
switch (c) {
|
||||
case 0: { // BRA
|
||||
shoe.pc = new_pc; return; // branch unconditionally
|
||||
}
|
||||
case 1: {
|
||||
assert(!"How did we get here?"); // decoder should have called inst_bsr()
|
||||
}
|
||||
case 2: if (!C && !Z) shoe.pc = new_pc; return; // bhi
|
||||
case 3: if (C || Z) shoe.pc = new_pc; return; // bls
|
||||
case 4: if (!C) shoe.pc = new_pc; return; // bcc
|
||||
case 5: if (C) shoe.pc = new_pc; return; // bcs
|
||||
case 6: if (!Z) shoe.pc = new_pc; return; // bne
|
||||
case 7: if (Z) shoe.pc = new_pc; return; // beq
|
||||
case 8: if (!V) shoe.pc = new_pc; return; // bvc
|
||||
case 9: if (V) shoe.pc = new_pc ; return; // bvs
|
||||
case 10: if (!N) shoe.pc = new_pc; return; // bpl
|
||||
case 11: if (N) shoe.pc = new_pc; return; // bmi
|
||||
case 12: if ( (N && V) || (!N && !V) ) shoe.pc = new_pc; return; // bge
|
||||
case 13: if ( (N && !V) || (!N && V) ) shoe.pc = new_pc; return; // blt
|
||||
case 14: if ( (N && V && !Z) || (!N && !V && !Z) ) shoe.pc = new_pc; return; // bgt
|
||||
case 15: if ( (Z || (N && !V) || (!N && V) ) ) shoe.pc = new_pc; return; // ble
|
||||
if (d == 0) shoe.pc += 2;
|
||||
else if (d == 0xff) shoe.pc += 4;
|
||||
}
|
||||
})
|
||||
|
||||
~inst(scc, {
|
||||
~decompose(shoe.op, 0101 cccc 11 MMMMMM);
|
||||
const uint8_t C = sr_c();
|
||||
const uint8_t Z = sr_z();
|
||||
const uint8_t V = sr_v();
|
||||
const uint8_t N = sr_n();
|
||||
|
||||
uint8_t byte = 0;
|
||||
switch (c) {
|
||||
case 0: // st (set unconditionally? FIXME: TEST ME!)
|
||||
byte = 0xff;
|
||||
break;
|
||||
case 1: // sf
|
||||
byte = 0x0; // (FIXME: do-not-set unconditionally? This can possibly be right)
|
||||
break;
|
||||
case 2:
|
||||
if (!C && !Z) byte = 0xff; // shi
|
||||
break;
|
||||
case 3:
|
||||
if (C || Z) byte = 0xff; // sls
|
||||
break;
|
||||
case 4:
|
||||
if (!C) byte = 0xff; // scc
|
||||
break;
|
||||
case 5:
|
||||
if (C) byte = 0xff; // scs
|
||||
break;
|
||||
case 6:
|
||||
if (!Z) byte = 0xff; // sne
|
||||
break;
|
||||
case 7:
|
||||
if (Z) byte = 0xff; // seq
|
||||
break;
|
||||
case 8:
|
||||
if (!V) byte = 0xff; // svc
|
||||
break;
|
||||
case 9:
|
||||
if (V) byte = 0xff; // svs
|
||||
break;
|
||||
case 10:
|
||||
if (!N) byte = 0xff; // spl
|
||||
break;
|
||||
case 11:
|
||||
if (N) byte = 0xff; // smi
|
||||
break;
|
||||
case 12:
|
||||
if ( (N && V) || (!N && !V) ) byte = 0xff; // sge
|
||||
break;
|
||||
case 13:
|
||||
if ( (N && !V) || (!N && V) ) byte = 0xff; // slt
|
||||
break;
|
||||
case 14:
|
||||
if ( (N && V && !Z) || (!N && !V && !Z) ) byte = 0xff; // sgt
|
||||
break;
|
||||
case 15:
|
||||
if ( (Z || (N && !V) || (!N && V) ) ) byte = 0xff; // sle
|
||||
break;
|
||||
}
|
||||
shoe.dat = byte;
|
||||
shoe.dat = evaluate_cc[c]() ? 0xff : 0;
|
||||
call_ea_write(M, 1);
|
||||
})
|
||||
|
||||
~inst(nop, {})
|
||||
|
||||
/*
|
||||
// Illegal on 68040
|
||||
~inst(cinv, {
|
||||
// Caches aren't implemented, so do nothing
|
||||
})
|
||||
|
||||
~inst(cpush, {
|
||||
// Caches aren't implemented, so do nothing
|
||||
})
|
||||
*/
|
||||
|
||||
~inst(chk, {
|
||||
~decompose(shoe.op, 0100 rrr 1s 0 MMMMMM);
|
||||
|
||||
const uint8_t sz = s ? 2 : 4;
|
||||
|
||||
call_ea_read(M, sz);
|
||||
call_ea_read_commit(M, sz);
|
||||
|
||||
int32_t reg, ea;
|
||||
|
||||
@ -2019,6 +1903,8 @@ global_shoebill_context_t shoe;
|
||||
set_sr_n((reg < 0));
|
||||
throw_frame_two(shoe.sr, shoe.pc, 6, shoe.orig_pc);
|
||||
}
|
||||
|
||||
call_ea_read_commit(M, sz);
|
||||
|
||||
return ;
|
||||
})
|
||||
@ -2036,39 +1922,22 @@ global_shoebill_context_t shoe;
|
||||
|
||||
shoe.a[7] -= 4;
|
||||
shoe.pc = shoe.dat;
|
||||
if (sr_s()&&0) {
|
||||
/*
|
||||
if (sr_s()) {
|
||||
//return ;
|
||||
coff_symbol *symb = coff_find_func(shoe.coff, shoe.pc);
|
||||
if (symb) {
|
||||
uint32_t i;
|
||||
|
||||
printf("CALL %s+%u 0x%08x\n", symb->name, shoe.pc-symb->value, shoe.pc);
|
||||
if (strcmp(symb->name, "tracescsi") == 0) {
|
||||
uint32_t addr = lget(shoe.a[7]+4, 4);
|
||||
|
||||
printf("tracescsi: [");
|
||||
char c;
|
||||
do {
|
||||
c = lget(addr++, 1);
|
||||
printf("%c", c);
|
||||
} while ((c != 0) && (!shoe.abort));
|
||||
printf("]\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (shoe.pc == 0x1002ba94) {
|
||||
uint32_t addr = lget(shoe.a[7]+4, 4);
|
||||
printf("panic: [");
|
||||
char c;
|
||||
do {
|
||||
c = lget(addr++, 1);
|
||||
printf("%c", c);
|
||||
} while ((c != 0) && (!shoe.abort));
|
||||
printf("]\n");
|
||||
if (symb) {
|
||||
sprintf(ring_tmp, "CALL (s) %s+%u 0x%08x\n", symb->name, shoe.pc-symb->value, shoe.pc);
|
||||
ring_print(ring_tmp);
|
||||
}
|
||||
else {
|
||||
sprintf(ring_tmp, "CALL (s) unknown+ 0x%08x\n", shoe.pc);
|
||||
ring_print(ring_tmp);
|
||||
}
|
||||
|
||||
}
|
||||
else if (0) {
|
||||
else {
|
||||
char *name = (char*)"unknown";
|
||||
uint32_t value = 0;
|
||||
if ((shoe.pc >= 0x40000000) && (shoe.pc < 0x50000000)) {
|
||||
@ -2081,16 +1950,12 @@ global_shoebill_context_t shoe;
|
||||
value = macii_rom_symbols[i].addr;
|
||||
}
|
||||
}
|
||||
/*else {
|
||||
coff_symbol *symb = coff_find_func(shoe.launch, shoe.pc);
|
||||
if (symb) {
|
||||
value = symb->value;
|
||||
name = symb->name;
|
||||
}
|
||||
}*/
|
||||
|
||||
printf("CALL %s+%u 0x%08x\n", name, shoe.pc-value, shoe.pc);
|
||||
|
||||
sprintf(ring_tmp, "CALL (u) %s+%u 0x%08x\n", name, shoe.pc-value, shoe.pc);
|
||||
ring_print(ring_tmp);
|
||||
}
|
||||
*/
|
||||
|
||||
})
|
||||
|
||||
@ -2136,6 +2001,7 @@ global_shoebill_context_t shoe;
|
||||
shoe.a[7] += 4;
|
||||
shoe.pc = pop;
|
||||
|
||||
/*
|
||||
if (sr_s() && 0) {
|
||||
// return ;
|
||||
coff_symbol *symb = coff_find_func(shoe.coff, shoe.pc);
|
||||
@ -2155,23 +2021,15 @@ global_shoebill_context_t shoe;
|
||||
value = macii_rom_symbols[i].addr;
|
||||
}
|
||||
}
|
||||
/*else {
|
||||
coff_symbol *symb = coff_find_func(shoe.launch, shoe.pc);
|
||||
if (symb) {
|
||||
value = symb->value;
|
||||
name = symb->name;
|
||||
}
|
||||
}*/
|
||||
|
||||
printf("RETURN TO %s+%u 0x%08x\n", name, shoe.pc-value, shoe.pc);
|
||||
}
|
||||
}*/
|
||||
})
|
||||
|
||||
|
||||
~inst(link_long, {
|
||||
~decompose(shoe.op, 0100 1000 0000 1 rrr);
|
||||
const uint16_t ext_hi = nextword();
|
||||
const uint32_t disp = (ext_hi<<16) | nextword();
|
||||
const uint32_t disp = nextlong();
|
||||
|
||||
// push the contents of the address register onto the stack
|
||||
lset(shoe.a[7]-4, 4, shoe.a[r]);
|
||||
@ -2926,14 +2784,19 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin
|
||||
assert(!"never get here");
|
||||
})
|
||||
|
||||
void dump_ring();
|
||||
~inst(unknown, {
|
||||
printf("Unknown instruction (0x%04x)!\n", shoe.op);
|
||||
/*if (shoe.op == 0x33fe) {
|
||||
dump_ring();
|
||||
assert(!"dumped");
|
||||
}*/
|
||||
throw_illegal_instruction();
|
||||
})
|
||||
|
||||
~inst(a_line, {
|
||||
|
||||
if (shoe.op == 0xA9EB || shoe.op == 0xA9EC) {
|
||||
/*if (shoe.op == 0xA9EB || shoe.op == 0xA9EC) {
|
||||
shoe.suppress_exceptions = 1;
|
||||
|
||||
uint32_t fp_op = lget(shoe.a[7]+0, 2);
|
||||
@ -2961,7 +2824,7 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin
|
||||
|
||||
shoe.abort = 0;
|
||||
shoe.suppress_exceptions = 0;
|
||||
}
|
||||
}*/
|
||||
|
||||
throw_illegal_instruction();
|
||||
})
|
||||
@ -3058,36 +2921,35 @@ fail:
|
||||
|
||||
void cpu_step()
|
||||
{
|
||||
while (1) {
|
||||
// remember the PC and SR (so we can throw exceptions later)
|
||||
shoe.orig_pc = shoe.pc;
|
||||
shoe.orig_sr = shoe.sr;
|
||||
|
||||
// Is this an odd address? Throw an address exception!
|
||||
if (shoe.pc & 1) {
|
||||
// throw_address_error(shoe.pc, 0);
|
||||
assert(!"What do I do here?");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fetch the next instruction word
|
||||
shoe.op = lget(shoe.pc, 2);
|
||||
|
||||
// If there was an exception, then the pc changed. Restart execution from the beginning.
|
||||
if (shoe.abort) {
|
||||
shoe.abort = 0;
|
||||
continue;
|
||||
}
|
||||
shoe.pc+=2;
|
||||
|
||||
inst_instruction_to_pointer[inst_opcode_map[shoe.op]]();
|
||||
|
||||
/* The abort flag indicates that a routine should stop trying to execute the
|
||||
instruction and return immediately to cpu_step(), usually to begin
|
||||
exception processing */
|
||||
|
||||
shoe.abort = 0; // clear the abort flag
|
||||
// remember the PC and SR (so we can throw exceptions later)
|
||||
shoe.orig_pc = shoe.pc;
|
||||
shoe.orig_sr = shoe.sr;
|
||||
|
||||
// Is this an odd address? Throw an address exception!
|
||||
if (shoe.pc & 1) {
|
||||
// throw_address_error(shoe.pc, 0);
|
||||
// I'm leaving this assert in here for now because it almost always indicates a bug in the emulator when it fires
|
||||
assert(!"What do I do here?");
|
||||
return ;
|
||||
}
|
||||
|
||||
// Fetch the next instruction word
|
||||
shoe.op = lget(shoe.pc, 2);
|
||||
|
||||
// If there was an exception, then the pc changed. Restart execution from the beginning.
|
||||
if (shoe.abort) {
|
||||
shoe.abort = 0;
|
||||
return ;
|
||||
}
|
||||
shoe.pc+=2;
|
||||
|
||||
inst_instruction_to_pointer[inst_opcode_map[shoe.op]]();
|
||||
|
||||
/* The abort flag indicates that a routine should stop trying to execute the
|
||||
instruction and return immediately to cpu_step(), usually to begin
|
||||
exception processing */
|
||||
|
||||
shoe.abort = 0; // clear the abort flag
|
||||
return ;
|
||||
}
|
||||
|
||||
|
@ -929,6 +929,65 @@ void begin_definitions()
|
||||
|
||||
// subtract illegal size (00)
|
||||
sub_range(inst, "00 00 xxxxxx xxxxxx");
|
||||
|
||||
// subtract move_from_d
|
||||
sub_range(inst, "00 xx xxxxxx 000xxx");
|
||||
|
||||
// subtract move_to_d
|
||||
sub_range(inst, "00 xx xxx000 xxxxxx");
|
||||
}
|
||||
|
||||
{ // move_d_to_d
|
||||
inst_t *inst = new_inst("move_d_to_d", "all", 1);
|
||||
no_ea(inst);
|
||||
|
||||
add_range(inst, "00 xx xxx 000 000 xxx");
|
||||
sub_range(inst, "00 00 xxx 000 000 xxx");
|
||||
}
|
||||
|
||||
{ // move_to_d
|
||||
inst_t *inst = new_inst("move_to_d", "all", 2);
|
||||
{ // EA mode == addr register (byte-size not allowed)
|
||||
set_range_group(inst, 0);
|
||||
add_range(inst, "00 11 xxx000 MMMMMM");
|
||||
add_range(inst, "00 10 xxx000 MMMMMM");
|
||||
ea_add_mode(inst, EA_001);
|
||||
}
|
||||
{ // all other EA modes
|
||||
set_range_group(inst, 1);
|
||||
add_range(inst, "00 xx xxx000 MMMMMM");
|
||||
sub_range(inst, "00 00 xxx000 MMMMMM");
|
||||
ea_all(inst);
|
||||
ea_sub_mode(inst, EA_001);
|
||||
ea_sub_mode(inst, EA_000); // EA_000 is handled by move_d_to_d
|
||||
}
|
||||
}
|
||||
|
||||
{ // move_from_d
|
||||
inst_t *inst = new_inst("move_from_d", "all", 1);
|
||||
|
||||
// I'm manually specifying this entire thing, since the EA description is too complicated
|
||||
no_ea(inst);
|
||||
|
||||
// Add in all modes, all sizes
|
||||
add_range(inst, "00 xx xxxxxx 000xxx");
|
||||
|
||||
// subtract the invalid destination modes (001, 111_010, 111_011, 111_100)
|
||||
sub_range(inst, "00 xx xxx 001 xxxxxx");
|
||||
sub_range(inst, "00 xx 010 111 xxxxxx");
|
||||
sub_range(inst, "00 xx 011 111 xxxxxx");
|
||||
sub_range(inst, "00 xx 100 111 xxxxxx");
|
||||
|
||||
// subtract the illegal destination modes (111_101, 111_110, 111_111)
|
||||
sub_range(inst, "00 xx 101 111 xxxxxx");
|
||||
sub_range(inst, "00 xx 110 111 xxxxxx");
|
||||
sub_range(inst, "00 xx 111 111 xxxxxx");
|
||||
|
||||
// subtract illegal size (00)
|
||||
sub_range(inst, "00 00 xxxxxx xxxxxx");
|
||||
|
||||
// subtract move_d_to_d
|
||||
sub_range(inst, "00 xx xxx 000 000xxx");
|
||||
}
|
||||
|
||||
{ // movea
|
||||
|
12
core/dis.c
12
core/dis.c
@ -802,6 +802,18 @@ void dis_move () {
|
||||
sprintf(dis.str, "move.%c %s,%s", "blw"[s-1], sourceStr, destStr);
|
||||
}
|
||||
|
||||
void dis_move_d_to_d () {
|
||||
sprintf(dis.str, "move_d_to_d ???");
|
||||
}
|
||||
|
||||
void dis_move_to_d () {
|
||||
sprintf(dis.str, "move_to_d ???");
|
||||
}
|
||||
|
||||
void dis_move_from_d () {
|
||||
sprintf(dis.str, "move_from_d ???");
|
||||
}
|
||||
|
||||
void dis_scc () {
|
||||
const char *condition_names[16] = {
|
||||
"t", "ra", "hi", "ls", "cc", "cs", "ne", "eq",
|
||||
|
@ -28,15 +28,7 @@
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#pragma mark Alloc pool stuff
|
||||
|
||||
/* --- alloc pool --- */
|
||||
|
||||
typedef struct _alloc_pool_t{
|
||||
struct _alloc_pool_t *prev, *next;
|
||||
uint32_t size, magic;
|
||||
} alloc_pool_t;
|
||||
#include "../core/shoebill.h"
|
||||
|
||||
#define fix_endian(x) do { \
|
||||
if (ntohs(1) == 1) \
|
||||
@ -45,76 +37,9 @@ typedef struct _alloc_pool_t{
|
||||
case 1: break; \
|
||||
case 2: (x) = ntohs(x); break; \
|
||||
case 4: (x) = ntohl(x); break; \
|
||||
case 8: { \
|
||||
const uint64_t n = ntohl((x) & 0xffffffff); \
|
||||
(x) = (n<<32) | ntohl((x)>>32); \
|
||||
break; \
|
||||
} \
|
||||
default: assert(!"bogus size"); \
|
||||
}} while (0)
|
||||
|
||||
static void* p_alloc(alloc_pool_t *pool, uint64_t size)
|
||||
{
|
||||
alloc_pool_t *buf = calloc(sizeof(alloc_pool_t) + size, 1);
|
||||
buf->size = size;
|
||||
buf->magic = 'moof';
|
||||
|
||||
buf->next = pool->next;
|
||||
buf->prev = pool;
|
||||
|
||||
if (pool->next)
|
||||
pool->next->prev = buf;
|
||||
pool->next = buf;
|
||||
|
||||
return &buf[1];
|
||||
}
|
||||
|
||||
static void* p_realloc(void *ptr, uint64_t size)
|
||||
{
|
||||
alloc_pool_t *header = &((alloc_pool_t*)ptr)[-1];
|
||||
alloc_pool_t *new_header = realloc(header, size + sizeof(alloc_pool_t));
|
||||
|
||||
if (new_header)
|
||||
return &new_header[1];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void p_free(void *ptr)
|
||||
{
|
||||
alloc_pool_t *header = &((alloc_pool_t*)ptr)[-1];
|
||||
assert(header->magic == 'moof');
|
||||
|
||||
if (header->next)
|
||||
header->next->prev = header->prev;
|
||||
|
||||
if (header->prev)
|
||||
header->prev->next = header->next;
|
||||
|
||||
free(header);
|
||||
}
|
||||
|
||||
static void p_free_pool(alloc_pool_t *pool)
|
||||
{
|
||||
while (pool->prev)
|
||||
pool = pool->prev;
|
||||
|
||||
while (pool) {
|
||||
alloc_pool_t *cur = pool;
|
||||
pool = cur->next;
|
||||
assert(cur->magic == 'moof');
|
||||
free(cur);
|
||||
}
|
||||
}
|
||||
|
||||
static alloc_pool_t* p_new_pool(void)
|
||||
{
|
||||
alloc_pool_t *pool = calloc(sizeof(alloc_pool_t), 1);
|
||||
pool->magic = 'moof';
|
||||
return pool;
|
||||
}
|
||||
|
||||
|
||||
/* --- Disk/partition management stuff --- */
|
||||
#pragma mark Disk/partition management stuff
|
||||
|
||||
@ -344,8 +269,8 @@ static disk_t* open_disk (const char *disk_path, char *error_str)
|
||||
memcpy(disk->partitions[i].name, disk->partition_maps[i].pmPartName, 32);
|
||||
memcpy(disk->partitions[i].type, disk->partition_maps[i].pmPartType, 32);
|
||||
|
||||
// printf("%u type:%s name:%s\n", i, disk->partitions[i].type, disk->partitions[i].name);
|
||||
// printf("bz_magic=0x%08x slice=%u\n", disk->partition_maps[i].bz.magic, disk->partition_maps[i].bz.slice);
|
||||
printf("%u type:%s name:%s\n", i, disk->partitions[i].type, disk->partitions[i].name);
|
||||
printf("bz_magic=0x%08x slice=%u\n", disk->partition_maps[i].bz.magic, disk->partition_maps[i].bz.slice);
|
||||
}
|
||||
|
||||
return disk;
|
||||
@ -855,7 +780,8 @@ typedef struct __attribute__ ((__packed__)) {
|
||||
uint16_t nlink;
|
||||
uint16_t uid;
|
||||
uint16_t gid;
|
||||
uint64_t size;
|
||||
uint32_t size_hi; // UFS stores size as a uint64_t, but A/UX apparently only reads/writes
|
||||
uint32_t size; // to the low bits, so sometimes the hi bits contain garbage
|
||||
uint32_t atime;
|
||||
uint32_t dummy;
|
||||
uint32_t mtime;
|
||||
@ -986,6 +912,7 @@ static uint8_t ufs_load_inode(ufs_t *mount, ufs_inode_t *inode, uint32_t inum)
|
||||
fix_endian(inode->nlink);
|
||||
fix_endian(inode->uid);
|
||||
fix_endian(inode->gid);
|
||||
fix_endian(inode->size_hi);
|
||||
fix_endian(inode->size);
|
||||
fix_endian(inode->atime);
|
||||
fix_endian(inode->mtime);
|
||||
@ -1043,7 +970,7 @@ static uint8_t ufs_read_level(ufs_t *mount,
|
||||
const uint32_t block_addr = (blockno / mount->frag_per_block) * mount->frag_per_block;
|
||||
const uint32_t block_offset = (blockno - block_addr) * mount->frag_size;
|
||||
|
||||
//printf("L%u: raw_blkno=0x%08x len=0x%08x blockno:0x%08x chunk_size=0x%08x\n", level-1, blockno, (uint32_t)*len, block_addr, (uint32_t)chunk_size);
|
||||
printf("L%u: raw_blkno=0x%08x len=0x%08x blockno:0x%08x chunk_size=0x%08x\n", level-1, blockno, (uint32_t)*len, block_addr, (uint32_t)chunk_size);
|
||||
|
||||
// If the chunk_size is a whole block, then we better be reading in a whole block
|
||||
if (chunk_size == mount->block_size) {
|
||||
@ -1325,6 +1252,7 @@ uint8_t* shoebill_extract_kernel(const char *disk_path, const char *kernel_path,
|
||||
sprintf(error_str, "Couldn't find root partition");
|
||||
goto done;
|
||||
}
|
||||
printf("apm_part_num = %u\n", apm_part_num);
|
||||
|
||||
svfs_mount_obj = svfs_mount(&disk->partitions[apm_part_num]);
|
||||
if (svfs_mount_obj) {
|
||||
|
@ -81,15 +81,15 @@ void inst_mc68851_pflushr(uint16_t ext){
|
||||
verify_supervisor();
|
||||
printf("pflushr!");
|
||||
// Just nuke the entire cache
|
||||
bzero(shoe.pmmu_cache[0].valid_map, 512/8);
|
||||
bzero(shoe.pmmu_cache[1].valid_map, 512/8);
|
||||
bzero(shoe.pmmu_cache[0].valid_map, PMMU_CACHE_SIZE/8);
|
||||
bzero(shoe.pmmu_cache[1].valid_map, PMMU_CACHE_SIZE/8);
|
||||
}
|
||||
|
||||
void inst_mc68851_pflush(uint16_t ext){
|
||||
verify_supervisor();
|
||||
printf("pflush!");
|
||||
bzero(shoe.pmmu_cache[0].valid_map, 512/8);
|
||||
bzero(shoe.pmmu_cache[1].valid_map, 512/8);
|
||||
bzero(shoe.pmmu_cache[0].valid_map, PMMU_CACHE_SIZE/8);
|
||||
bzero(shoe.pmmu_cache[1].valid_map, PMMU_CACHE_SIZE/8);
|
||||
// printf("%s: Error, not implemented!\n", __func__);
|
||||
}
|
||||
|
||||
|
909
core/mem.c
909
core/mem.c
File diff suppressed because it is too large
Load Diff
16
core/scsi.c
16
core/scsi.c
@ -150,7 +150,7 @@ typedef struct {
|
||||
uint8_t target_id; // target ID (as an int [0, 7])
|
||||
|
||||
// transfer buffers
|
||||
uint8_t buf[512 * 64];
|
||||
uint8_t buf[512 * 256];
|
||||
uint32_t bufi;
|
||||
uint32_t in_len, in_i;
|
||||
uint32_t out_len, out_i;
|
||||
@ -412,13 +412,19 @@ static void scsi_buf_set (uint8_t byte)
|
||||
|
||||
printf("scsi_buf_set: Responding to read at off=%u len=%u\n", offset, len);
|
||||
|
||||
assert(len <= 64);
|
||||
//assert(len <= 64);
|
||||
|
||||
assert(dev->num_blocks > offset);
|
||||
|
||||
if (len == 0) {
|
||||
switch_status_phase(0);
|
||||
break;
|
||||
}
|
||||
|
||||
assert(0 == fseeko(dev->f, 512 * offset, SEEK_SET));
|
||||
assert(fread(scsi.buf, len * 512, 1, dev->f) == 1);
|
||||
|
||||
|
||||
scsi.in_len = len * 512;
|
||||
scsi.in_i = 0;
|
||||
|
||||
@ -435,7 +441,7 @@ static void scsi_buf_set (uint8_t byte)
|
||||
|
||||
printf("scsi_buf_set: Responding to write at off=%u len=%u\n", offset, len);
|
||||
|
||||
assert(len <= 64);
|
||||
//assert(len <= 64);
|
||||
|
||||
scsi.write_offset = offset;
|
||||
scsi.out_len = len * 512;
|
||||
@ -466,7 +472,7 @@ void scsi_reg_read ()
|
||||
{
|
||||
const uint32_t reg = ((shoe.physical_addr & 0xffff) >> 4) & 0xf;
|
||||
|
||||
printf("\nscsi_reg_read: reading from register %s(%u) ", scsi_read_reg_str[reg], reg);
|
||||
//printf("\nscsi_reg_read: reading from register %s(%u) ", scsi_read_reg_str[reg], reg);
|
||||
|
||||
switch (reg) {
|
||||
case 0: // Current scsi data bus register
|
||||
@ -555,7 +561,7 @@ void scsi_reg_read ()
|
||||
break;
|
||||
}
|
||||
|
||||
printf("(set to 0x%02x)\n\n", (uint32_t)shoe.physical_dat);
|
||||
//printf("(set to 0x%02x)\n\n", (uint32_t)shoe.physical_dat);
|
||||
}
|
||||
|
||||
void scsi_reg_write ()
|
||||
|
@ -33,6 +33,9 @@
|
||||
#include <pthread.h>
|
||||
//#include <histedit.h>
|
||||
|
||||
// void ring_print(const char *str);
|
||||
// extern char *ring_tmp;
|
||||
|
||||
#include "coff.h"
|
||||
|
||||
// -- Global constants --
|
||||
@ -59,7 +62,7 @@
|
||||
#define get_d(n,s) get_reg__(shoe.d[n], s)
|
||||
#define get_a(n,s) get_reg__(shoe.a[n], s)
|
||||
#define set_d(n,val,s) set_reg__(shoe.d[n], val, s)
|
||||
// #define set_a(n,val,s) set_reg__(shoe.a[n], val, s) // address registers should always be set with sz==4
|
||||
|
||||
|
||||
// sr masks
|
||||
#define sr_c() (shoe.sr&1)
|
||||
@ -100,12 +103,13 @@
|
||||
shoe.sr = newsr & 0xf71f; \
|
||||
load_stack_pointer(); \
|
||||
}
|
||||
|
||||
|
||||
#define set_sr_c(b) {shoe.sr &= (~(1<<0)); shoe.sr |= (((b)!=0)<<0);}
|
||||
#define set_sr_v(b) {shoe.sr &= (~(1<<1)); shoe.sr |= (((b)!=0)<<1);}
|
||||
#define set_sr_z(b) {shoe.sr &= (~(1<<2)); shoe.sr |= (((b)!=0)<<2);}
|
||||
#define set_sr_n(b) {shoe.sr &= (~(1<<3)); shoe.sr |= (((b)!=0)<<3);}
|
||||
#define set_sr_x(b) {shoe.sr &= (~(1<<4)); shoe.sr |= (((b)!=0)<<4);}
|
||||
#define set_sr_mask(m) {shoe.sr &= (~(7<<8)); shoe.sr |= ((((uint16_t)(m))&7) << 8);}
|
||||
// Be careful when setting these bits
|
||||
#define set_sr_m(b) {make_stack_pointers_valid(); shoe.sr &= (~(1<<12)); shoe.sr |= (((b)!=0)<<12); load_stack_pointer();}
|
||||
#define set_sr_s(b) {make_stack_pointers_valid(); shoe.sr &= (~(1<<13)); shoe.sr |= (((b)!=0)<<13); load_stack_pointer();}
|
||||
@ -132,7 +136,21 @@
|
||||
|
||||
// misc
|
||||
#define ea_n(s) ((shoe.dat>>((s)*8-1))&1)
|
||||
#define ea_z(s) ((shoe.dat&((0xffffffff)>>(8*(4-(s)))))==0)
|
||||
#define ea_z(s) (chop(shoe.dat, (s))==0)
|
||||
|
||||
// alloc_pool.c
|
||||
typedef struct _alloc_pool_t {
|
||||
struct _alloc_pool_t *prev, *next;
|
||||
uint32_t size, magic;
|
||||
} alloc_pool_t;
|
||||
|
||||
void* p_alloc(alloc_pool_t *pool, uint64_t size);
|
||||
void* p_realloc(void *ptr, uint64_t size);
|
||||
void p_free(void *ptr);
|
||||
void p_free_pool(alloc_pool_t *pool);
|
||||
alloc_pool_t* p_new_pool(void);
|
||||
|
||||
|
||||
|
||||
typedef struct dbg_breakpoint_t {
|
||||
struct dbg_breakpoint_t *next;
|
||||
@ -231,7 +249,6 @@ typedef struct {
|
||||
} iwm_state_t;
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t (*read_func)(uint32_t, uint32_t, uint8_t);
|
||||
void (*write_func)(uint32_t, uint32_t, uint32_t, uint8_t);
|
||||
@ -270,9 +287,11 @@ typedef struct {
|
||||
pthread_mutex_t cpu_freeze_lock;
|
||||
|
||||
// -- PMMU caching structures ---
|
||||
#define PMMU_CACHE_KEY_BITS 10
|
||||
#define PMMU_CACHE_SIZE (1<<PMMU_CACHE_KEY_BITS)
|
||||
struct {
|
||||
pmmu_cache_entry_t entry[512];
|
||||
uint8_t valid_map[512 / 8];
|
||||
pmmu_cache_entry_t entry[PMMU_CACHE_SIZE];
|
||||
uint8_t valid_map[PMMU_CACHE_SIZE / 8];
|
||||
} pmmu_cache[2];
|
||||
|
||||
// -- Assorted CPU state variables --
|
||||
@ -280,8 +299,8 @@ typedef struct {
|
||||
uint16_t orig_sr; // the sr before we began executing the instruction
|
||||
uint32_t orig_pc; // the address of the instruction we're currently running
|
||||
uint16_t exception;
|
||||
uint16_t abort;
|
||||
uint32_t suppress_exceptions;
|
||||
_Bool abort;
|
||||
_Bool suppress_exceptions;
|
||||
|
||||
// -- Physical memory --
|
||||
uint8_t *physical_mem_base;
|
||||
@ -296,7 +315,7 @@ typedef struct {
|
||||
uint64_t physical_dat; // <- Data for physical fetches is put/stored here
|
||||
uint64_t logical_dat; // <- Data for logical fetches is put/stored here
|
||||
|
||||
uint8_t logical_is_write; // <- boolean: true iff the operation is logical_set()
|
||||
_Bool logical_is_write; // <- boolean: true iff the operation is logical_set()
|
||||
uint8_t logical_fc; // logical function code
|
||||
|
||||
// -- Interrupts/VIA chips --
|
||||
@ -433,6 +452,7 @@ typedef struct {
|
||||
scsi_device_t scsi_devices[8]; // SCSI devices
|
||||
|
||||
debugger_state_t dbg;
|
||||
alloc_pool_t *pool;
|
||||
} global_shoebill_context_t;
|
||||
|
||||
extern global_shoebill_context_t shoe; // declared in cpu.c
|
||||
@ -459,7 +479,16 @@ void throw_frame_two (uint16_t sr, uint32_t next_pc, uint32_t vector_num, uint32
|
||||
|
||||
// mem.c functions
|
||||
|
||||
void physical_get (void);
|
||||
//void physical_get (void);
|
||||
typedef void (*physical_get_ptr) (void);
|
||||
typedef void (*physical_set_ptr) (void);
|
||||
extern const physical_get_ptr physical_get_jump_table[16];
|
||||
extern const physical_set_ptr physical_set_jump_table[16];
|
||||
|
||||
#define physical_set() physical_set_jump_table[shoe.physical_addr >> 28]()
|
||||
#define pset(addr, s, val) {shoe.physical_addr=(addr); shoe.physical_size=(s); shoe.physical_dat=(val); physical_set();}
|
||||
|
||||
#define physical_get() physical_get_jump_table[shoe.physical_addr >> 28]()
|
||||
#define pget(addr, s) ({shoe.physical_addr=(addr); shoe.physical_size=(s); physical_get(); shoe.physical_dat;})
|
||||
|
||||
void logical_get (void);
|
||||
@ -479,9 +508,6 @@ void logical_get (void);
|
||||
shoe.logical_dat; \
|
||||
})
|
||||
|
||||
void physical_set (void);
|
||||
#define pset(addr, s, val) {shoe.physical_addr=(addr); shoe.physical_size=(s); shoe.physical_dat=(val); physical_set();}
|
||||
|
||||
void logical_set (void);
|
||||
#define lset_fc(addr, s, val, fc) {\
|
||||
shoe.logical_addr=(addr); \
|
||||
|
15
core/via.c
15
core/via.c
@ -99,10 +99,10 @@ void process_pending_interrupt ()
|
||||
// If the CPU was stopped, unstop it
|
||||
shoe.cpu_thread_notifications &= ~~SHOEBILL_STATE_STOPPED;
|
||||
|
||||
printf("Interrupt pri %u! mask=%u\n", priority, sr_mask());
|
||||
|
||||
const uint16_t vector_offset = (priority + 24) * 4;
|
||||
|
||||
printf("Interrupt pri %u! mask=%u vector_offset=0x%08x\n", priority, sr_mask(), vector_offset);
|
||||
|
||||
// Save the old SR, and switch to supervisor mode
|
||||
const uint16_t old_sr = shoe.sr;
|
||||
set_sr_s(1);
|
||||
@ -119,7 +119,6 @@ void process_pending_interrupt ()
|
||||
push_a7(old_sr, 2);
|
||||
printf("interrupt: pushed sr 0x%04x to 0x%08x\n", old_sr, shoe.a[7]);
|
||||
assert(!shoe.abort);
|
||||
|
||||
|
||||
if (sr_m()) {
|
||||
// clear sr_m, and write a format 1 exception to the ISP
|
||||
@ -137,8 +136,18 @@ void process_pending_interrupt ()
|
||||
assert(!shoe.abort);
|
||||
}
|
||||
|
||||
/*
|
||||
* "When processing an interrupt exception, the MC68020/EC020 first makes an internal copy of the SR,
|
||||
* sets the privilege level to supervisor, suppresses tracing, and sets the processor interrupt mask
|
||||
* level to the level of the interrupt being serviced."
|
||||
*/
|
||||
set_sr_mask(priority);
|
||||
set_sr_t0(0);
|
||||
set_sr_t1(0);
|
||||
|
||||
// Fetch the autovector handler address
|
||||
const uint32_t newpc = lget(shoe.vbr + vector_offset, 4);
|
||||
printf("autovector handler = *0x%08x = 0x%08x\n", shoe.vbr + vector_offset, newpc);
|
||||
assert(!shoe.abort);
|
||||
|
||||
shoe.pc = newpc;
|
||||
|
BIN
web/0.0.2_prefs_general.png
Normal file
BIN
web/0.0.2_prefs_general.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
Loading…
x
Reference in New Issue
Block a user