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:
Peter Rutenbar 2014-04-26 13:35:56 -04:00
parent cc2bb3c605
commit 9f0e6ed115
16 changed files with 942 additions and 936 deletions

View File

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

View File

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

View File

@ -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 (Im 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 cant 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 cant 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!

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB