Execution begins from 0. On hitting "DONE", execution stops. Each execution fully resets the DSP state. The output sample is written to 3FE (left) and 3FF (right). ------------------------------------------------------------------------------- OP & 0x8000 == 0x0000: // ALU instructions 15 14 13 12 11 10 9 8 7 4 3 0 |...|OpCount|UseMult2|MuxA |MuxB|Oper|Shift| Load `OpCount` operand words. If an input is referenced, it is read from the operands. Refer to the order in dsp_operands.txt for the read order. switch(MuxA) { case 0: SrcA = ACC; case 1: SrcA = ALU1 << 16; case 2: SrcA = ALU2 << 16; case 3: if UseMult2: SrcA = MULT1*MULT2*2 else: SrcA = MULT1*(ACC >> 16)*2 // ADDCY and SUBCY override the value of SrcA here if Oper==3or5: SrcA = Carry ? (MULT1 << 16) : 0 } switch(MuxB) { case 0: SrcB = ACC; case 1: SrcB = ALU1 << 16; case 2: SrcB = ALU2 << 16; case 3: if UseMult2: SrcB = MULT1*MULT2*2 else: SrcB = MULT1*(ACC >> 16)*2 // ADDCY and SUBCY probably would override this too, but they do not use SrcB. } Overflow = 0 Carry = 0 switch(Oper) { case 0x0: // LDA ACC = SrcA; case 0x1: // NEGB ACC = -SrcB; Overflow = [calc] Carry = [calc] case 0x2: // ADD ACC = SrcA+SrcB; Overflow = [calc] Carry = [calc] case 0x3: // ADDCY ACC = SrcA+(OldCarry ? 1 << 16 : 0); Overflow = [calc] Carry = [calc] case 0x4: // SUB ACC = SrcA-SrcB; Overflow = [calc] Carry = [calc] case 0x5: // SUBCY ACC = SrcA-(OldCarry ? 1 << 16 : 0); Overflow = [calc] Carry = [calc] case 0x6: // INC ACC = SrcA+(1 << 12); Overflow = [calc] Carry = [calc] case 0x7: // DEC ACC = SrcA-(1 << 12); Overflow = [calc] Carry = [calc] case 0x8: // LDA (for unsigned shift) ACC = SrcA; case 0x9: // NOT ACC = ~SrcA; case 0xA: // AND ACC = SrcA & SrcB; case 0xB: // NAND ACC = ~(SrcA & SrcB); case 0xC: // OR ACC = SrcA | SrcB; case 0xD: // NOR ACC = ~(SrcA | SrcB); case 0xE: // XOR ACC = SrcA ^ SrcB; case 0xF: // XNOR ACC = ~(SrcA ^ SrcB); } Zero = ACC & (0xFFFF << 16) Neg = ACC & (1 << 31) Exact = (ACC & 0xF000) ? 0 : 1 switch(Shift) { // If Oper & 8, shifts are unsigned, otherwise signed case 0x0: NOP case 0x1: ACC <<= 1; case 0x2: ACC <<= 2; case 0x3: ACC <<= 3; case 0x4: ACC <<= 4; case 0x5: ACC <<= 5; case 0x6: ACC <<= 8; case 0x7: if Over: ACC = Neg ? ((1 << 31) - 1) : -1; case 0x8: Carry = (ACC < 0) ACC[b31~b16] ROL 1 (bottom 4 bits left alone) case 0x9: ACC >>= 16; case 0xA: ACC >>= 8; case 0xB: ACC >>= 5; case 0xC: ACC >>= 4; case 0xD: ACC >>= 3; case 0xE: ACC >>= 2; case 0xF: ACC >>= 1; } if(WritebackEA) IMEM[WritebackEA] = ACC >> 16; ------------------------------------------------------------------------------- OP & 0xFC00 == 0x8000: switch (OP >> 7) & 0x7: 0x00: NOP 0x01: PC = ACC >> 16 0x02: REGBASE = OP & 0x3F 0x03: REGMAP = OP & 7 0x04: PC = ReturnPC 0x05: OP_MASK = OP & 0x1F 0x06: NOP 0x07: DONE ------------------------------------------------------------------------------- OP & 0xFC00 == 0x8400: PC = OP & 0x3FF ------------------------------------------------------------------------------- OP & 0xFC00 == 0x8800: ReturnPC = PC PC = OP & 0x3FF ------------------------------------------------------------------------------- OP & 0xFC00 == 0x8C00: PC = OP & 0x3FF ------------------------------------------------------------------------------- OP & 0xF800 == 0x9000: EA = REGADDR[OP & 0xF] if OP & 0x10: EA = IMEM[EA] IMEM[EA] = ReadOp() ------------------------------------------------------------------------------- OP & 0xF800 == 0x9800: EA = OP & 0x3FF if OP & 0x400: EA = IMEM[EA] IMEM[EA] = ReadOp() ------------------------------------------------------------------------------- OP & 0xF000 >= 0xA000: 15 14 10 9 0 |...|Condition|Addr| if ConditionCheck: PC = Addr switch(Condition) { case 0x08: FALSE case 0x09: Over case 0x0A: Neg case 0x0B: Neg && Over case 0x0C: FALSE case 0x0D: Zero case 0x0E: Carry case 0x0F: Carry && Zero case 0x10: FALSE case 0x11: !Over case 0x12: !Neg case 0x13: !Neg && !Over case 0x14: FALSE case 0x15: !Zero case 0x16: !Carry case 0x17: !Carry && !Zero // Odd versions of the below are just invert of even versions case 0x18: Neg != Over case 0x19: Neg == Over case 0x1A: (Neg != Over) || Zero case 0x1B: (Neg == Over) && Zero case 0x1C: Carry && !Zero case 0x1D: !Carry || Zero case 0x1E: Exact case 0x1F: !Exact } =============================================================================== Public domain 3DO chip documentation, by trap15 Last update 2020-05-09T20:10+09 Knowledge derived from FreeDO source. FreeDO Project authors: Alexander Troosh Maxim Grishin Allen Wright John Sammons Felix Lazarev