From cc2bb3c60560657f1abae44a5fabd4793e6a8319 Mon Sep 17 00:00:00 2001 From: Peter Rutenbar Date: Sat, 19 Apr 2014 12:12:15 -0400 Subject: [PATCH] Implemented trapv/trapcc + a few more FPU instructions. Implemented the divide-by-zero exception. Made some progress toward 16/24-bit video. --- .gitignore | 1 + core/core_api.h | 1 + core/cpu.c | 83 +++++++++++++++++++++++++++--- core/exception.c | 9 +--- core/filesystem.c | 2 +- core/fpu.c | 28 ++++++++-- core/video.c | 128 ++++++++++++++++------------------------------ 7 files changed, 148 insertions(+), 104 deletions(-) diff --git a/.gitignore b/.gitignore index ae42782..befdf97 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .DS_Store *.xcworkspace xcuserdata +/gui/build diff --git a/core/core_api.h b/core/core_api.h index ed1e18a..5fedc97 100644 --- a/core/core_api.h +++ b/core/core_api.h @@ -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; diff --git a/core/cpu.c b/core/cpu.c index bf68036..3854557 100644 --- a/core/cpu.c +++ b/core/cpu.c @@ -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]; diff --git a/core/exception.c b/core/exception.c index 56cc605..c771e93 100644 --- a/core/exception.c +++ b/core/exception.c @@ -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; -} \ No newline at end of file diff --git a/core/filesystem.c b/core/filesystem.c index 89280be..220bfb4 100644 --- a/core/filesystem.c +++ b/core/filesystem.c @@ -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; diff --git a/core/fpu.c b/core/fpu.c index 91f9d0c..fffd66f 100644 --- a/core/fpu.c +++ b/core/fpu.c @@ -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[] = { diff --git a/core/video.c b/core/video.c index 15b3739..ced29af 100644 --- a/core/video.c +++ b/core/video.c @@ -26,7 +26,6 @@ #include #include #include -#include #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; } + }