void dsp16_device::execute_run() { // HACK TO MAKE CPU DO NOTHING. // REMOVE IF DEVELOPING CPU CORE. m_icount = 0; return; do { // debugging m_ppc = m_pc; // copy PC to previous PC debugger_instruction_hook(this, m_pc); // instruction fetch & execute UINT8 cycles; UINT8 pcAdvance; const UINT16 op = opcode_read(); execute_one(op, cycles, pcAdvance); // step m_pc += pcAdvance; m_icount -= cycles; // The 16 bit PI "shadow" register gets set to PC on each instruction except // when an interrupt service routine is active (TODO: Interrupt check) (page 2-4) m_pi = m_pc; } while (m_icount > 0); }
void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance) { cycles = 1; pcAdvance = 0; const UINT8 opcode = (op >> 11) & 0x1f; switch(opcode) { // Format 1: Multiply/ALU Read/Write Group case 0x06: { // F1, Y : (page 3-38) const UINT8 Y = (op & 0x000f); const UINT8 S = (op & 0x0200) >> 9; const UINT8 D = (op & 0x0400) >> 10; const UINT8 F1 = (op & 0x01e0) >> 5; executeF1Field(F1, D, S); executeYFieldPost(Y); cycles = 1; pcAdvance = 1; break; } case 0x04: case 0x1c: { // F1 Y=a0[1] | F1 Y=a1[1] //const UINT8 Y = (op & 0x000f); //const UINT8 S = (op & 0x0200) >> 9; //const UINT8 D = (op & 0x0400) >> 10; //const UINT8 F1 = (op & 0x01e0) >> 5; break; } case 0x16: { // F1, x = Y //const UINT8 Y = (op & 0x000f); //const UINT8 S = (op & 0x0200) >> 9; //const UINT8 D = (op & 0x0400) >> 10; //const UINT8 F1 = (op & 0x01e0) >> 5; break; } case 0x17: { // F1, y[l] = Y : (page 3-44) const UINT8 Y = (op & 0x000f); const UINT8 X = (op & 0x0010) >> 4; const UINT8 S = (op & 0x0200) >> 9; const UINT8 D = (op & 0x0400) >> 10; const UINT8 F1 = (op & 0x01e0) >> 5; executeF1Field(F1, D, S); UINT16* sourceReg = (UINT16*)registerFromYFieldUpper(Y); UINT16 sourceValue = data_read(*sourceReg); switch (X) { case 0x00: writeRegister(addressYL(), sourceValue); break; case 0x01: writeRegister(&m_y, sourceValue); break; default: break; } executeYFieldPost(Y); cycles = 1; pcAdvance = 1; break; } case 0x1f: { // F1, y = Y, x = *pt++[i] //const UINT8 Y = (op & 0x000f); //const UINT8 X = (op & 0x0010) >> 4; //const UINT8 S = (op & 0x0200) >> 9; //const UINT8 D = (op & 0x0400) >> 10; //const UINT8 F1 = (op & 0x01e0) >> 5; break; } case 0x19: case 0x1b: { // F1, y = a0|1, x = *pt++[i] //const UINT8 Y = (op & 0x000f); //const UINT8 X = (op & 0x0010) >> 4; //const UINT8 S = (op & 0x0200) >> 9; //const UINT8 D = (op & 0x0400) >> 10; //const UINT8 F1 = (op & 0x01e0) >> 5; break; } case 0x14: { // F1, Y = y[1] : (page 3-53) const UINT8 Y = (op & 0x000f); const UINT8 X = (op & 0x0010) >> 4; const UINT8 S = (op & 0x0200) >> 9; const UINT8 D = (op & 0x0400) >> 10; const UINT8 F1 = (op & 0x01e0) >> 5; executeF1Field(F1, D, S); UINT16* destinationReg = (UINT16*)registerFromYFieldUpper(Y); UINT16 yRegValue = 0x0000; switch (X) { case 0x00: yRegValue = (m_y & 0x0000ffff); break; case 0x01: yRegValue = (m_y & 0xffff0000) >> 16; break; default: break; } data_write(*destinationReg, yRegValue); executeYFieldPost(Y); cycles = 2; pcAdvance = 1; break; } // Format 1a: Multiply/ALU Read/Write Group (TODO: Figure out major typo in docs on p3-51) case 0x07: { // F1, At[1] = Y : (page 3-50) const UINT8 Y = (op & 0x000f); const UINT8 S = (op & 0x0200) >> 9; const UINT8 aT = (op & 0x0400) >> 10; const UINT8 F1 = (op & 0x01e0) >> 5; executeF1Field(F1, !aT, S); UINT64* destinationReg = NULL; switch(aT) { case 0: destinationReg = &m_a1; break; case 1: destinationReg = &m_a0; break; default: break; } UINT16 sourceAddress = *((UINT16*)registerFromYFieldUpper(Y)); INT64 sourceValueSigned = (INT16)data_read(sourceAddress); *destinationReg = sourceValueSigned & U64(0xffffffffff); executeYFieldPost(Y); cycles = 1; pcAdvance = 1; break; } // Format 2: Multiply/ALU Read/Write Group case 0x15: { // F1, Z : y[1] //const UINT8 Z = (op & 0x000f); //const UINT8 X = (op & 0x0010) >> 4; //const UINT8 S = (op & 0x0200) >> 9; //const UINT8 D = (op & 0x0400) >> 10; //const UINT8 F1 = (op & 0x01e0) >> 5; break; } case 0x1d: { // F1, Z : y, x=*pt++[i] //const UINT8 Z = (op & 0x000f); //const UINT8 X = (op & 0x0010) >> 4; //const UINT8 S = (op & 0x0200) >> 9; //const UINT8 D = (op & 0x0400) >> 10; //const UINT8 F1 = (op & 0x01e0) >> 5; break; } // Format 2a: Multiply/ALU Read/Write Group case 0x05: { // F1, Z : aT[1] //const UINT8 Z = (op & 0x000f); //const UINT8 X = (op & 0x0010) >> 4; //const UINT8 S = (op & 0x0200) >> 9; //const UINT8 aT = (op & 0x0400) >> 10; //const UINT8 F1 = (op & 0x01e0) >> 5; break; } // Format 3: Special Functions case 0x12: case 0x13: { // if|ifc CON F2 //const UINT8 CON = (op & 0x001f); //const UINT8 S = (op & 0x0200) >> 9; //const UINT8 D = (op & 0x0400) >> 10; //const UINT8 F2 = (op & 0x01e0) >> 5; break; } // Format 4: Branch Direct Group case 0x00: case 0x01: { // goto JA : (page 3-20) const UINT16 JA = (op & 0x0fff) | (m_pc & 0xf000); m_pc = JA; cycles = 2; pcAdvance = 0; break; } case 0x10: case 0x11: { // call JA : (page 3-23) const UINT16 JA = (op & 0x0fff) | (m_pc & 0xf000); m_pr = m_pc + 1; m_pc = JA; cycles = 2; pcAdvance = 0; break; } // Format 5: Branch Indirect Group case 0x18: { // goto B //const UINT8 B = (op & 0x0700) >> 8; break; } // Format 6: Contitional Branch Qualifier/Software Interrupt (icall) case 0x1a: { // if CON [goto/call/return] //const UINT8 CON = (op & 0x001f); break; } // Format 7: Data Move Group case 0x09: case 0x0b: { // R = aS //const UINT8 R = (op & 0x03f0) >> 4; //const UINT8 S = (op & 0x1000) >> 12; break; } case 0x08: { // aT = R //const UINT8 R = (op & 0x03f0) >> 4; //const UINT8 aT = (op & 0x0400) >> 10; break; } case 0x0f: { // R = Y //const UINT8 Y = (op & 0x000f); //const UINT8 R = (op & 0x03f0) >> 4; break; } case 0x0c: { // Y = R : (page 3-33) const UINT8 Y = (op & 0x000f); const UINT8 R = (op & 0x03f0) >> 4; UINT16* destinationReg = (UINT16*)registerFromYFieldUpper(Y); UINT16* sourceReg = (UINT16*)registerFromRTable(R); data_write(*destinationReg, *sourceReg); executeYFieldPost(Y); cycles = 2; pcAdvance = 1; break; } case 0x0d: { // Z : R //const UINT8 Z = (op & 0x000f); //const UINT8 R = (op & 0x03f0) >> 4; break; } // Format 8: Data Move (immediate operand - 2 words) case 0x0a: { // R = N : (page 3-28) const UINT8 R = (op & 0x03f0) >> 4; const UINT16 iVal = opcode_read(1); void* reg = registerFromRTable(R); writeRegister(reg, iVal); cycles = 2; pcAdvance = 2; break; } // Format 9: Short Immediate Group case 0x02: case 0x03: { // R = M : (page 3-27) const INT8 M = (op & 0x00ff); const UINT8 R = (op & 0x0e00) >> 9; void* reg = registerFromRImmediateField(R); writeRegister(reg, (INT16)M); // Sign extend 8 bit int cycles = 1; pcAdvance = 1; break; } // Format 10: do - redo case 0x0e: { // do|redo K : (pages 3-25 & 3-26) const UINT8 K = (op & 0x007f); const UINT8 NI = (op & 0x0780) >> 7; if (NI != 0) { // Do m_cacheStart = m_pc + 1; m_cacheEnd = m_pc + NI + 1; m_cacheIterations = K-1; // -1 because we check the counter below cycles = 1; pcAdvance = 1; } else { // Redo m_cacheIterations = K-1; // -1 because we check the counter below m_cacheRedoNextPC = m_pc + 1; m_pc = m_cacheStart; pcAdvance = 0; cycles = 2; pcAdvance = 1; } break; } // RESERVED case 0x1e: { break; } // UNKNOWN default: { break; } } // Handle end-of-cache conditions for do|redos if (m_cacheIterations == 0 && m_cacheRedoNextPC != CACHE_INVALID) { // You've reached the end of a cache loop after a redo opcode. m_pc = m_cacheRedoNextPC; m_cacheRedoNextPC = CACHE_INVALID; pcAdvance = 0; } if (m_cacheIterations > 0 && (m_pc+pcAdvance == m_cacheEnd)) { // A regular iteration on a cached loop. m_cacheIterations--; m_pc = m_cacheStart; pcAdvance = 0; } }