From 96af9667b6b408bf1d6a684d508634eb27702325 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Mon, 17 Apr 2023 16:24:36 +0100 Subject: bus/gio64/newport.cpp, cpu/mips/mips3.cpp: Fixed issues affecting IRIX. (#11117) * cpu/mips/mips3.cpp: Sign-extend result of COP0 LL instruction. * cpu/mips/mips3.cpp: Ported COP0 Random implementation from new R4000 interpreter. * bus/gio64/newport.cpp: Use octant encoding used by hardware, and fixed Scr2Scr. --- src/devices/bus/gio64/newport.cpp | 162 +++++++++++++++++--------------------- src/devices/cpu/mips/mips3.cpp | 19 ++--- 2 files changed, 81 insertions(+), 100 deletions(-) diff --git a/src/devices/bus/gio64/newport.cpp b/src/devices/bus/gio64/newport.cpp index 8ba637d91db..06f01ae0cd5 100644 --- a/src/devices/bus/gio64/newport.cpp +++ b/src/devices/bus/gio64/newport.cpp @@ -2701,20 +2701,33 @@ uint32_t newport_base_device::get_rgb_color(int16_t x, int16_t y) uint8_t newport_base_device::get_octant(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t dx, int32_t dy) { - if (x1 < x2) - { - if (y2 < y1) - return (dx > dy) ? 0 : 1; - else - return (dx > dy) ? 7 : 6; - } - else - { - if (y2 < y1) - return (dx > dy) ? 3 : 2; - else - return (dx > dy) ? 4 : 5; - } + uint8_t octant = 0; + + // Octant format: {MSB, 2nd, LSB} = {XMAJOR, XDEC, YDEC} + // Mapping of hardware octant to peseudocode octant in manual + // | Pseudocode | hardware | hardware(dec) | + // | 1 | 3'b101 | 5 | + // | 2 | 3'b001 | 1 | + // | 3 | 3'b011 | 3 | + // | 4 | 3'b111 | 7 | + // | 5 | 3'b110 | 6 | + // | 6 | 3'b010 | 2 | + // | 7 | 3'b000 | 0 | + // | 8 | 3'b100 | 4 | + + /* YDEC */ + if (y1 > y2) + octant |= (1 << 0); // Bit 0 + + /* XDEC */ + if (x1 > x2) + octant |= (1 << 1); // Bit 1 + + /* XMAJOR */ + if (dx > dy) + octant |= (1 << 2); // Bit 2 + + return octant; } void newport_base_device::do_setup(void) @@ -2725,39 +2738,13 @@ void newport_base_device::do_setup(void) const int32_t y2 = util::sext(m_rex3.m_y_end >> 7, 20); const int32_t dx = abs(x1 - x2); const int32_t dy = abs(y1 - y2); - const uint8_t adrmode = (m_rex3.m_draw_mode0 >> 2) & 7; - if (adrmode >= 0 && adrmode <= 1) - { - /* quadrant for block or span */ - uint8_t quadrant = 0; - /* This is purely guessed */ - if (x1 > x2) - { - if (y1 > y2) - quadrant = 3; - else - quadrant = 2; - } - else - { - if (y1 > y2) - quadrant = 1; - else - quadrant = 0; - } - m_rex3.m_bres_octant_inc1 &= ~(0x7 << 24); - m_rex3.m_bres_octant_inc1 |= quadrant << 24; - } - else if (adrmode >= 2 && adrmode <= 4) - { - uint8_t octant; - /* octant for line */ - /* FIXME: error terms and Bresenham terms */ - octant = get_octant(x1, y1, x2, y2, dx, dy); - m_rex3.m_bres_octant_inc1 &= ~(0x7 << 24); - m_rex3.m_bres_octant_inc1 |= octant << 24; - } + /* octant for line and block, span */ + const uint8_t octant = get_octant(x1, y1, x2, y2, dx, dy); + m_rex3.m_bres_octant_inc1 &= ~(0x7 << 24); + m_rex3.m_bres_octant_inc1 |= (uint32_t)octant << 24; + /* FIXME: error terms (incr1, incr2) and Bresenham terms (d) */ + LOGMASKED(LOG_REX3, "do_setup: octant = %d, x1 = %d, y1 = %d, x2 = %d, y2 = %d, dx = %d, dy = %d\n", octant, x1, y1, x2, y2, dx, dy); } void newport_base_device::do_fline(uint32_t color) @@ -2792,14 +2779,14 @@ void newport_base_device::do_fline(uint32_t color) static const bresenham_octant_info_t s_bresenham_infos[8] = { - { 1, 1, 0, 1, 0 }, - { 0, 1, 1, 1, 1 }, - { 0, -1, 1, 1, 1 }, - { -1, -1, 0, 1, 0 }, - { -1, -1, 0, -1, 0 }, - { 0, -1, -1, -1, 1 }, - { 0, 1, -1, -1, 1 }, - { 1, 1, 0, -1, 0 } + { 0, 1, -1, -1, 1 }, // Pseudo 7 + { 0, 1, 1, 1, 1 }, // Pseudo 2 + { 0, -1, -1, -1, 1 }, // Pseudo 6 + { 0, -1, 1, 1, 1 }, // Pseudo 3 + { 1, 1, 0, -1, 0 }, // Pseudo 8 + { 1, 1, 0, 1, 0 }, // Pseudo 1 + { -1, -1, 0, -1, 0 }, // Pseudo 5 + { -1, -1, 0, 1, 0 } // Pseudo 4 }; const uint8_t octant = (m_rex3.m_bres_octant_inc1 >> 24) & 0x7; @@ -2818,10 +2805,10 @@ void newport_base_device::do_fline(uint32_t color) switch (octant) { - case 0: + case 5: // Pseudo 1 // Nothing special needed break; - case 1: + case 1: // Pseudo 2 { const int16_t temp_fract = x1_fract; x1_fract = y1_fract; @@ -2831,7 +2818,7 @@ void newport_base_device::do_fline(uint32_t color) dy = temp_d; break; } - case 2: + case 3: // Pseudo 3 { const int16_t temp_fract = 0x10 - x1_fract; x1_fract = y1_fract; @@ -2841,14 +2828,14 @@ void newport_base_device::do_fline(uint32_t color) dy = temp_d; break; } - case 3: + case 7: // Pseudo 4 x1_fract = 0x10 - x1_fract; break; - case 4: + case 6: // Pseudo 5 x1_fract = 0x10 - x1_fract; y1_fract = 0x10 - y1_fract; break; - case 5: + case 2: // Pseudo 6 { const int16_t temp_fract = 0x10 - x1_fract; x1_fract = 0x10 - y1_fract; @@ -2858,7 +2845,7 @@ void newport_base_device::do_fline(uint32_t color) dy = temp_d; break; } - case 6: + case 0: // Pseudo 7 { const int16_t temp_fract = 0x10 - y1_fract; y1_fract = x1_fract; @@ -2868,7 +2855,7 @@ void newport_base_device::do_fline(uint32_t color) dy = temp_d; break; } - case 7: + case 4: // Pseudo 8 y1_fract = 0x10 - y1_fract; break; } @@ -2983,14 +2970,14 @@ void newport_base_device::do_iline(uint32_t color) static const bresenham_octant_info_t s_bresenham_infos[8] = { - { 1, 1, 0, 1, 0 }, - { 0, 1, 1, 1, 1 }, - { 0, -1, 1, 1, 1 }, - { -1, -1, 0, 1, 0 }, - { -1, -1, 0, -1, 0 }, - { 0, -1, -1, -1, 1 }, - { 0, 1, -1, -1, 1 }, - { 1, 1, 0, -1, 0 } + { 0, 1, -1, -1, 1 }, // Pseudo 7 + { 0, 1, 1, 1, 1 }, // Pseudo 2 + { 0, -1, -1, -1, 1 }, // Pseudo 6 + { 0, -1, 1, 1, 1 }, // Pseudo 3 + { 1, 1, 0, -1, 0 }, // Pseudo 8 + { 1, 1, 0, 1, 0 }, // Pseudo 1 + { -1, -1, 0, -1, 0 }, // Pseudo 5 + { -1, -1, 0, 1, 0 } // Pseudo 4 }; const uint8_t octant = (m_rex3.m_bres_octant_inc1 >> 24) & 0x7; @@ -3092,7 +3079,6 @@ void newport_base_device::do_iline(uint32_t color) uint32_t newport_base_device::do_pixel_read() { - m_rex3.m_bres_octant_inc1 = 0; const int16_t src_x = m_rex3.m_x_start_i + m_rex3.m_x_window - 0x1000; const int16_t src_y = m_rex3.m_y_start_i + m_rex3.m_y_window - 0x1000; uint32_t ret = 0; @@ -3342,8 +3328,9 @@ void newport_base_device::do_rex3_command() int16_t end_x = m_rex3.m_x_end_i; int16_t end_y = m_rex3.m_y_end_i; int16_t dx = 1, dy = 1; + int8_t octant; - LOGMASKED(LOG_COMMANDS, "REX3 Command: %08x|%08x - %s %s\n", mode0, mode1, s_opcode_str[mode0 & 3], s_adrmode_str[(mode0 >> 2) & 7]); + LOGMASKED(LOG_COMMANDS, "REX3 Command: %08x|%08x - %s %s %s\n", mode0, mode1, s_opcode_str[mode0 & 3], s_adrmode_str[(mode0 >> 2) & 7], BIT(mode0, 5) ? "Setup" : "NoSetup"); const uint8_t opcode = mode0 & 3; const uint8_t adrmode = (mode0 >> 2) & 7; @@ -3353,31 +3340,18 @@ void newport_base_device::do_rex3_command() case 0: // NoOp break; case 1: // Read + if (BIT(mode0, 5)) + do_setup(); + // Our do_pixel_word_read does not use octant, but seems like hardware is still updating it m_rex3.m_host_dataport = do_pixel_word_read(); break; case 2: // Draw if (BIT(mode0, 5)) do_setup(); + octant = (m_rex3.m_bres_octant_inc1 >> 24) & 0x7; + dx = BIT(octant, 1) ? -1 : 1; + dy = BIT(octant, 0) ? -1 : 1; - switch ((m_rex3.m_bres_octant_inc1 >> 24) & 0x3) - { - case 0: - dx = 1; - dy = 1; - break; - case 1: - dx = 1; - dy = -1; - break; - case 2: - dx = -1; - dy = 1; - break; - case 3: - dx = -1; - dy = -1; - break; - } switch (adrmode) { case 0: // Span @@ -3548,6 +3522,12 @@ void newport_base_device::do_rex3_command() const bool stop_on_x = BIT(mode0, 8); const bool stop_on_y = BIT(mode0, 9); + if (BIT(mode0, 5)) + do_setup(); + octant = (m_rex3.m_bres_octant_inc1 >> 24) & 0x7; + dx = BIT(octant, 1) ? -1 : 1; + dy = BIT(octant, 0) ? -1 : 1; + end_x += dx; end_y += dy; diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index 2775353b1a0..fa245e00135 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -441,9 +441,9 @@ void mips3_device::device_start() for (int regnum = 0; regnum < 32; regnum++) { char buf[10]; - sprintf(buf, "r%d", regnum); + snprintf(buf, 10, "r%d", regnum); m_drcuml->symbol_add(&m_core->r[regnum], sizeof(m_core->r[regnum]), buf); - sprintf(buf, "f%d", regnum); + snprintf(buf, 10, "f%d", regnum); m_drcuml->symbol_add(&m_core->cpr[1][regnum], sizeof(m_core->cpr[1][regnum]), buf); } m_drcuml->symbol_add(&m_core->r[REG_LO], sizeof(m_core->r[REG_LO]), "lo"); @@ -1881,12 +1881,13 @@ uint64_t mips3_device::get_cop0_reg(int idx) } else if (idx == COP0_Random) { - int wired = m_core->cpr[0][COP0_Wired] & 0x3f; - int range = 48 - wired; - if (range > 0) - return ((total_cycles() - m_core->count_zero_time) % range + wired) & 0x3f; - else - return 47; + uint32_t wired = m_core->cpr[0][COP0_Wired] & 0x3f; + uint32_t unwired = m_tlbentries - wired; + + if (unwired == 0) + return m_tlbentries - 1; + + return (generate_tlb_index() % unwired) + wired; } return m_core->cpr[0][idx]; } @@ -5397,7 +5398,7 @@ void mips3_device::execute_run() { // Should actually use physical address m_core->cpr[0][COP0_LLAddr] = SIMMVAL + RSVAL32; - RTVAL64 = temp; + RTVAL64 = int64_t(int32_t(temp)); m_core->llbit = 1; if LL_BREAK machine().debug_break(); -- cgit v1.2.3