diff options
Diffstat (limited to 'src/devices/cpu/patinhofeio/patinho_feio.cpp')
| -rw-r--r-- | src/devices/cpu/patinhofeio/patinho_feio.cpp | 935 |
1 files changed, 467 insertions, 468 deletions
diff --git a/src/devices/cpu/patinhofeio/patinho_feio.cpp b/src/devices/cpu/patinhofeio/patinho_feio.cpp index 9377ad259f8..78fc92a8270 100644 --- a/src/devices/cpu/patinhofeio/patinho_feio.cpp +++ b/src/devices/cpu/patinhofeio/patinho_feio.cpp @@ -28,14 +28,14 @@ #define INCREMENT_PC_4K (PC = (PC+1) & ADDRESS_MASK_4K) unsigned int patinho_feio_cpu_device::compute_effective_address(unsigned int addr){ - unsigned int retval = addr; - if (m_indirect_addressing){ - retval = READ_WORD_PATINHO(addr); - if (retval & 0x1000) - return compute_effective_address(retval & 0xFFF); - } - - return retval; + unsigned int retval = addr; + if (m_indirect_addressing){ + retval = READ_WORD_PATINHO(addr); + if (retval & 0x1000) + return compute_effective_address(retval & 0xFFF); + } + + return retval; } const device_type PATINHO_FEIO = &device_creator<patinho_feio_cpu_device>; @@ -43,494 +43,493 @@ const device_type PATINHO_FEIO = &device_creator<patinho_feio_cpu_device>; //Internal 4kbytes of RAM static ADDRESS_MAP_START(prog_8bit, AS_PROGRAM, 8, patinho_feio_cpu_device) - AM_RANGE(0x0000, 0x0fff) AM_RAM AM_SHARE("internalram") + AM_RANGE(0x0000, 0x0fff) AM_RAM AM_SHARE("internalram") ADDRESS_MAP_END patinho_feio_cpu_device::patinho_feio_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : cpu_device(mconfig, PATINHO_FEIO, "PATINHO FEIO", tag, owner, clock, "patinho_feio_cpu", __FILE__), - m_program_config("program", ENDIANNESS_LITTLE, 8, 12, 0, ADDRESS_MAP_NAME(prog_8bit)), - m_icount(0), - m_rc_read_cb(*this) + : cpu_device(mconfig, PATINHO_FEIO, "PATINHO FEIO", tag, owner, clock, "patinho_feio_cpu", __FILE__), + m_program_config("program", ENDIANNESS_LITTLE, 8, 12, 0, ADDRESS_MAP_NAME(prog_8bit)), + m_icount(0), + m_rc_read_cb(*this) { } UINT16 patinho_feio_cpu_device::read_panel_keys_register(){ - if (!m_rc_read_cb.isnull()) - m_rc = m_rc_read_cb(0); - else - m_rc = 0; + if (!m_rc_read_cb.isnull()) + m_rc = m_rc_read_cb(0); + else + m_rc = 0; - return m_rc; + return m_rc; } void patinho_feio_cpu_device::device_start() { - m_program = &space(AS_PROGRAM); - - save_item(NAME(m_pc)); - save_item(NAME(m_acc)); - save_item(NAME(m_rc)); - save_item(NAME(m_idx)); - save_item(NAME(m_flags)); - - // Register state for debugger - state_add( PATINHO_FEIO_CI, "CI", m_pc ).mask(0xFFF); - state_add( PATINHO_FEIO_RC, "RC", m_rc ).mask(0xFFF); - state_add( PATINHO_FEIO_ACC, "ACC", m_acc ).mask(0xFF); - state_add( PATINHO_FEIO_IDX, "IDX", m_idx ).mask(0xFF); - state_add(STATE_GENPC, "GENPC", m_pc).formatstr("0%06O").noshow(); - state_add(STATE_GENFLAGS, "GENFLAGS", m_flags).noshow().formatstr("%8s"); - - if (m_rc_read_cb.isnull()){ - fatalerror("Panel keys register not found!"); - } else { - m_rc_read_cb.resolve(); - } - - m_icountptr = &m_icount; + m_program = &space(AS_PROGRAM); + + save_item(NAME(m_pc)); + save_item(NAME(m_acc)); + save_item(NAME(m_rc)); + save_item(NAME(m_idx)); + save_item(NAME(m_flags)); + + // Register state for debugger + state_add( PATINHO_FEIO_CI, "CI", m_pc ).mask(0xFFF); + state_add( PATINHO_FEIO_RC, "RC", m_rc ).mask(0xFFF); + state_add( PATINHO_FEIO_ACC, "ACC", m_acc ).mask(0xFF); + state_add( PATINHO_FEIO_IDX, "IDX", m_idx ).mask(0xFF); + state_add(STATE_GENPC, "GENPC", m_pc).formatstr("0%06O").noshow(); + state_add(STATE_GENFLAGS, "GENFLAGS", m_flags).noshow().formatstr("%8s"); + + if (m_rc_read_cb.isnull()){ + fatalerror("Panel keys register not found!"); + } else { + m_rc_read_cb.resolve(); + } + + m_icountptr = &m_icount; } void patinho_feio_cpu_device::device_reset() { - m_pc = 0x006; - m_acc = 0; - m_rc = 0; - m_idx = READ_INDEX_REG(); - m_flags = 0; - m_run = true; - m_scheduled_IND_bit_reset = false; - m_indirect_addressing = false; + m_pc = 0x006; + m_acc = 0; + m_rc = 0; + m_idx = READ_INDEX_REG(); + m_flags = 0; + m_run = true; + m_scheduled_IND_bit_reset = false; + m_indirect_addressing = false; } /* execute instructions on this CPU until icount expires */ void patinho_feio_cpu_device::execute_run() { - do - { - if ((! m_run)){ - m_icount = 0; /* if processor is stopped, just burn cycles */ - } else { - m_idx = READ_INDEX_REG(); - read_panel_keys_register(); - - execute_instruction(); - m_icount --; - } - } - while (m_icount > 0); + do + { + if ((! m_run)){ + m_icount = 0; /* if processor is stopped, just burn cycles */ + } else { + m_idx = READ_INDEX_REG(); + read_panel_keys_register(); + + execute_instruction(); + m_icount --; + } + } + while (m_icount > 0); } /* execute one instruction */ void patinho_feio_cpu_device::execute_instruction() { - debugger_instruction_hook(this, PC); - offs_t addr; - bool skip; - unsigned int tmp; - unsigned char value, channel, function; - unsigned char opcode = READ_BYTE_PATINHO(PC); - INCREMENT_PC_4K; - - if (m_scheduled_IND_bit_reset) - m_indirect_addressing = false; - - if (m_indirect_addressing) - m_scheduled_IND_bit_reset = true; - - switch (opcode){ - case 0xD2: - //XOR: Computes the bitwise XOR of an immediate into the accumulator - ACC ^= READ_BYTE_PATINHO(PC); - INCREMENT_PC_4K; - //TODO: update T and V flags - return; - case 0xD4: - //NAND: Computes the bitwise XOR of an immediate into the accumulator - ACC = ~(ACC & READ_BYTE_PATINHO(PC)); - INCREMENT_PC_4K; - //TODO: update T and V flags - return; - case 0xD8: - //SOMI="Soma Imediato": - // Add an immediate into the accumulator - ACC += READ_BYTE_PATINHO(PC); - INCREMENT_PC_4K; - //TODO: update T and V flags - return; - case 0xDA: - //CARI="Carrega Imediato": - // Load an immediate into the accumulator - ACC = READ_BYTE_PATINHO(PC); - INCREMENT_PC_4K; - return; - case 0x80: - //LIMPO: - // Clear accumulator and flags - ACC = 0; - FLAGS = 0; - return; - case 0x81: - //UM="One": - // Load 1 into accumulator - // and clear the flags - ACC = 1; - FLAGS = 0; - return; - case 0x82: - //CMP1: - // Compute One's complement of the accumulator - // and clear the flags - ACC = ~ACC; - FLAGS = 0; - return; - case 0x83: - //CMP2: - // Compute Two's complement of the accumulator - // and updates flags according to the result of the operation - ACC = ~ACC + 1; - FLAGS = 0; //TODO: fix-me (I'm not sure yet how to compute the flags here) - return; - case 0x84: - //LIM="Limpa": - // Clear flags - FLAGS = 0; - return; - case 0x85: - //INC: - // Increment accumulator - ACC++; - FLAGS = 0; //TODO: fix-me (I'm not sure yet how to compute the flags here) - return; - case 0x86: - //UNEG="Um Negativo": - // Load -1 into accumulator and clear flags - ACC = -1; - FLAGS = 0; - return; - case 0x87: - //LIMP1: - // Clear accumulator, reset T and set V - ACC = 0; - FLAGS = V; - return; - case 0x88: - //PNL 0: - ACC = (RC & 0xFF); - FLAGS = 0; - return; - case 0x89: - //PNL 1: - ACC = (RC & 0xFF) + 1; - //TODO: FLAGS = ?; - return; - case 0x8A: - //PNL 2: - ACC = (RC & 0xFF) - ACC - 1; - //TODO: FLAGS = ?; - return; - case 0x8B: - //PNL 3: - ACC = (RC & 0xFF) - ACC; - //TODO: FLAGS = ?; - return; - case 0x8C: - //PNL 4: - ACC = (RC & 0xFF) + ACC; - //TODO: FLAGS = ?; - return; - case 0x8D: - //PNL 5: - ACC = (RC & 0xFF) + ACC + 1; - //TODO: FLAGS = ?; - return; - case 0x8E: - //PNL 6: - ACC = (RC & 0xFF) - 1; - //TODO: FLAGS = ?; - return; - case 0x8F: - //PNL 7: - ACC = (RC & 0xFF); - FLAGS = V; - return; - case 0x9A: - //INIB="Inibe" - // disables interrupts - m_interrupts_enabled = false; - return; - case 0x9B: - //PERM="Permite" - // enables interrupts - m_interrupts_enabled = true; - return; - case 0x9C: - //ESP="Espera": - // Holds execution and waits for an interrupt to occur. - m_run = false; - m_wait_for_interrupt = true; - return; - case 0x9D: - //PARE="Pare": - // Holds execution. This can only be recovered by - // manually triggering execution again by - // pressing the "Partida" (start) button in the panel - m_run = false; - m_wait_for_interrupt = false; - return; - case 0x9E: - //TRI="Troca com Indexador": - // Exchange the value of the accumulator with the index register - value = ACC; - ACC = READ_INDEX_REG(); - WRITE_INDEX_REG(value); - return; - case 0x9F: - //IND="Enderecamento indireto": - // Sets memory addressing for the next instruction to be indirect. - m_indirect_addressing = true; - m_scheduled_IND_bit_reset = false; //the next instruction execution will schedule it. - return; - case 0xD1: - //Bit-Shift/Bit-Rotate instructions - value = READ_BYTE_PATINHO(PC); - INCREMENT_PC_4K; - for (int i=0; i<4; i++){ - if (value & (1<<i)){ - /* The number of shifts or rotations is determined by the - ammount of 1 bits in the lower 4 bits of 'value' */ - switch(value & 0xF0) - { - case 0x00: - //DD="Deslocamento para a Direita" - // Shift right - FLAGS &= ~V; - if (ACC & 1) - FLAGS |= V; - - ACC >>= 1; - break; - case 0x20: - //GD="Giro para a Direita" - // Rotate right - FLAGS &= ~V; - if (ACC & 1) - FLAGS |= V; - - ACC = ((ACC & 1) << 7) | (ACC >> 1); - break; - case 0x10: //DDV="Deslocamento para a Direita com Vai-um" - // Shift right with Carry - case 0x30: //GDV="Giro para a Direita com Vai-um" - // Rotate right with Carry - - //both instructions are equivalent - if (FLAGS & V) - tmp = 0x100 | ACC; - else - tmp = ACC; - - FLAGS &= ~V; - if (ACC & 1) - FLAGS |= V; - - ACC = tmp >> 1; - break; - case 0x40: //DE="Deslocamento para a Esquerda" - // Shift left - FLAGS &= ~V; - if (ACC & (1<<7)) - FLAGS |= V; - - ACC <<= 1; - break; - case 0x60: //GE="Giro para a Esquerda" - // Rotate left - FLAGS &= ~V; - if (ACC & (1<<7)) - FLAGS |= V; - - ACC = (ACC << 1) | ((ACC >> 7) & 1); - break; - case 0x50: //DEV="Deslocamento para a Esquerda com Vai-um" - // Shift left with Carry - case 0x70: //GEV="Giro para a Esquerda com Vai-um" - // Rotate left with Carry - - //both instructions are equivalent - if (FLAGS & V) - tmp = (ACC << 1) | 1; - else - tmp = (ACC << 1); - - FLAGS &= ~V; - if (tmp & (1<<8)) - FLAGS |= V; - - ACC = tmp & 0xFF; - break; - case 0x80: //DDS="Deslocamento para a Direita com duplicacao de Sinal" - // Rotate right with signal duplication - FLAGS &= ~V; - if (ACC & 1) - FLAGS |= V; - - ACC = (ACC & (1 << 7)) | ACC >> 1; - break; - default: - printf("Illegal instruction: %02X %02X\n", opcode, value); - return; - } - } - } - return; - } - - switch (opcode & 0xF0){ - case 0x00: - //PLA = "Pula": Jump to address - addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); - INCREMENT_PC_4K; - PC = addr; - return; - case 0x10: - //PLAX = "Pula indexado": Jump to indexed address - tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); - INCREMENT_PC_4K; - m_idx = READ_INDEX_REG(); - PC = compute_effective_address(m_idx + tmp); - return; - case 0x20: - //ARM = "Armazena": Store the value of the accumulator into a given memory position - addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); - INCREMENT_PC_4K; - WRITE_BYTE_PATINHO(addr, ACC); - return; - case 0x30: - //ARMX = "Armazena indexado": Store the value of the accumulator into a given indexed memory position - tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); - INCREMENT_PC_4K; - m_idx = READ_INDEX_REG(); - addr = compute_effective_address(m_idx + tmp); - WRITE_BYTE_PATINHO(addr, ACC); - return; - case 0x40: - //CAR = "Carrega": Load a value from a given memory position into the accumulator - addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); - INCREMENT_PC_4K; - ACC = READ_BYTE_PATINHO(addr); - return; - case 0x50: - //CARX = "Carga indexada": Load a value from a given indexed memory position into the accumulator - tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); - INCREMENT_PC_4K; - m_idx = READ_INDEX_REG(); - addr = compute_effective_address(m_idx + tmp); - ACC = READ_BYTE_PATINHO(addr); - return; - case 0x60: - //SOM = "Soma": Add a value from a given memory position into the accumulator - addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); - INCREMENT_PC_4K; - ACC += READ_BYTE_PATINHO(addr); - //TODO: update V and T flags - return; - case 0x70: - //SOMX = "Soma indexada": Add a value from a given indexed memory position into the accumulator - tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); - INCREMENT_PC_4K; - m_idx = READ_INDEX_REG(); - addr = compute_effective_address(m_idx + tmp); - ACC += READ_BYTE_PATINHO(addr); - //TODO: update V and T flags - return; - case 0xA0: - //PLAN = "Pula se ACC negativo": Jump to a given address if ACC is negative - addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); - INCREMENT_PC_4K; - if ((signed char) ACC < 0) - PC = addr; - return; - case 0xB0: - //PLAZ = "Pula se ACC for zero": Jump to a given address if ACC is zero - addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); - INCREMENT_PC_4K; - if (ACC == 0) - PC = addr; - return; - case 0xC0: - //Executes I/O functions - //TODO: Implement-me! - value = READ_BYTE_PATINHO(PC); - INCREMENT_PC_4K; - channel = opcode & 0x0F; - function = value & 0x0F; - switch(value & 0xF0){ - case 0x10: - printf("Unimplemented FNC /%X%X instruction\n", channel, function); - break; - case 0x20: - //SAL="Salta" - // Skips a couple bytes if a condition is met - skip = false; - switch(function) - { - case 1: - if (m_peripherals[channel].io_status == DEVICE_READY) - skip = true; - break; - case 2: - if (m_peripherals[channel].device_is_ok) - skip = true; - break; - case 4: - if (m_peripherals[channel].IRQ_request == true) - skip = true; - break; - } - - if (skip){ - INCREMENT_PC_4K; - INCREMENT_PC_4K; - } - break; - case 0x40: - printf("Unimplemented ENTR /%X0 instruction\n", channel); - break; - case 0x80: - printf("Unimplemented SAI /%X0 instruction (ACC = 0x%02X '%c')\n", channel, ACC, ACC); - break; - } - return; - case 0xE0: - //SUS = "Subtrai um ou Salta": Subtract one from the data in the given address - // or, if the data is zero, then simply skip a couple bytes. - addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); - INCREMENT_PC_4K; - value = READ_BYTE_PATINHO(addr); - if (value > 0){ - WRITE_BYTE_PATINHO(addr, value-1); - } else { - INCREMENT_PC_4K; - INCREMENT_PC_4K; - } - return; - case 0xF0: - //PUG = "Pula e guarda": Jump and store. - // It stores the return address to addr and addr+1 - // And then jumps to addr+2 - addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); - INCREMENT_PC_4K; - WRITE_BYTE_PATINHO(addr, (PC >> 8) & 0x0F); - WRITE_BYTE_PATINHO(addr+1, PC & 0xFF); - PC = addr+2; - return; - } - printf("unimplemented opcode: 0x%02X\n", opcode); + debugger_instruction_hook(this, PC); + offs_t addr; + bool skip; + unsigned int tmp; + unsigned char value, channel, function; + unsigned char opcode = READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + + if (m_scheduled_IND_bit_reset) + m_indirect_addressing = false; + + if (m_indirect_addressing) + m_scheduled_IND_bit_reset = true; + + switch (opcode){ + case 0xD2: + //XOR: Computes the bitwise XOR of an immediate into the accumulator + ACC ^= READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + //TODO: update T and V flags + return; + case 0xD4: + //NAND: Computes the bitwise XOR of an immediate into the accumulator + ACC = ~(ACC & READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + //TODO: update T and V flags + return; + case 0xD8: + //SOMI="Soma Imediato": + // Add an immediate into the accumulator + ACC += READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + //TODO: update T and V flags + return; + case 0xDA: + //CARI="Carrega Imediato": + // Load an immediate into the accumulator + ACC = READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + return; + case 0x80: + //LIMPO: + // Clear accumulator and flags + ACC = 0; + FLAGS = 0; + return; + case 0x81: + //UM="One": + // Load 1 into accumulator + // and clear the flags + ACC = 1; + FLAGS = 0; + return; + case 0x82: + //CMP1: + // Compute One's complement of the accumulator + // and clear the flags + ACC = ~ACC; + FLAGS = 0; + return; + case 0x83: + //CMP2: + // Compute Two's complement of the accumulator + // and updates flags according to the result of the operation + ACC = ~ACC + 1; + FLAGS = 0; //TODO: fix-me (I'm not sure yet how to compute the flags here) + return; + case 0x84: + //LIM="Limpa": + // Clear flags + FLAGS = 0; + return; + case 0x85: + //INC: + // Increment accumulator + ACC++; + FLAGS = 0; //TODO: fix-me (I'm not sure yet how to compute the flags here) + return; + case 0x86: + //UNEG="Um Negativo": + // Load -1 into accumulator and clear flags + ACC = -1; + FLAGS = 0; + return; + case 0x87: + //LIMP1: + // Clear accumulator, reset T and set V + ACC = 0; + FLAGS = V; + return; + case 0x88: + //PNL 0: + ACC = (RC & 0xFF); + FLAGS = 0; + return; + case 0x89: + //PNL 1: + ACC = (RC & 0xFF) + 1; + //TODO: FLAGS = ?; + return; + case 0x8A: + //PNL 2: + ACC = (RC & 0xFF) - ACC - 1; + //TODO: FLAGS = ?; + return; + case 0x8B: + //PNL 3: + ACC = (RC & 0xFF) - ACC; + //TODO: FLAGS = ?; + return; + case 0x8C: + //PNL 4: + ACC = (RC & 0xFF) + ACC; + //TODO: FLAGS = ?; + return; + case 0x8D: + //PNL 5: + ACC = (RC & 0xFF) + ACC + 1; + //TODO: FLAGS = ?; + return; + case 0x8E: + //PNL 6: + ACC = (RC & 0xFF) - 1; + //TODO: FLAGS = ?; + return; + case 0x8F: + //PNL 7: + ACC = (RC & 0xFF); + FLAGS = V; + return; + case 0x9A: + //INIB="Inibe" + // disables interrupts + m_interrupts_enabled = false; + return; + case 0x9B: + //PERM="Permite" + // enables interrupts + m_interrupts_enabled = true; + return; + case 0x9C: + //ESP="Espera": + // Holds execution and waits for an interrupt to occur. + m_run = false; + m_wait_for_interrupt = true; + return; + case 0x9D: + //PARE="Pare": + // Holds execution. This can only be recovered by + // manually triggering execution again by + // pressing the "Partida" (start) button in the panel + m_run = false; + m_wait_for_interrupt = false; + return; + case 0x9E: + //TRI="Troca com Indexador": + // Exchange the value of the accumulator with the index register + value = ACC; + ACC = READ_INDEX_REG(); + WRITE_INDEX_REG(value); + return; + case 0x9F: + //IND="Enderecamento indireto": + // Sets memory addressing for the next instruction to be indirect. + m_indirect_addressing = true; + m_scheduled_IND_bit_reset = false; //the next instruction execution will schedule it. + return; + case 0xD1: + //Bit-Shift/Bit-Rotate instructions + value = READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + for (int i=0; i<4; i++){ + if (value & (1<<i)){ + /* The number of shifts or rotations is determined by the + ammount of 1 bits in the lower 4 bits of 'value' */ + switch(value & 0xF0) + { + case 0x00: + //DD="Deslocamento para a Direita" + // Shift right + FLAGS &= ~V; + if (ACC & 1) + FLAGS |= V; + + ACC >>= 1; + break; + case 0x20: + //GD="Giro para a Direita" + // Rotate right + FLAGS &= ~V; + if (ACC & 1) + FLAGS |= V; + + ACC = ((ACC & 1) << 7) | (ACC >> 1); + break; + case 0x10: //DDV="Deslocamento para a Direita com Vai-um" + // Shift right with Carry + case 0x30: //GDV="Giro para a Direita com Vai-um" + // Rotate right with Carry + + //both instructions are equivalent + if (FLAGS & V) + tmp = 0x100 | ACC; + else + tmp = ACC; + + FLAGS &= ~V; + if (ACC & 1) + FLAGS |= V; + + ACC = tmp >> 1; + break; + case 0x40: //DE="Deslocamento para a Esquerda" + // Shift left + FLAGS &= ~V; + if (ACC & (1<<7)) + FLAGS |= V; + + ACC <<= 1; + break; + case 0x60: //GE="Giro para a Esquerda" + // Rotate left + FLAGS &= ~V; + if (ACC & (1<<7)) + FLAGS |= V; + + ACC = (ACC << 1) | ((ACC >> 7) & 1); + break; + case 0x50: //DEV="Deslocamento para a Esquerda com Vai-um" + // Shift left with Carry + case 0x70: //GEV="Giro para a Esquerda com Vai-um" + // Rotate left with Carry + + //both instructions are equivalent + if (FLAGS & V) + tmp = (ACC << 1) | 1; + else + tmp = (ACC << 1); + + FLAGS &= ~V; + if (tmp & (1<<8)) + FLAGS |= V; + + ACC = tmp & 0xFF; + break; + case 0x80: //DDS="Deslocamento para a Direita com duplicacao de Sinal" + // Rotate right with signal duplication + FLAGS &= ~V; + if (ACC & 1) + FLAGS |= V; + + ACC = (ACC & (1 << 7)) | ACC >> 1; + break; + default: + printf("Illegal instruction: %02X %02X\n", opcode, value); + return; + } + } + } + return; + } + + switch (opcode & 0xF0){ + case 0x00: + //PLA = "Pula": Jump to address + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + PC = addr; + return; + case 0x10: + //PLAX = "Pula indexado": Jump to indexed address + tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + m_idx = READ_INDEX_REG(); + PC = compute_effective_address(m_idx + tmp); + return; + case 0x20: + //ARM = "Armazena": Store the value of the accumulator into a given memory position + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + WRITE_BYTE_PATINHO(addr, ACC); + return; + case 0x30: + //ARMX = "Armazena indexado": Store the value of the accumulator into a given indexed memory position + tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + m_idx = READ_INDEX_REG(); + addr = compute_effective_address(m_idx + tmp); + WRITE_BYTE_PATINHO(addr, ACC); + return; + case 0x40: + //CAR = "Carrega": Load a value from a given memory position into the accumulator + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + ACC = READ_BYTE_PATINHO(addr); + return; + case 0x50: + //CARX = "Carga indexada": Load a value from a given indexed memory position into the accumulator + tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + m_idx = READ_INDEX_REG(); + addr = compute_effective_address(m_idx + tmp); + ACC = READ_BYTE_PATINHO(addr); + return; + case 0x60: + //SOM = "Soma": Add a value from a given memory position into the accumulator + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + ACC += READ_BYTE_PATINHO(addr); + //TODO: update V and T flags + return; + case 0x70: + //SOMX = "Soma indexada": Add a value from a given indexed memory position into the accumulator + tmp = (opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + m_idx = READ_INDEX_REG(); + addr = compute_effective_address(m_idx + tmp); + ACC += READ_BYTE_PATINHO(addr); + //TODO: update V and T flags + return; + case 0xA0: + //PLAN = "Pula se ACC negativo": Jump to a given address if ACC is negative + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + if ((signed char) ACC < 0) + PC = addr; + return; + case 0xB0: + //PLAZ = "Pula se ACC for zero": Jump to a given address if ACC is zero + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + if (ACC == 0) + PC = addr; + return; + case 0xC0: + //Executes I/O functions + //TODO: Implement-me! + value = READ_BYTE_PATINHO(PC); + INCREMENT_PC_4K; + channel = opcode & 0x0F; + function = value & 0x0F; + switch(value & 0xF0){ + case 0x10: + printf("Unimplemented FNC /%X%X instruction\n", channel, function); + break; + case 0x20: + //SAL="Salta" + // Skips a couple bytes if a condition is met + skip = false; + switch(function) + { + case 1: + if (m_peripherals[channel].io_status == DEVICE_READY) + skip = true; + break; + case 2: + if (m_peripherals[channel].device_is_ok) + skip = true; + break; + case 4: + if (m_peripherals[channel].IRQ_request == true) + skip = true; + break; + } + + if (skip){ + INCREMENT_PC_4K; + INCREMENT_PC_4K; + } + break; + case 0x40: + printf("Unimplemented ENTR /%X0 instruction\n", channel); + break; + case 0x80: + printf("Unimplemented SAI /%X0 instruction (ACC = 0x%02X '%c')\n", channel, ACC, ACC); + break; + } + return; + case 0xE0: + //SUS = "Subtrai um ou Salta": Subtract one from the data in the given address + // or, if the data is zero, then simply skip a couple bytes. + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + value = READ_BYTE_PATINHO(addr); + if (value > 0){ + WRITE_BYTE_PATINHO(addr, value-1); + } else { + INCREMENT_PC_4K; + INCREMENT_PC_4K; + } + return; + case 0xF0: + //PUG = "Pula e guarda": Jump and store. + // It stores the return address to addr and addr+1 + // And then jumps to addr+2 + addr = compute_effective_address((opcode & 0x0F) << 8 | READ_BYTE_PATINHO(PC)); + INCREMENT_PC_4K; + WRITE_BYTE_PATINHO(addr, (PC >> 8) & 0x0F); + WRITE_BYTE_PATINHO(addr+1, PC & 0xFF); + PC = addr+2; + return; + } + printf("unimplemented opcode: 0x%02X\n", opcode); } offs_t patinho_feio_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) { - extern CPU_DISASSEMBLE( patinho_feio ); - return CPU_DISASSEMBLE_NAME(patinho_feio)(this, buffer, pc, oprom, opram, options); + extern CPU_DISASSEMBLE( patinho_feio ); + return CPU_DISASSEMBLE_NAME(patinho_feio)(this, buffer, pc, oprom, opram, options); } - |
