Implemented trapv/trapcc + a few more FPU instructions.

Implemented the divide-by-zero exception.
Made some progress toward 16/24-bit video.
This commit is contained in:
Peter Rutenbar 2014-04-19 12:12:15 -04:00
parent ba8b9e80d1
commit cc2bb3c605
7 changed files with 148 additions and 104 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
.DS_Store
*.xcworkspace
xcuserdata
/gui/build

View File

@ -46,6 +46,7 @@ typedef struct {
typedef struct {
video_ctx_color_t *direct_buf, *clut;
uint8_t *indexed_buf, *rom;
uint8_t *cur_buf;
uint32_t pixels;

View File

@ -69,11 +69,81 @@ global_shoebill_context_t shoe;
})
~inst(trapcc, {
assert(!"trapcc: error: not implemented\n");
~decompose(shoe.op, 0101 cccc 11111 xyz);
// (xyz) == (100) -> sz=0
// (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 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)
throw_frame_two(shoe.sr, next_pc, 7, shoe.orig_pc);
else
shoe.pc = next_pc;
})
~inst(trapv, {
assert(!"trapv: error: not implemented\n");
if (sr_v())
throw_frame_two(shoe.sr, shoe.pc, 7, shoe.orig_pc);
})
~inst(asx_reg, {
@ -344,7 +414,7 @@ global_shoebill_context_t shoe;
const uint16_t divisor = (uint16_t)shoe.dat;
if (divisor == 0) {
throw_divide_by_zero();
throw_frame_two(shoe.orig_sr, shoe.uncommitted_ea_read_pc, 5, shoe.orig_pc);
return ;
}
@ -371,7 +441,7 @@ global_shoebill_context_t shoe;
const int16_t s_divisor = (int16_t)shoe.dat;
if (s_divisor == 0) {
throw_divide_by_zero();
throw_frame_two(shoe.orig_sr, shoe.uncommitted_ea_read_pc, 5, shoe.orig_pc);
return ;
}
@ -976,14 +1046,15 @@ global_shoebill_context_t shoe;
~decompose(shoe.op, 0100 1100 01 MMMMMM);
~decompose(ext, 0 qqq u s 0000000 rrr);
call_ea_read(M, 4);
call_ea_read_commit(M, 4);
const uint32_t divisor = shoe.dat;
if (divisor == 0) {
throw_divide_by_zero();
throw_frame_two(shoe.orig_sr, shoe.uncommitted_ea_read_pc, 5, shoe.orig_pc);
return ;
}
call_ea_read_commit(M, 4);
uint64_t dividend;
if (s)
dividend = (((uint64_t)shoe.d[r])<<32) | shoe.d[q];

View File

@ -239,13 +239,6 @@ void throw_privilege_violation()
//printf("throw_privilege_violation(): I'm throwing a privilege violation exception! (shoe.orig_pc = 0x%08x op=0x%04x\n", shoe.orig_pc, shoe.op);
throw_frame_zero(shoe.orig_sr, shoe.orig_pc, 8);
shoe.abort = 1;
// shoe.abort = 1;
}
void throw_divide_by_zero()
{
printf("throw_divide_by_zero(): I'm throwing a divide-by-zero exception!\n");
assert(0);
shoe.abort = 1;
}

View File

@ -1374,7 +1374,7 @@ done:
uint32_t size;
char error_str[1024];
buf = extract_kernel(argv[1], argv[2], error_str, &size);
buf = shoebill_extract_kernel(argv[1], argv[2], error_str, &size);
if (!buf)
return 0;

View File

@ -1304,10 +1304,17 @@ void inst_fmath(uint16_t op, uint16_t ext)
break;
case ~b(0001000): assert(!"fpu_inst_fetoxm1;");
case ~b(0001001): assert(!"fpu_inst_ftanh;");
case ~b(0001010): assert(!"fpu_inst_fatan;");
case ~b(0001010): // fatan
printf("inst_fatan dest = %Lf source = %Lf\n", dest, source);
result = atanl(source);
break;
case ~b(0001100): assert(!"fpu_inst_fasin;");
case ~b(0001101): assert(!"fpu_inst_fatanh;");
case ~b(0001110): assert(!"fpu_inst_fsin;");
case ~b(0001110): // fsin
printf("inst_fsin dest = %Lf source = %Lf\n", dest, source);
result = sinl(source);
break;
case ~b(0001111): assert(!"fpu_inst_ftan;");
case ~b(0010000): // fetox
printf("inst_fetox dest = %Lf source = %Lf\n", dest, source);
@ -1320,7 +1327,11 @@ void inst_fmath(uint16_t op, uint16_t ext)
case ~b(0010110): assert(!"fpu_inst_flog2;");
case ~b(0011001): assert(!"fpu_inst_fcosh;");
case ~b(0011100): assert(!"fpu_inst_facos;");
case ~b(0011101): assert(!"fpu_inst_fcos;");
case ~b(0011101): // fcos
printf("fpu_inst_fcos dest = %Lf source = %Lf\n", dest, source);
result = cosl(source);
break;
case ~b(0011110): assert(!"fpu_inst_fgetexp;");
case ~b(0011111): assert(!"fpu_inst_fgetman;");
case ~b(0100001):
@ -1380,10 +1391,13 @@ void inst_fmath(uint16_t op, uint16_t ext)
break;
}
case ~b(0011010):
case ~b(1011010):
case ~b(1011110):
assert(!"fpu_inst_fneg;");
assert(!"fneg: can't handle");
case ~b(0011010): // fneg
printf("inst_fneg dest = %Lf source = %Lf\n", dest, source);
result = -source;
break;
case ~b(1000001):
case ~b(1000101):
@ -1458,6 +1472,10 @@ void fpu_setup_jump_table()
fpu_inst_fsqrt,
fpu_inst_flognp1,
fpu_inst_fetox,
fpu_inst_fsin,
fpu_inst_fcos,
fpu_inst_fneg,
fpu_inst_fatan,
};
const fpu_inst_name_t dyadic[] = {

View File

@ -26,7 +26,6 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <GLUT/glut.h>
#include "shoebill.h"
#include "core_api.h"
@ -56,85 +55,6 @@ typedef struct __attribute__ ((__packed__)) {
uint32_t plane_bytes;
} video_params_t;
/*void nubus_video_display_func (void)
{
uint32_t myw = glutGet(GLUT_WINDOW_WIDTH);
uint32_t myh = glutGet(GLUT_WINDOW_HEIGHT);
uint32_t slotnum, i;
int32_t my_window_id = glutGetWindow();
for (slotnum = 0; slotnum < 16; slotnum++)
if (shoe.slots[slotnum].glut_window_id == my_window_id)
break;
video_ctx_t *ctx = (video_ctx_t*)shoe.slots[slotnum].ctx;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, myw, 0, myh, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.1, 0.1, 0.8);
uint32_t gli = 0;
switch (ctx->depth) {
case 1: {
for (i=0; i < ctx->pixels/8; i++) {
const uint8_t byte = ctx->indexed_buf[i];
ctx->direct_buf[i * 8 + 0] = ctx->clut[(byte >> 7) & 1];
ctx->direct_buf[i * 8 + 1] = ctx->clut[(byte >> 6) & 1];
ctx->direct_buf[i * 8 + 2] = ctx->clut[(byte >> 5) & 1];
ctx->direct_buf[i * 8 + 3] = ctx->clut[(byte >> 4) & 1];
ctx->direct_buf[i * 8 + 4] = ctx->clut[(byte >> 3) & 1];
ctx->direct_buf[i * 8 + 5] = ctx->clut[(byte >> 2) & 1];
ctx->direct_buf[i * 8 + 6] = ctx->clut[(byte >> 1) & 1];
ctx->direct_buf[i * 8 + 7] = ctx->clut[(byte >> 0) & 1];
}
break;
}
case 2: {
for (i=0; i < ctx->pixels/4; i++) {
const uint8_t byte = ctx->indexed_buf[i];
ctx->direct_buf[i * 4 + 0] = ctx->clut[(byte >> 6) & 3];
ctx->direct_buf[i * 4 + 1] = ctx->clut[(byte >> 4) & 3];
ctx->direct_buf[i * 4 + 2] = ctx->clut[(byte >> 2) & 3];
ctx->direct_buf[i * 4 + 3] = ctx->clut[(byte >> 0) & 3];
}
break;
}
case 4: {
for (i=0; i < ctx->pixels/2; i++) {
const uint8_t byte = ctx->indexed_buf[i];
ctx->direct_buf[i * 2 + 0] = ctx->clut[(byte >> 4) & 0xf];
ctx->direct_buf[i * 2 + 1] = ctx->clut[(byte >> 0) & 0xf];
}
break;
}
case 8:
for (i=0; i < ctx->pixels; i++)
ctx->direct_buf[i] = ctx->clut[ctx->indexed_buf[i]];
break;
default:
assert(!"unknown depth");
}
glViewport(0, 0, myw, myh);
glRasterPos2i(0, myh);
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_TRUE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelZoom(1.0, -1.0);
glDrawPixels(myw, myh, GL_RGBA, GL_UNSIGNED_BYTE, ctx->direct_buf);
glFlush();
}*/
uint32_t compute_nubus_crc(uint8_t *rom, uint32_t len)
{
uint32_t i, sum = 0;
@ -156,6 +76,15 @@ uint32_t compute_nubus_crc(uint8_t *rom, uint32_t len)
return sum;
}
static void _switch_depth(shoebill_card_video_t *ctx, uint32_t depth)
{
ctx->depth = depth;
if (depth > 8)
ctx->cur_buf = (uint8_t*)ctx->direct_buf;
else
ctx->cur_buf = ctx->indexed_buf;
}
void nubus_video_init(void *_ctx, uint8_t slotnum,
uint16_t width, uint16_t height, uint16_t scanline_width,
double refresh_rate)
@ -172,7 +101,7 @@ void nubus_video_init(void *_ctx, uint8_t slotnum,
ctx->rom = malloc(4096);
// Set the depth and clut for B&W
ctx->depth = 1;
_switch_depth(ctx, 1);
bzero(ctx->clut, 256 * 4);
ctx->clut[0].r = 0xff;
ctx->clut[0].g = 0xff;
@ -199,6 +128,14 @@ void nubus_video_init(void *_ctx, uint8_t slotnum,
params[3].right = htons(width);
params[3].bottom = htons(height);
/*params[4].line_width = htons(scanline_width * 2);
params[4].right = htons(width);
params[4].bottom = htons(height);
params[5].line_width = htons(scanline_width * 4);
params[5].right = htons(width);
params[5].bottom = htons(height);*/
// Recompute the rom crc
compute_nubus_crc(ctx->rom, 4096);
@ -274,8 +211,30 @@ void nubus_video_write_func(const uint32_t rawaddr, const uint32_t size,
break;
}
case 1: { // Set depth
const uint32_t depth = 1 << (data - 128); // FIXME: this won't work for direct mode
ctx->depth = depth;
uint32_t newdepth;
switch (data) {
case 128:
newdepth = 1;
break;
case 129:
newdepth = 2;
break;
case 130:
newdepth = 4;
break;
case 131:
newdepth = 8;
break;
case 132:
newdepth = 16;
break;
case 133:
newdepth = 32;
break;
default:
assert(!"driver tried to set bogus depth");
}
_switch_depth(ctx, newdepth);
printf("nubus_magic: set depth = %u\n", ctx->depth);
break;
}
@ -312,13 +271,14 @@ void nubus_video_write_func(const uint32_t rawaddr, const uint32_t size,
}
// Else, this is video ram
// uint32_t i, myaddr = addr % ctx->indexed_buf_len, mydata = data;
uint32_t myaddr, mydata;
for (myaddr = addr + size, mydata = data; addr < myaddr; ) {
// assert(myaddr < ctx->pixels)
ctx->indexed_buf[(--myaddr) % ctx->pixels] = mydata & 0xff;
mydata >>= 8;
}
}