Merge pull request #1041 from MooglyGuy/master

Fix some SPARC issues, attn: RB
This commit is contained in:
R. Belmont 2016-07-04 20:42:51 -04:00 committed by GitHub
commit b1a90fda41
3 changed files with 891 additions and 314 deletions

View File

@ -26,6 +26,14 @@ const device_type MB86901 = &device_creator<mb86901_device>;
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

View File

@ -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 <map>
#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<typename T> static void add_asi_desc(device_t &device, const T &desc) { return downcast<mb86901_device &>(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<UINT16, std::string> 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__ */

View File

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