summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/patinhofeio/patinho_feio.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/patinhofeio/patinho_feio.cpp')
-rw-r--r--src/devices/cpu/patinhofeio/patinho_feio.cpp935
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);
}
-