diff --git a/src/devices/cpu/sparc/mb86901.cpp b/src/devices/cpu/sparc/mb86901.cpp index 2bf8e1ba284..fea2908952f 100644 --- a/src/devices/cpu/sparc/mb86901.cpp +++ b/src/devices/cpu/sparc/mb86901.cpp @@ -26,6 +26,14 @@ const device_type MB86901 = &device_creator; const int mb86901_device::NWINDOWS = 7; +#if LOG_FCODES +#include "ss1fcode.ipp" +#endif + +#if SPARCV8 +#include "sparcv8ops.ipp" +#endif + //------------------------------------------------- // mb86901_device - constructor //------------------------------------------------- @@ -40,13 +48,87 @@ mb86901_device::mb86901_device(const machine_config &mconfig, const char *tag, d void mb86901_device::device_start() { +#if LOG_FCODES + m_ss1_fcode_table.clear(); + FILE* input = fopen("names.txt", "rb"); + + if (input != NULL) + { + fseek(input, 0, SEEK_END); + size_t filesize = ftell(input); + fseek(input, 0, SEEK_SET); + + UINT8 *buf = new UINT8[filesize]; + fread(buf, 1, filesize, input); + fclose(input); + + size_t pos = 0; + while (pos < filesize) + { + // eat newlines + while (pos < filesize && (buf[pos] == 0x0d || buf[pos] == 0x0a)) + pos++; + + if (pos >= filesize) + break; + + // get opcode + UINT16 opcode = 0; + for (int shift = 12; shift >= 0 && pos < filesize; shift -= 4) + { + UINT8 digit = buf[pos]; + if (digit >= 'a' && digit <= 'z') + { + digit &= ~0x20; + } + + if (digit >= '0' && digit <= '9') + { + opcode |= (digit - 0x30) << shift; + } + else if (digit >= 'A' && digit <= 'F') + { + opcode |= ((digit - 0x41) + 10) << shift; + } + pos++; + } + + if (pos >= filesize) + break; + + // skip " : " + pos += 3; + + if (pos >= filesize) + break; + + // read description + std::string description; + while (buf[pos] != ';' && pos < filesize) + { + description += char(buf[pos]); + pos++; + } + + if (pos >= filesize) + break; + + if (buf[pos] == ';') + pos++; + + m_ss1_fcode_table[opcode & ~1] = description; + } + delete [] buf; + } +#endif m_bp_reset_in = false; - m_bp_irl = 0; m_bp_fpu_present = false; m_bp_cp_present = false; m_pb_error = false; m_pb_block_ldst_byte = false; m_pb_block_ldst_word = false; + m_bp_irl = 0; + m_irq_state = 0; memset(m_dbgregs, 0, 24 * sizeof(UINT32)); @@ -298,6 +380,9 @@ void mb86901_device::device_reset() m_fpu_sequence_err = 0; m_cp_sequence_err = 0; + m_bp_irl = 0; + m_irq_state = 0; + m_asi = 0; MAE = false; HOLD_BUS = false; @@ -329,6 +414,14 @@ void mb86901_device::device_reset() m_regs[i] = m_r + i; } update_gpr_pointers(); + +#if LOG_FCODES + m_ss1_next_pc = ~0; + m_ss1_next_opcode = ~0; + m_ss1_next_handler_base = ~0; + m_ss1_next_entry_point = ~0; + m_ss1_next_stack = ~0; +#endif } @@ -495,7 +588,7 @@ UINT32 mb86901_device::execute_max_cycles() const UINT32 mb86901_device::execute_input_lines() const { - return 0; + return 16; } @@ -506,13 +599,53 @@ UINT32 mb86901_device::execute_input_lines() const void mb86901_device::execute_set_input(int inputnum, int state) { + switch (inputnum) + { + case SPARC_IRQ1: + case SPARC_IRQ2: + case SPARC_IRQ3: + case SPARC_IRQ4: + case SPARC_IRQ5: + case SPARC_IRQ6: + case SPARC_IRQ7: + case SPARC_IRQ8: + case SPARC_IRQ9: + case SPARC_IRQ10: + case SPARC_IRQ11: + case SPARC_IRQ12: + case SPARC_IRQ13: + case SPARC_IRQ14: + case SPARC_NMI: + { + int index = (inputnum - SPARC_IRQ1) + 1; + if (state) + { + m_irq_state |= 1 << index; + } + else + { + m_irq_state &= ~(1 << index); + } + + for(index = 15; index > 0; index--) + { + if (m_irq_state & (1 << index)) + { + break; + } + } + + m_bp_irl = index; + break; + } + + case SPARC_MAE: + m_mae = (state != 0) ? 1 : 0; + break; + } } -#if SPARCV8 -#include "sparcv8ops.ipp" -#endif - //------------------------------------------------- // execute_add - execute an add-type opcode //------------------------------------------------- @@ -541,14 +674,14 @@ void mb86901_device::execute_add(UINT32 op) ((not result<31>) and (r[rs1]<31> or operand2<31>)) ); */ + UINT32 rs1 = RS1REG; UINT32 operand2 = USEIMM ? SIMM13 : RS2REG; UINT32 result = 0; if (ADD || ADDCC) - result = RS1REG + operand2; + result = rs1 + operand2; else if (ADDX || ADDXCC) - result = RS1REG + operand2 + ICC_C; - + result = rs1 + operand2 + ICC_C; if (RD != 0) RDREG = result; @@ -558,10 +691,10 @@ void mb86901_device::execute_add(UINT32 op) CLEAR_ICC; PSR |= (BIT31(result)) ? PSR_N_MASK : 0; PSR |= (result == 0) ? PSR_Z_MASK : 0; - PSR |= ((BIT31(RS1REG) && BIT31(operand2) && !BIT31(result)) || - (!BIT31(RS1REG) && !BIT31(operand2) && BIT31(result))) ? PSR_V_MASK : 0; - PSR |= ((BIT31(RS1REG) && BIT31(operand2)) || - (!BIT31(result) && (BIT31(RS1REG) || BIT31(operand2)))) ? PSR_C_MASK : 0; + PSR |= ((BIT31(rs1) && BIT31(operand2) && !BIT31(result)) || + (!BIT31(rs1) && !BIT31(operand2) && BIT31(result))) ? PSR_V_MASK : 0; + PSR |= ((BIT31(rs1) && BIT31(operand2)) || + (!BIT31(result) && (BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; } } @@ -598,13 +731,14 @@ void mb86901_device::execute_taddcc(UINT32 op) r[rd] <- result; ); */ + UINT32 rs1 = RS1REG; UINT32 operand2 = USEIMM ? SIMM13 : RS2REG; - UINT32 result = RS1REG + operand2; + UINT32 result = rs1 + operand2; - bool temp_v = (BIT31(RS1REG) && BIT31(operand2) && !BIT31(result)) || - (!BIT31(RS1REG) && !BIT31(operand2) && BIT31(result)) || - ((RS1REG & 3) != 0 || (RS1REG & 3) != 0) ? true : false; + bool temp_v = (BIT31(rs1) && BIT31(operand2) && !BIT31(result)) || + (!BIT31(rs1) && !BIT31(operand2) && BIT31(result)) || + ((rs1 & 3) != 0 || (operand2 & 3) != 0) ? true : false; if (TADDCCTV && temp_v) { @@ -617,8 +751,8 @@ void mb86901_device::execute_taddcc(UINT32 op) PSR |= (BIT31(result)) ? PSR_N_MASK : 0; PSR |= (result == 0) ? PSR_Z_MASK : 0; PSR |= temp_v ? PSR_V_MASK : 0; - PSR |= ((BIT31(RS1REG) && BIT31(operand2)) || - (!BIT31(result) && (BIT31(RS1REG) || BIT31(operand2)))) ? PSR_C_MASK : 0; + PSR |= ((BIT31(rs1) && BIT31(operand2)) || + (!BIT31(result) && (BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; if (RD != 0) RDREG = result; @@ -655,13 +789,14 @@ void mb86901_device::execute_sub(UINT32 op) (result<31> and ((not r[rs1]<31>) or operand2<31>)) ); */ + UINT32 rs1 = RS1REG; UINT32 operand2 = USEIMM ? SIMM13 : RS2REG; UINT32 result = 0; if (SUB || SUBCC) - result = RS1REG - operand2; + result = rs1 - operand2; else if (SUBX || SUBXCC) - result = RS1REG - operand2 - ICC_C; + result = rs1 - operand2 - ICC_C; if (RD != 0) RDREG = result; @@ -671,10 +806,10 @@ void mb86901_device::execute_sub(UINT32 op) CLEAR_ICC; PSR |= (BIT31(result)) ? PSR_N_MASK : 0; PSR |= (result == 0) ? PSR_Z_MASK : 0; - PSR |= ((BIT31(RS1REG) && !BIT31(operand2) && !BIT31(result)) || - (!BIT31(RS1REG) && BIT31(operand2) && BIT31(result))) ? PSR_V_MASK : 0; - PSR |= ((!BIT31(RS1REG) && BIT31(operand2)) || - (BIT31(result) && (!BIT31(RS1REG) || BIT31(operand2)))) ? PSR_C_MASK : 0; + PSR |= ((BIT31(rs1) && !BIT31(operand2) && !BIT31(result)) || + (!BIT31(rs1) && BIT31(operand2) && BIT31(result))) ? PSR_V_MASK : 0; + PSR |= ((!BIT31(rs1) && BIT31(operand2)) || + (BIT31(result) && (!BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; } } @@ -712,13 +847,14 @@ void mb86901_device::execute_tsubcc(UINT32 op) ); */ + UINT32 rs1 = RS1REG; UINT32 operand2 = USEIMM ? SIMM13 : RS2REG; - UINT32 result = RS1REG - operand2; + UINT32 result = rs1 - operand2; - bool temp_v = (BIT31(RS1REG) && !BIT31(operand2) && !BIT31(result)) || - (!BIT31(RS1REG) && BIT31(operand2) && BIT31(result)) || - ((RS1REG & 3) != 0 || (RS1REG & 3) != 0) ? true : false; + bool temp_v = (BIT31(rs1) && !BIT31(operand2) && !BIT31(result)) || + (!BIT31(rs1) && BIT31(operand2) && BIT31(result)) || + ((rs1 & 3) != 0 || (operand2 & 3) != 0) ? true : false; if (TSUBCCTV && temp_v) { @@ -731,8 +867,8 @@ void mb86901_device::execute_tsubcc(UINT32 op) PSR |= (BIT31(result)) ? PSR_N_MASK : 0; PSR |= (result == 0) ? PSR_Z_MASK : 0; PSR |= temp_v ? PSR_V_MASK : 0; - PSR |= ((!BIT31(RS1REG) && BIT31(operand2)) || - (BIT31(result) && (!BIT31(RS1REG) || BIT31(operand2)))) ? PSR_C_MASK : 0; + PSR |= ((!BIT31(rs1) && BIT31(operand2)) || + (BIT31(result) && (!BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; if (RD != 0) RDREG = result; @@ -1111,8 +1247,14 @@ void mb86901_device::execute_rett(UINT32 op) if (ET) { m_trap = 1; - if (IS_USER) m_privileged_instruction = 1; - else m_illegal_instruction = 1; + if (IS_USER) + { + m_privileged_instruction = 1; + } + else + { + m_illegal_instruction = 1; + } } else if (IS_USER) { @@ -1129,7 +1271,6 @@ void mb86901_device::execute_rett(UINT32 op) m_tt = 6; m_execute_mode = 0; m_error_mode = 1; - } else if (address & 3) { @@ -1384,9 +1525,11 @@ void mb86901_device::execute_group2(UINT32 op) #endif default: + { m_trap = 1; m_illegal_instruction = 1; break; + } } } @@ -2408,6 +2551,7 @@ void mb86901_device::select_trap() if (m_reset_trap) { + m_reset_trap = 0; m_trap = 0; return; } @@ -2457,6 +2601,7 @@ void mb86901_device::select_trap() else if (m_interrupt_level > 0) m_tt = 0x10 | m_interrupt_level; + TBR |= m_tt << 4; m_instruction_access_exception = 0; m_illegal_instruction = 0; m_privileged_instruction = 0; @@ -2472,6 +2617,7 @@ void mb86901_device::select_trap() m_division_by_zero = 0; m_trap_instruction = 0; m_interrupt_level = 0; + m_mae = 0; } @@ -2563,7 +2709,9 @@ void mb86901_device::execute_trap() */ if (!m_trap) + { return; + } select_trap(); @@ -2702,7 +2850,6 @@ void mb86901_device::dispatch_instruction(UINT32 op) { m_trap = 1; m_illegal_instruction = 1; - } if (((OP == OP_ALU && (FPOP1 || FPOP2)) || (OP == OP_TYPE0 && OP2 == OP2_FBFCC)) && (!EF || !m_bp_fpu_present)) { @@ -2731,7 +2878,6 @@ void mb86901_device::complete_fp_execution(UINT32 /*op*/) { } - //------------------------------------------------- // execute_step - perform one step in execute // mode (versus error or reset modes) @@ -2812,7 +2958,7 @@ void mb86901_device::execute_step() UINT32 addr_space = (IS_USER ? 8 : 9); UINT32 op = read_sized_word(addr_space, PC, 4); -#if 0 +#if LOG_FCODES if (PC == 0xffef0000) { UINT32 opcode = read_sized_word(11, REG(5), 2); @@ -2820,252 +2966,47 @@ void mb86901_device::execute_step() { opcode >>= 16; } - UINT32 l1 = opcode << 2; - l1 += REG(2); - UINT32 handler_offset = read_sized_word(11, l1, 2); - if (!(l1 & 2)) + + UINT32 handler_base = opcode << 2; + handler_base += REG(2); // l1 = r2 + opcode << 2 + + UINT32 entry_point = read_sized_word(11, handler_base, 2); + if (!(handler_base & 2)) { - handler_offset >>= 16; + entry_point >>= 16; } - handler_offset <<= 2; - handler_offset += REG(2); - if (handler_offset == 0xffe87964) + entry_point <<= 2; + entry_point += REG(2); // l0 = r2 + entry_point << 2 + +#if 0 + // Doesn't seem to work + UINT32 name_length_addr = (REG(2) + ((opcode & ~1) << 2)) - 1; + UINT32 name_length_shift = (3 - (name_length_addr & 3)) * 8; + UINT32 name_length = (read_sized_word(11, name_length_addr, 1) >> name_length_shift) & 0x7f; + UINT32 name_start_addr = name_length_addr - name_length; + char name_buf[129]; + memset(name_buf, 0, 129); + if (name_length > 0) { - printf("Opcode at %08x: %04x, handler is at %08x // call %08x\n", REG(5), opcode, handler_offset, l1 + 2); - } - else if (handler_offset == 0xffe8799c) - { - UINT32 address = REG(5) + 2; - UINT32 half = read_sized_word(11, address, 2); - if (!(address & 2)) half >>= 16; - - printf("Opcode at %08x: %04x, handler is at %08x // push_data current result (%08x) + load address %08x\n", REG(5), opcode, handler_offset, REG(4), REG(3) + half); - } - else if (handler_offset == 0xffe879e4) - { - UINT32 address = l1 + 2; - UINT32 half0 = read_sized_word(11, address, 2); - if (address & 2) half0 <<= 16; - - address = l1 + 4; - UINT32 half1 = read_sized_word(11, address, 2); - if (!(address & 2)) half1 >>= 16; - - UINT32 value = half0 | half1; - - printf("Opcode at %08x: %04x, handler is at %08x // push_data current result (%08x) + load immediate word from handler table (%08x)\n", REG(5), opcode, handler_offset, REG(4), value); - } - else if (handler_offset == 0xffe879c4) - { - UINT32 address = l1 + 2; - UINT32 l0 = read_sized_word(11, address, 2); - if (!(address & 2)) l0 >>= 16; - - address = REG(3) + l0; - UINT32 l1_2 = read_sized_word(11, address, 2); - if (!(address & 2)) l1_2 >>= 16; - - address = REG(2) + (l1_2 << 2); - UINT32 l0_2 = read_sized_word(11, address, 2); - if (!(address & 2)) l0_2 >>= 16; - - UINT32 dest = REG(2) + (l0_2 << 2); - - printf("Opcode at %08x: %04x, handler is at %08x // SPARC branch to %08x, calcs: g2(%08x) + halfword[g2(%04x) + (halfword[g3(%08x) + halfword[entry_point(%04x) + 2](%04x)](%04x) << 2)](%08x)\n", REG(5), opcode, handler_offset, dest, REG(2), REG(2), REG(3), l1, l0, l1_2, l0_2); - printf(" // Target func: %08x\n", l0_2 << 2); - switch (l0_2 << 2) + for (int i = 0; i < name_length; i++) { - case 0x10: // call - printf(" // call %08x\n", (REG(2) + (l1_2 << 2)) + 2); - break; - default: - printf(" // unknown handler address: %08x\n", REG(2) + (l0_2 << 2)); - break; + UINT32 char_addr = name_start_addr + i; + UINT32 char_shift = (3 - (char_addr & 3)) * 8; + name_buf[i] = (read_sized_word(11, char_addr, 1) >> char_shift) & 0xff; } } - else if (handler_offset == 0xffe8c838) - { - UINT32 address = l1 + 2; - UINT32 half0 = read_sized_word(11, address, 2); - if (address & 2) half0 <<= 16; +#endif - address = l1 + 4; - UINT32 half1 = read_sized_word(11, address, 2); - if (!(address & 2)) half1 >>= 16; - - UINT32 value = half0 | half1; - - printf("Opcode at %08x: %04x, handler is at %08x // add 32-bit word (%08x) from handler table to result (%08x + %08x = %08x)\n", REG(5), opcode, handler_offset, value, REG(4), value, REG(4) + value); - } - else if (opcode == 0x003f || opcode == 0x0066 || opcode == 0x0099 || opcode == 0x0121 || opcode == 0x0136 || opcode == 0x014f || opcode == 0x0155 || opcode == 0x01c7 || opcode == 0x01cd || - opcode == 0x0217 || opcode == 0x0289 || opcode == 0x0296 || opcode == 0x029d || opcode == 0x02f2 || opcode == 0x0334 || opcode == 0x0381 || opcode == 0x3d38) - { - switch(opcode) - { - case 0x003f: - { - UINT32 address = REG(5) + 2; - UINT32 half0 = read_sized_word(11, address, 2); - if (address & 2) half0 <<= 16; - - address = REG(5) + 4; - UINT32 half1 = read_sized_word(11, address, 2); - if (!(address & 2)) half1 >>= 16; - - UINT32 value = half0 | half1; - - printf("Opcode at %08x: %04x, handler is at %08x // push_data current result (%08x) + load immediate word from instructions (%08x)\n", REG(5), opcode, handler_offset, REG(4), value); - break; - } - - case 0x0066: - { - UINT32 address = REG(5) + 2; - UINT32 offset = read_sized_word(11, address, 2); - if (!(address & 2)) offset >>= 16; - - UINT32 target = REG(5) + 2 + offset; - - printf("Opcode at %08x: %04x, handler is at %08x // if result (%08x) is zero, jump to %08x\n", REG(5), opcode, handler_offset, REG(4), target); - break; - } - - case 0x0099: - { - UINT32 l1_2 = REG(4); - - UINT32 address = REG(7); - UINT32 l0_2 = read_sized_word(11, address, 4); - - address = REG(7) + 4; - UINT32 popped_g4 = read_sized_word(11, address, 4); - - address = REG(5) + 2; - UINT32 offset = read_sized_word(11, address, 2); - if (!(address & 2)) offset >>= 16; - - UINT32 target = REG(5) + 2 + offset; - - printf("Opcode at %08x: %04x, handler is at %08x // branch relative to %08x if data stack pop/top (%08x) == result (%08x), pop_data result (%08x)\n", REG(5), opcode, handler_offset, target, l0_2, l1_2, popped_g4); - if (l1_2 == l0_2) - { - printf(" // branch will be taken\n"); - } - else - { - printf(" // branch will not be taken\n"); - printf(" // push pc (%08x) onto program stack\n", REG(5) + 2); - printf(" // push previous data stack top + 0x80000000 (%08x) onto program stack\n", l0_2 + 0x8000000); - printf(" // push diff of (result - stack top) (%08x - %08x = %08x)\n", popped_g4, l0_2 + 0x8000000, popped_g4 - (l0_2 + 0x80000000)); - } - - break; - } - - case 0x0121: - { - UINT32 address = REG(7); - UINT32 word = read_sized_word(11, address, 4); - printf("Opcode at %08x: %04x, handler is at %08x // logical-AND result with data stack pop, store in result: %08x = %08x & %08x\n", REG(5), opcode, handler_offset, word & REG(4), word, REG(4)); - break; - } - - case 0x0136: - printf("Opcode at %08x: %04x, handler is at %08x // invert result (%08x -> %08x)\n", REG(5), opcode, handler_offset, REG(4), REG(4) ^ 0xffffffff); - break; - - case 0x014f: - { - UINT32 address = REG(7); - UINT32 word = read_sized_word(11, address, 4); - printf("Opcode at %08x: %04x, handler is at %08x // add result to data stack pop, store in result: %08x = %08x + %08x\n", REG(5), opcode, handler_offset, word + REG(4), word, REG(4)); - break; - } - - case 0x0155: - { - UINT32 address = REG(7); - UINT32 word = read_sized_word(11, address, 4); - printf("Opcode at %08x: %04x, handler is at %08x // subtract result from data stack pop, store in result: %08x = %08x - %08x\n", REG(5), opcode, handler_offset, word - REG(4), word, REG(4)); - break; - } - - case 0x01c7: - { - UINT32 address = REG(6); - UINT32 half0 = read_sized_word(11, address, 2); - if (address & 2) half0 <<= 16; - - address = REG(6) + 2; - UINT32 half1 = read_sized_word(11, address, 2); - if (!(address & 2)) half1 >>= 16; - - UINT32 value = half0 | half1; - - printf("Opcode at %08x: %04x, handler is at %08x // return (%08x) (pops off program stack)\n", REG(5), opcode, handler_offset, value); - break; - } - - case 0x01cd: - printf("Opcode at %08x: %04x, handler is at %08x // insert result (%08x) between data stack top (%08x) and next data stack entry\n", REG(5), opcode, handler_offset, REG(4), read_sized_word(11, REG(7), 4)); - break; - - case 0x0217: - { - UINT32 value = read_sized_word(11, REG(7), 4); - printf("Opcode at %08x: %04x, handler is at %08x // if pop_data (%08x) >= result (%08x), set result to 0, otherwise -1 (%08x)\n", REG(5), opcode, handler_offset, value, REG(4), (value >= REG(4)) ? 0 : ~0); - break; - } - - case 0x0289: - printf("Opcode at %08x: %04x, handler is at %08x // push_data(g4 (%08x))\n", REG(5), opcode, handler_offset, REG(4)); - break; - - case 0x0296: - printf("Opcode at %08x: %04x, handler is at %08x // swap result (%08x) with top of data stack (%08x)\n", REG(5), opcode, handler_offset, REG(4), read_sized_word(11, REG(7), 4)); - break; - - case 0x029d: - { - UINT32 top = read_sized_word(11, REG(7), 4); - UINT32 next = read_sized_word(11, REG(7) + 4, 4); - printf("Opcode at %08x: %04x, handler is at %08x // swap the top two values of the data stack (%08x <-> %08x), exchange second value with result (%08x <-> %08x)\n", REG(5), opcode, handler_offset, top, next, REG(4), next); - break; - } - - case 0x02f2: - printf("Opcode at %08x: %04x, handler is at %08x // decrement g4 (%08x -> %08x)\n", REG(5), opcode, handler_offset, REG(4), REG(4) - 1); - break; - - case 0x0334: - { - UINT32 address = REG(4); - UINT32 half0 = read_sized_word(11, address, 2); - if (address & 2) half0 <<= 16; - - address = REG(4) + 2; - UINT32 half1 = read_sized_word(11, address, 2); - if (!(address & 2)) half1 >>= 16; - - UINT32 value = half0 | half1; - - printf("Opcode at %08x: %04x, handler is at %08x // load result with 32-bit word at result address (g4 = [%08x] (%08x)\n", REG(5), opcode, handler_offset, REG(4), value); - break; - } - - case 0x0381: - printf("Opcode at %08x: %04x, handler is at %08x // word[g4 (%08x)] = pop_data(g7), result = pop_data(g7), g7 = %08x\n", REG(5), opcode, handler_offset, REG(4), REG(7)); - break; - - case 0x3d38: - printf("Opcode at %08x: %04x, handler is at %08x // call ffe8fe90\n", REG(5), opcode, handler_offset); - break; - } - } - else - { - printf("Opcode at %08x: %04x, handler is at %08x\n", REG(5), opcode, handler_offset); - } + disassemble_ss1_fcode(REG(5), opcode, handler_base, entry_point, REG(7)); + } + else if (PC == m_ss1_next_entry_point) + { + disassemble_ss1_fcode(m_ss1_next_pc, m_ss1_next_opcode, m_ss1_next_handler_base, m_ss1_next_entry_point, m_ss1_next_stack); + m_ss1_next_pc = ~0; + m_ss1_next_opcode = ~0; + m_ss1_next_handler_base = ~0; + m_ss1_next_entry_point = ~0; + m_ss1_next_stack = ~0; } #endif diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h index 1acc2263854..cca7a70eceb 100644 --- a/src/devices/cpu/sparc/sparc.h +++ b/src/devices/cpu/sparc/sparc.h @@ -11,36 +11,41 @@ #include "sparcdasm.h" -#define SPARCV8 (0) +#define SPARCV8 (0) +#define LOG_FCODES (0) -#define SPARC_NO_TRAP 256 -#define SPARC_RESET 0 -#define SPARC_INSTRUCTION_ACCESS_EXCEPTION 1 -#define SPARC_ILLEGAL_INSTRUCTION 2 -#define SPARC_PRIVILEGED_INSTRUCTION 3 -#define SPARC_FP_DISABLED 4 -#define SPARC_WINDOW_OVERFLOW 5 -#define SPARC_WINDOW_UNDERFLOW 6 -#define SPARC_MEM_ADDRESS_NOT_ALIGNED 7 -#define SPARC_FLOATING_POINT_EXCEPTION 8 -#define SPARC_DATA_ACCESS_EXCEPTION 9 -#define SPARC_TAG_OVERFLOW 10 -#define SPARC_INT1 17 -#define SPARC_INT2 18 -#define SPARC_INT3 19 -#define SPARC_INT4 20 -#define SPARC_INT5 21 -#define SPARC_INT6 22 -#define SPARC_INT7 23 -#define SPARC_INT8 24 -#define SPARC_INT9 25 -#define SPARC_INT10 26 -#define SPARC_INT11 27 -#define SPARC_INT12 28 -#define SPARC_INT13 29 -#define SPARC_INT14 30 -#define SPARC_INT15 31 -#define SPARC_TRAP_INSTRUCTION 128 +#if LOG_FCODES +#include +#endif + +#define SPARC_NO_TRAP 256 +#define SPARC_RESET 0 +#define SPARC_INSTRUCTION_ACCESS_EXCEPTION 1 +#define SPARC_ILLEGAL_INSTRUCTION 2 +#define SPARC_PRIVILEGED_INSTRUCTION 3 +#define SPARC_FP_DISABLED 4 +#define SPARC_WINDOW_OVERFLOW 5 +#define SPARC_WINDOW_UNDERFLOW 6 +#define SPARC_MEM_ADDRESS_NOT_ALIGNED 7 +#define SPARC_FLOATING_POINT_EXCEPTION 8 +#define SPARC_DATA_ACCESS_EXCEPTION 9 +#define SPARC_TAG_OVERFLOW 10 +#define SPARC_INT1 17 +#define SPARC_INT2 18 +#define SPARC_INT3 19 +#define SPARC_INT4 20 +#define SPARC_INT5 21 +#define SPARC_INT6 22 +#define SPARC_INT7 23 +#define SPARC_INT8 24 +#define SPARC_INT9 25 +#define SPARC_INT10 26 +#define SPARC_INT11 27 +#define SPARC_INT12 28 +#define SPARC_INT13 29 +#define SPARC_INT14 30 +#define SPARC_INT15 31 +#define SPARC_TRAP_INSTRUCTION 128 #define SPARC_FPU_SEQUENCE_ERROR // TODO: when there are more SPARC CPUs, move setter to a base class @@ -78,11 +83,6 @@ public: UINT8 get_asi() { return m_asi; } UINT32 pc() { return m_pc; } - void trap(UINT8 type, UINT8 tt_override = 0); - void set_mae() { m_mae = true; } - void hold_bus() { m_hold_bus = true; } - void release_bus() { m_hold_bus = false; } - template static void add_asi_desc(device_t &device, const T &desc) { return downcast(device).add_asi_desc(desc); } protected: @@ -130,6 +130,11 @@ protected: void reset_step(); void error_step(); +#if LOG_FCODES + void indent(); + void disassemble_ss1_fcode(UINT32 r5, UINT32 opcode, UINT32 handler_base, UINT32 entry_point, UINT32 stack); +#endif + // address spaces const address_space_config m_program_config; @@ -167,6 +172,7 @@ protected: bool m_pb_error; bool m_pb_block_ldst_byte; bool m_pb_block_ldst_word; + UINT16 m_irq_state; // trap and error registers bool m_trap; @@ -235,6 +241,15 @@ protected: // address spaces address_space *m_program; +#if LOG_FCODES + UINT32 m_ss1_next_pc; + UINT32 m_ss1_next_opcode; + UINT32 m_ss1_next_handler_base; + UINT32 m_ss1_next_entry_point; + UINT32 m_ss1_next_stack; + std::map m_ss1_fcode_table; +#endif + // processor configuration static const int NWINDOWS; }; @@ -242,10 +257,6 @@ protected: // device type definition extern const device_type MB86901; -/*************************************************************************** - REGISTER ENUMERATION -***************************************************************************/ - enum { SPARC_PC = 1, @@ -280,4 +291,24 @@ enum SPARC_R96, SPARC_R97, SPARC_R98, SPARC_R99, SPARC_R100, SPARC_R101, SPARC_R102, SPARC_R103, SPARC_R104, SPARC_R105, SPARC_R106, SPARC_R107, SPARC_R108, SPARC_R109, SPARC_R110, SPARC_R111 }; +enum +{ + SPARC_IRQ1, + SPARC_IRQ2, + SPARC_IRQ3, + SPARC_IRQ4, + SPARC_IRQ5, + SPARC_IRQ6, + SPARC_IRQ7, + SPARC_IRQ8, + SPARC_IRQ9, + SPARC_IRQ10, + SPARC_IRQ11, + SPARC_IRQ12, + SPARC_IRQ13, + SPARC_IRQ14, + SPARC_NMI, + SPARC_MAE +}; + #endif /* __SPARC_H__ */ diff --git a/src/devices/cpu/sparc/ss1fcode.ipp b/src/devices/cpu/sparc/ss1fcode.ipp new file mode 100644 index 00000000000..ebfd6abeb2c --- /dev/null +++ b/src/devices/cpu/sparc/ss1fcode.ipp @@ -0,0 +1,605 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +//================================================================ +// +// ss1fcode.ipp - Logging support for execution of the Forth VM +// used in the Sun SPARCstation 1. +// +//================================================================ + +void mb86901_device::indent() +{ + UINT32 program_depth = (0xffeff000 - (REG(6) - 4)) / 4; + for (int i = 0; i < program_depth; i++) + { + printf(" "); + } +} + +void mb86901_device::disassemble_ss1_fcode(UINT32 r5, UINT32 opcode, UINT32 handler_base, UINT32 entry_point, UINT32 stack) +{ + std::string opdesc = m_ss1_fcode_table[opcode & ~1]; + if (opdesc.length() == 0) + opdesc = "[unknown]"; + + if (entry_point == 0xffe87964) + { + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; call %08x\n", r5, opcode, entry_point, opdesc.c_str(), handler_base + 2); + indent(); printf(" // program stack now %08x (%d words deep)\n", REG(6) - 4, (0xffeff000 - (REG(6) - 4)) / 4); + } + else if (entry_point == 0xffe87974) + { + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push handler_base+2 (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), handler_base + 2); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + } + else if (entry_point == 0xffe8799c) + { + UINT32 address = handler_base + 2; + UINT32 half = read_sized_word(11, address, 2); + if (!(address & 2)) half >>= 16; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; add halfword at handler_base+2 (%04x) to VM base pointer (%08x) and push onto stack (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), half, REG(3), REG(3) + half); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + } + else if (entry_point == 0xffe879e4) + { + UINT32 address = handler_base + 2; + UINT32 half0 = read_sized_word(11, address, 2); + if (address & 2) half0 <<= 16; + + address = handler_base + 4; + UINT32 half1 = read_sized_word(11, address, 2); + if (!(address & 2)) half1 >>= 16; + + UINT32 value = half0 | half1; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push immediate word from handler table (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), value); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + } + else if (entry_point == 0xffe879c4) + { + UINT32 address = handler_base + 2; + UINT32 l0 = read_sized_word(11, address, 2); + if (!(address & 2)) l0 >>= 16; + + address = REG(3) + l0; + UINT32 handler_base_2 = read_sized_word(11, address, 2); + if (!(address & 2)) handler_base_2 >>= 16; + + address = REG(2) + (handler_base_2 << 2); + UINT32 l0_2 = read_sized_word(11, address, 2); + if (!(address & 2)) l0_2 >>= 16; + + UINT32 dest = REG(2) + (l0_2 << 2); + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; SPARC branch to %08x, calcs: g2(%08x) + halfword[g2(%04x) + (halfword[g3(%08x) + halfword[entry_point(%04x) + 2](%04x)](%04x) << 2)](%08x)\n", r5, opcode, entry_point, opdesc.c_str(), dest, REG(2), REG(2), REG(3), handler_base, l0, handler_base_2, l0_2); + indent(); printf(" // target func: %08x\n", l0_2 << 2); + switch (l0_2 << 2) + { + case 0x10: // call + indent(); printf(" // call %08x\n", (REG(2) + (handler_base_2 << 2)) + 2); + indent(); printf(" // program stack now %08x (%d words deep)\n", REG(6) - 4, (0xffeff000 - (REG(6) - 4)) / 4); + break; + default: + indent(); printf(" // unknown handler address: %08x\n", REG(2) + (l0_2 << 2)); + break; + } + } + else if (entry_point == 0xffe8c838) + { + UINT32 address = handler_base + 2; + UINT32 half0 = read_sized_word(11, address, 2); + if (address & 2) half0 <<= 16; + + address = handler_base + 4; + UINT32 half1 = read_sized_word(11, address, 2); + if (!(address & 2)) half1 >>= 16; + + UINT32 value = half0 | half1; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; add 32-bit word (%08x) from handler table to top of stack (%08x + %08x = %08x)\n", r5, opcode, entry_point, opdesc.c_str(), value, REG(4), value, REG(4) + value); + } + else + { + switch(opcode) + { + case 0x003f: + { + UINT32 address = r5 + 2; + UINT32 half0 = read_sized_word(11, address, 2); + if (address & 2) half0 <<= 16; + + address = r5 + 4; + UINT32 half1 = read_sized_word(11, address, 2); + if (!(address & 2)) half1 >>= 16; + + UINT32 value = half0 | half1; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push immediate word from instructions (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), value); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + } + + case 0x004b: + { + UINT32 address = r5 + 2; + UINT32 value = read_sized_word(11, address, 2); + if (!(address & 2)) value >>= 16; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push immediate halfword from instructions (%04x)\n", r5, opcode, entry_point, opdesc.c_str(), value); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + } + + case 0x0055: + { + UINT32 address = REG(4); + UINT32 new_opcode = read_sized_word(11, address, 2); + if (!(address & 2)) new_opcode >>= 16; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; pop stack top (%08x) as an opcode to execute\n", r5, opcode, entry_point, opdesc.c_str(), REG(4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (stack + 4)) / 4); + indent(); printf(" // inserted opcode:\n"); + + m_ss1_next_pc = REG(4); + m_ss1_next_opcode = new_opcode; + m_ss1_next_handler_base = REG(4); + + m_ss1_next_entry_point = read_sized_word(11, m_ss1_next_handler_base, 2); + if (!(m_ss1_next_handler_base & 2)) + { + m_ss1_next_entry_point >>= 16; + } + m_ss1_next_entry_point <<= 2; + m_ss1_next_entry_point += REG(2); + m_ss1_next_stack = stack + 4; + break; + } + + case 0x05f: + { + UINT32 address = r5 + 2; + UINT32 pc_offset = read_sized_word(11, address, 2); + if (!(address & 2)) pc_offset >>= 16; + + // advance program counter by amount specified as parameter + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; advance program counter by amount specified as parameter (%08x = %08x + %04x)\n", r5, opcode, entry_point, opdesc.c_str(), r5 + 2 + pc_offset, r5 + 2, pc_offset); + break; + } + + case 0x0066: + { + UINT32 address = r5 + 2; + UINT32 offset = read_sized_word(11, address, 2); + if (!(address & 2)) offset >>= 16; + + UINT32 target = r5 + 2 + offset; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; pop data stack top (%08x) and if zero, jump to %08x\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), target); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (stack + 4)) / 4); + break; + } + + case 0x007b: + { + UINT32 r4 = REG(4); + UINT32 value = read_sized_word(11, REG(6), 4); + UINT32 result = value + r4; + bool arithmetic_overflow = ((BIT31(value) && BIT31(r4) && !BIT31(result)) || (!BIT31(value) && !BIT31(r4) && BIT31(result))); + + UINT32 address = r5 + 2; + UINT32 offset = read_sized_word(11, address, 2); + if (!(address & 2)) offset >>= 16; + UINT32 target = r5 + 2 + offset; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; pop data stack top and add to program stack top (%08x = %08x + %08x)\n", r5, opcode, entry_point, opdesc.c_str(), result, value, r4); + indent(); printf(" // if no addition overflow, jump to %08x\n", target); + indent(); printf(" // if addition overflow, pop 3 words off program stack\n"); + if (arithmetic_overflow) + { + indent(); printf(" // program stack now %08x (%d words deep)\n", REG(6) + 12, (0xffeff000 - (REG(6) + 12)) / 4); + } + break; + } + + case 0x0099: + { + UINT32 handler_base_2 = REG(4); + + UINT32 address = stack; + UINT32 l0_2 = read_sized_word(11, address, 4); + + address = stack + 4; + UINT32 popped_g4 = read_sized_word(11, address, 4); + + address = r5 + 2; + UINT32 offset = read_sized_word(11, address, 2); + if (!(address & 2)) offset >>= 16; + + UINT32 target = r5 + 2 + offset; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; branch relative to %08x if data stack second (%08x) == data stack top (%08x), pop_data result (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), target, l0_2, handler_base_2, popped_g4); + if (handler_base_2 == l0_2) + { + indent(); printf(" // branch will be taken\n"); + } + else + { + indent(); printf(" // branch will not be taken\n"); + indent(); printf(" // push pc (%08x) onto program stack\n", r5 + 2); + indent(); printf(" // push previous data stack top + 0x80000000 (%08x) onto program stack\n", l0_2 + 0x80000000); + indent(); printf(" // push diff of (result - stack top) (%08x = %08x - %08x) onto program stack\n", handler_base_2, l0_2 + 0x80000000, handler_base_2 - (l0_2 + 0x80000000)); + indent(); printf(" // program stack now %08x (%d words deep)\n", REG(6) - 12, (0xffeff000 - (REG(6) - 12)) / 4); + } + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 8, (0xffefebe4 - (stack + 8)) / 4); + + break; + } + + case 0x00a4: + { + UINT32 word0 = read_sized_word(11, REG(6), 4); + UINT32 word1 = read_sized_word(11, REG(6) + 4, 4); + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push result (%08x) to data stack, add the top two values on the program stack, store in result (%08x = %08x + %08x)\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), word0 + word1, word0, word1); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + } + + case 0x0121: + { + UINT32 address = stack; + UINT32 word = read_sized_word(11, address, 4); + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; logical-AND result with data stack pop, store in result (%08x = %08x & %08x)\n", r5, opcode, entry_point, opdesc.c_str(), word & REG(4), word, REG(4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (stack + 4)) / 4); + break; + } + + case 0x0128: + { + UINT32 address = stack; + UINT32 word = read_sized_word(11, address, 4); + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; logical-OR result with data stack pop, store in result: %08x = %08x & %08x\n", r5, opcode, entry_point, opdesc.c_str(), word | REG(4), word, REG(4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (stack + 4)) / 4); + break; + } + + case 0x0136: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; invert result (%08x -> %08x)\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), REG(4) ^ 0xffffffff); + break; + + case 0x014f: + { + UINT32 address = stack; + UINT32 word = read_sized_word(11, address, 4); + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; add result to data stack pop, store in result: %08x = %08x + %08x\n", r5, opcode, entry_point, opdesc.c_str(), word + REG(4), word, REG(4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (stack + 4)) / 4); + break; + } + + case 0x0155: + { + UINT32 address = stack; + UINT32 word = read_sized_word(11, address, 4); + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; subtract result from data stack pop, store in result: %08x = %08x - %08x\n", r5, opcode, entry_point, opdesc.c_str(), word - REG(4), word, REG(4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (stack + 4)) / 4); + break; + } + + case 0x017f: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push result (%08x) onto data stack, set result to address of opcode dispatcher\n", r5, opcode, entry_point, opdesc.c_str(), REG(4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + + case 0x01a9: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push result (%08x) onto program stack, pop result from data stack (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), read_sized_word(11, stack, 4)); + indent(); printf(" // program stack now %08x (%d words deep)\n", REG(6) - 4, (0xffeff000 - (REG(6) - 4)) / 4); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (stack + 4)) / 4); + break; + + case 0x01b1: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push result (%08x) onto data stack, pop result from program stack (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), read_sized_word(11, REG(6), 4)); + indent(); printf(" // program stack now %08x (%d words deep)\n", REG(6) + 4, (0xffeff000 - (REG(6) + 4)) / 4); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + + case 0x01b9: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push result (%08x) onto data stack, assign program stack top to result (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), read_sized_word(11, REG(6), 4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + + case 0x01c0: + case 0x01c7: + { + UINT32 address = REG(6); + UINT32 half0 = read_sized_word(11, address, 2); + if (address & 2) half0 <<= 16; + + address = REG(6) + 2; + UINT32 half1 = read_sized_word(11, address, 2); + if (!(address & 2)) half1 >>= 16; + + UINT32 value = half0 | half1; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; return (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), value); + indent(); printf(" // program stack now %08x (%d words deep)\n", REG(6) + 4, (0xffeff000 - (REG(6) + 4)) / 4); + break; + } + + case 0x01cd: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; insert result (%08x) between data stack top (%08x) and next data stack entry\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), read_sized_word(11, stack, 4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + + case 0x01d5: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; throw away the word at the top of the data stack\n", r5, opcode, entry_point, opdesc.c_str()); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (stack + 4)) / 4); + break; + + case 0x01f4: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; if result (%08x) >= 0, set result to 0, otherwise -1 (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), (REG(4) >= 0) ? 0 : ~0); + break; + + case 0x0217: + { + UINT32 value = read_sized_word(11, stack, 4); + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; if pop_data (%08x) >= result (%08x), set result to 0, otherwise -1 (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), value, REG(4), (value >= REG(4)) ? 0 : ~0); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (stack + 4)) / 4); + break; + } + + case 0x022b: + { + UINT32 value = read_sized_word(11, stack, 4); + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; if pop_data (%08x) != result (%08x), set result to 0, otherwise -1 (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), value, REG(4), (value != REG(4)) ? 0 : ~0); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (stack + 4)) / 4); + break; + } + + case 0x0236: + { + UINT32 value = read_sized_word(11, stack, 4); + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; if pop_data (%08x) == result (%08x), set result to 0, otherwise -1 (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), value, REG(4), (value == REG(4)) ? 0 : ~0); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (stack + 4)) / 4); + break; + } + + case 0x026d: + { + UINT32 value = read_sized_word(11, stack, 4); + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; if pop_data (%08x) < result (%08x), set result to 0, otherwise -1 (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), value, REG(4), (value < REG(4)) ? 0 : ~0); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (stack + 4)) / 4); + break; + } + + case 0x0278: + { + UINT32 value = read_sized_word(11, stack, 4); + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; if pop_data (%08x) > result (%08x), set result to 0, otherwise -1 (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), value, REG(4), (value > REG(4)) ? 0 : ~0); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (stack + 4)) / 4); + break; + } + + case 0x0289: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push result (%08x) to data stack\n", r5, opcode, entry_point, opdesc.c_str(), REG(4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + + case 0x0283: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; pop result from data stack (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), read_sized_word(11, stack, 4)); + break; + + case 0x028f: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push result (%08x) onto data stack, assign previous top (%08x) to result\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), read_sized_word(11, stack, 4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + + case 0x0296: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; swap result (%08x) with top of data stack (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), read_sized_word(11, stack, 4)); + break; + + case 0x029d: + { + UINT32 top = read_sized_word(11, stack, 4); + UINT32 next = read_sized_word(11, stack + 4, 4); + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; swap the top two values of the data stack (%08x <-> %08x), exchange second value with result (%08x <-> %08x)\n", r5, opcode, entry_point, opdesc.c_str(), top, next, REG(4), next); + break; + } + + case 0x02af: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; pop_data to throw away data_top, then pop_data into result (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), read_sized_word(11, stack + 4, 4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 8, (0xffefebe4 - (stack + 8)) / 4); + break; + + case 0x02b6: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; duplicate top of data stack (%08x) and push the result (%08x) in between\n", r5, opcode, entry_point, opdesc.c_str(), read_sized_word(11, stack, 4), REG(4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 8, (0xffefebe4 - (REG(7) - 8)) / 4); + break; + + case 0x02e2: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; load result with value on data stack (%08x) indexed by result (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), read_sized_word(11, stack + (REG(4) << 2), 4), REG(4)); + break; + + case 0x02f2: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; decrement result (%08x = %08x - 1)\n", r5, opcode, entry_point, opdesc.c_str(), REG(4) - 1, REG(4)); + break; + + case 0x0306: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; shift result left by 1 bit (%08x = %08x << 1)\n", r5, opcode, entry_point, opdesc.c_str(), REG(4) << 1, REG(4)); + break; + + case 0x031e: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; store 0 at address contained by result (%08x), pop word from data stack into result (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), read_sized_word(11, stack, 4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 4, (0xffefebe4 - (REG(7) + 4)) / 4); + break; + + case 0x0334: + { + UINT32 address = REG(4); + UINT32 half0 = read_sized_word(11, address, 2); + if (address & 2) half0 <<= 16; + + address = REG(4) + 2; + UINT32 half1 = read_sized_word(11, address, 2); + if (!(address & 2)) half1 >>= 16; + + UINT32 value = half0 | half1; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; load result with word (%08x) at result address (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), value, REG(4)); + break; + } + + case 0x0349: + { + UINT32 address = REG(4); + UINT32 value = read_sized_word(11, address, 2); + if (!(address & 2)) value >>= 16; + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; load result with unsigned halfword (%04x) at result address (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), value, REG(4)); + break; + } + + case 0x0353: + { + UINT32 address = REG(4); + UINT32 value = read_sized_word(11, address, 1); + value >>= (3 - (address & 3)) * 8; + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; load result with unsigned byte (%02x) at result address (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), value, REG(4)); + break; + } + + case 0x0381: + case 0x0382: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; pop_data (%08x) into address contained by result (%08x), pop_data (%08x) into result\n", r5, opcode, entry_point, opdesc.c_str(), read_sized_word(11, stack, 4), REG(4), read_sized_word(11, stack + 4, 4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 8, (0xffefebe4 - (stack + 8)) / 4); + break; + + case 0x045a: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; pop word from data stack and add it to result << 2, (%08x = %08x + (%08x << 2))\n", r5, opcode, entry_point, opdesc.c_str(), (REG(4) << 2) + read_sized_word(11, stack, 4), read_sized_word(11, stack, 4), REG(4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + + case 0x0462: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; pop word from data stack and add it to result << 1, (%08x = %08x + (%08x << 1))\n", r5, opcode, entry_point, opdesc.c_str(), (REG(4) << 1) + read_sized_word(11, stack, 4), read_sized_word(11, stack, 4), REG(4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + + case 0x046a: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; increment result (%08x = %08x + 1\n", r5, opcode, entry_point, opdesc.c_str(), REG(4) + 1, REG(4)); + break; + + case 0x047e: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; add 2 to result (%08x = %08x + 2\n", r5, opcode, entry_point, opdesc.c_str(), REG(4) + 2, REG(4)); + break; + + case 0x04ff: + { + UINT32 address = r5 + 2; + UINT32 next_op = read_sized_word(11, address, 2); + if (!(address & 2)) next_op >>= 16; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push_data result (%08x), load result with entry_point for next opcode (%08x = %08x + %08x, op %04x)\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), REG(2) + (next_op << 2), REG(2), next_op << 2, next_op); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + } + + case 0x050a: + { + UINT32 byte_addr = read_sized_word(11, REG(6), 4); + UINT32 address_shift = (3 - (byte_addr & 3)) * 8; + UINT8 value = read_sized_word(11, byte_addr, 1) >> address_shift; + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push result (%08x) onto data stack\n", r5, opcode, entry_point, opdesc.c_str(), REG(4)); + indent(); printf(" // load result with byte pointed to by top of program stack (%02x)\n", value); + indent(); printf(" // push address of next byte (%08x) onto data stack\n", byte_addr + 1); + indent(); printf(" // add (result + 3) to program_top and clear the low bit (now %08x)\n", (byte_addr + value + 3) & ~1); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 8, (0xffefebe4 - (stack - 8)) / 4); + break; + } + + case 0x05ca: + { + // + UINT32 address = REG(4); + UINT32 g2_offset = read_sized_word(11, address, 2); + if (!(address & 2)) g2_offset >>= 16; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; add halfword at address in result (%08x) to forth table base pointer (%08x) and store in result (%08x = %08x + %08x)\n", r5, opcode, entry_point, opdesc.c_str(), address, REG(2), REG(2) + g2_offset, REG(2), g2_offset); + break; + } + + case 0x05e6: + { + UINT32 address = REG(4); + UINT32 next_op = read_sized_word(11, address, 2); + if (!(address & 2)) next_op >>= 16; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; load result with entry_point for opcode (%08x = %08x + %08x, op %04x) pointed to by result (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), REG(2) + (next_op << 2), REG(2), next_op << 2, next_op, REG(4)); + break; + } + + case 0x05ee: + case 0x05ef: + { + UINT32 stack_top = read_sized_word(11, stack, 4); + UINT32 new_opcode = (stack_top - REG(2)) >> 2; + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; pop word (%08x) from the data stack, turn it into a 16-bit opcode (%04x)\n", r5, opcode, entry_point, opdesc.c_str(), stack_top, new_opcode); + indent(); printf(" // store the opcode at the address contained in the result (%08x)\n", REG(4)); + indent(); printf(" // pop word from the data stack into to the result (%08x)\n", read_sized_word(11, stack + 4, 4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 8, (0xffefebe4 - (stack + 8)) / 4); + break; + } + + case 0x05fe: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push result (%08x) onto data stack, load base pointer of Fcode table (%08x) into result\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), REG(2)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + + case 0x0613: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; if result (%08x) is equal to g2 (%08x), push result to data stack and load with 0, else push nothing and load with ~0\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), REG(2)); + if (REG(4) == REG(2)) + { + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + } + break; + + case 0x0668: + { + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; some complex junk I don't understand, the amount of asm in this function is a PITA.\n", r5, opcode, entry_point, opdesc.c_str()); + indent(); printf(" // basically it involves a bunch of comparisons between whatever's on the top of the stack, the\n"); + indent(); printf(" // current result, and some other weird junk like 0x20000000\n"); + indent(); printf(" // like seriously, this function is a couple hundred lines of asm long\n"); + break; + } + + case 0x3d38: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; call ffe8fe90\n", r5, opcode, entry_point, opdesc.c_str()); + indent(); printf(" // program stack now %08x (%d words deep)\n", REG(6) - 4, (0xffeff000 - (REG(6) - 4)) / 4); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + + case 0x3fd2: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; pop address from data stack (%08x), pop data from data stack (%08x)\n", r5, opcode, entry_point, opdesc.c_str(), read_sized_word(11, stack, 4), read_sized_word(11, stack + 4, 4)); + indent(); printf(" // address at ASI specified by result (%d), then pop word from data stack (%08x) into result\n", REG(4), read_sized_word(11, stack + 8, 4)); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack + 12, (0xffefebe4 - (stack + 12)) / 4); + break; + + case 0x4181: + { + UINT32 address = handler_base + 2; + UINT32 g3_offset = read_sized_word(11, address, 2); + if (!(address & 2)) g3_offset >>= 16; + + address = REG(3) + g3_offset; + UINT32 new_result = read_sized_word(11, address, 2); + if (!(address & 2)) new_result >>= 16; + + indent(); printf("Opcode at %08x: %04x, entry is at %08x // %s ; push result (%08x) to data stack, load halfword (%04x) from handler table\n", r5, opcode, entry_point, opdesc.c_str(), REG(4), g3_offset); + indent(); printf(" // use g3 (%08x) plus first halfword as the address (%08x) from which to load a halfword (%04x) into result\n", REG(3), address, new_result); + indent(); printf(" // data stack now %08x (%d words deep)\n", stack - 4, (0xffefebe4 - (stack - 4)) / 4); + break; + } + + default: + indent(); printf("Opcode at %08x: %04x, entry is at %08x // unknown\n", r5, opcode, entry_point); + break; + } + } +}