trunk/src/emu/cpu/8x300/8x300dasm.c
| r0 | r26679 | |
| 1 | /* |
| 2 | * 8x300dasm.c |
| 3 | * Implementation of the Scientific Micro Systems SMS300 / Signetics 8X300 Microcontroller |
| 4 | * |
| 5 | * Created on: 18/12/2013 |
| 6 | */ |
| 7 | |
| 8 | #include "emu.h" |
| 9 | #include "8x300.h" |
| 10 | |
| 11 | #define SRC ((opcode & 0x1f00) >> 8) |
| 12 | #define DST (opcode & 0x001f) |
| 13 | #define ROTLEN ((opcode & 0x00e0) >> 5) |
| 14 | #define IMM8 (opcode & 0x00ff) |
| 15 | #define IMM5 (opcode & 0x001f) |
| 16 | |
| 17 | static const char *reg_names[32] = |
| 18 | { |
| 19 | "AUX", "R1", "R2", "R3", "R4", "R5", "R6", "IVL", "OVF", "R11", |
| 20 | "Unused12", "Unused13", "Unused14", "Unused15", "Unused16", "IVR", |
| 21 | "LIV0", "LIV1", "LIV2", "LIV3", "LIV4", "LIV5", "LIV6", "LIV7", |
| 22 | "RIV0", "RIV1", "RIV2", "RIV3", "RIV4", "RIV5", "RIV6", "RIV7" |
| 23 | }; |
| 24 | |
| 25 | // determines if right rotate or I/O field length is to be used |
| 26 | INLINE bool is_rot(UINT16 opcode) |
| 27 | { |
| 28 | if((opcode & 0x1000) || (opcode & 0x0010)) |
| 29 | return false; |
| 30 | else |
| 31 | return true; |
| 32 | } |
| 33 | |
| 34 | INLINE bool is_src_rot(UINT16 opcode) |
| 35 | { |
| 36 | if((opcode & 0x1000)) |
| 37 | return false; |
| 38 | else |
| 39 | return true; |
| 40 | } |
| 41 | |
| 42 | CPU_DISASSEMBLE( n8x300 ) |
| 43 | { |
| 44 | char tmp[16]; |
| 45 | unsigned startpc = pc; |
| 46 | UINT16 opcode = (oprom[pc - startpc] << 8) | oprom[pc+1 - startpc]; |
| 47 | UINT8 inst = opcode >> 13; |
| 48 | pc+=2; |
| 49 | |
| 50 | // determine instruction |
| 51 | switch (inst) |
| 52 | { |
| 53 | case 0x00: |
| 54 | sprintf(buffer,"MOVE "); |
| 55 | strcat(buffer,reg_names[SRC]); |
| 56 | if(is_rot(opcode)) |
| 57 | sprintf(tmp,"(%i),",ROTLEN); |
| 58 | else |
| 59 | sprintf(tmp,",%i,",ROTLEN); |
| 60 | strcat(buffer,tmp); |
| 61 | strcat(buffer,reg_names[DST]); |
| 62 | break; |
| 63 | case 0x01: |
| 64 | sprintf(buffer,"ADD "); |
| 65 | strcat(buffer,reg_names[SRC]); |
| 66 | if(is_rot(opcode)) |
| 67 | sprintf(tmp,"(%i),",ROTLEN); |
| 68 | else |
| 69 | sprintf(tmp,",%i,",ROTLEN); |
| 70 | strcat(buffer,tmp); |
| 71 | strcat(buffer,reg_names[DST]); |
| 72 | break; |
| 73 | case 0x02: |
| 74 | sprintf(buffer,"AND "); |
| 75 | strcat(buffer,reg_names[SRC]); |
| 76 | if(is_rot(opcode)) |
| 77 | sprintf(tmp,"(%i),",ROTLEN); |
| 78 | else |
| 79 | sprintf(tmp,",%i,",ROTLEN); |
| 80 | strcat(buffer,tmp); |
| 81 | strcat(buffer,reg_names[DST]); |
| 82 | break; |
| 83 | case 0x03: |
| 84 | sprintf(buffer,"XOR "); |
| 85 | strcat(buffer,reg_names[SRC]); |
| 86 | if(is_rot(opcode)) |
| 87 | sprintf(tmp,"(%i),",ROTLEN); |
| 88 | else |
| 89 | sprintf(tmp,",%i,",ROTLEN); |
| 90 | strcat(buffer,tmp); |
| 91 | strcat(buffer,reg_names[DST]); |
| 92 | break; |
| 93 | case 0x04: |
| 94 | sprintf(buffer,"XEC "); |
| 95 | strcat(buffer,reg_names[SRC]); |
| 96 | if(is_src_rot(opcode)) |
| 97 | { |
| 98 | sprintf(tmp,",%02XH",IMM8); |
| 99 | strcat(buffer,tmp); |
| 100 | } |
| 101 | else |
| 102 | { |
| 103 | sprintf(tmp,",%i",ROTLEN); |
| 104 | strcat(buffer,tmp); |
| 105 | sprintf(tmp,",%02XH",IMM5); |
| 106 | strcat(buffer,tmp); |
| 107 | } |
| 108 | break; |
| 109 | case 0x05: |
| 110 | sprintf(buffer,"NZT "); |
| 111 | strcat(buffer,reg_names[SRC]); |
| 112 | if(is_src_rot(opcode)) |
| 113 | { |
| 114 | sprintf(tmp,",%02XH",IMM8); |
| 115 | strcat(buffer,tmp); |
| 116 | } |
| 117 | else |
| 118 | { |
| 119 | sprintf(tmp,",%i",ROTLEN); |
| 120 | strcat(buffer,tmp); |
| 121 | sprintf(tmp,",%02XH",IMM5); |
| 122 | strcat(buffer,tmp); |
| 123 | } |
| 124 | break; |
| 125 | case 0x06: |
| 126 | sprintf(buffer,"XMIT "); |
| 127 | if(is_src_rot(opcode)) |
| 128 | { |
| 129 | sprintf(tmp,"%02XH,",IMM8); |
| 130 | strcat(buffer,tmp); |
| 131 | strcat(buffer,reg_names[SRC]); |
| 132 | } |
| 133 | else |
| 134 | { |
| 135 | sprintf(tmp,"%02XH,",IMM5); |
| 136 | strcat(buffer,tmp); |
| 137 | strcat(buffer,reg_names[SRC]); |
| 138 | sprintf(tmp,",%i",ROTLEN); |
| 139 | strcat(buffer,tmp); |
| 140 | } |
| 141 | break; |
| 142 | case 0x07: |
| 143 | sprintf(buffer,"JMP %04XH",opcode & 0x1fff); |
| 144 | break; |
| 145 | } |
| 146 | |
| 147 | |
| 148 | return (pc - startpc); |
| 149 | } |
trunk/src/emu/cpu/8x300/8x300.h
| r0 | r26679 | |
| 1 | /* |
| 2 | * 8x300.h |
| 3 | * |
| 4 | * Implementation of the Scientific Micro Systems SMS300 / Signetics 8X300 Microcontroller |
| 5 | * Created on: 18/12/2013 |
| 6 | */ |
| 7 | |
| 8 | #ifndef _8X300_H_ |
| 9 | #define _8X300_H_ |
| 10 | |
| 11 | // Register enumeration |
| 12 | enum |
| 13 | { |
| 14 | _8X300_PC = 1, |
| 15 | _8X300_AR, |
| 16 | _8X300_IR, |
| 17 | _8X300_AUX, |
| 18 | _8X300_R1, |
| 19 | _8X300_R2, |
| 20 | _8X300_R3, |
| 21 | _8X300_R4, |
| 22 | _8X300_R5, |
| 23 | _8X300_R6, |
| 24 | _8X300_IVL, |
| 25 | _8X300_OVF, |
| 26 | _8X300_R11, |
| 27 | _8X300_UNUSED12, |
| 28 | _8X300_UNUSED13, |
| 29 | _8X300_UNUSED14, |
| 30 | _8X300_UNUSED15, |
| 31 | _8X300_UNUSED16, |
| 32 | _8X300_IVR, |
| 33 | _8X300_LIV, |
| 34 | _8X300_RIV, |
| 35 | _8X300_GENPC |
| 36 | }; |
| 37 | |
| 38 | class n8x300_cpu_device : public cpu_device |
| 39 | { |
| 40 | public: |
| 41 | // construction/destruction |
| 42 | n8x300_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 43 | |
| 44 | protected: |
| 45 | // device-level overrides |
| 46 | virtual void device_start(); |
| 47 | virtual void device_reset(); |
| 48 | |
| 49 | // device_execute_interface overrides |
| 50 | virtual UINT32 execute_min_cycles() const { return 1; } |
| 51 | virtual UINT32 execute_max_cycles() const { return 1; } |
| 52 | virtual UINT32 execute_input_lines() const { return 0; } |
| 53 | virtual void execute_run(); |
| 54 | |
| 55 | // device_memory_interface overrides |
| 56 | virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const |
| 57 | { |
| 58 | switch (spacenum) |
| 59 | { |
| 60 | case AS_PROGRAM: return &m_program_config; |
| 61 | case AS_IO: return &m_io_config; |
| 62 | default: return NULL; |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | // device_state_interface overrides |
| 67 | void state_string_export(const device_state_entry &entry, astring &string); |
| 68 | |
| 69 | // device_disasm_interface overrides |
| 70 | virtual UINT32 disasm_min_opcode_bytes() const { return 2; } |
| 71 | virtual UINT32 disasm_max_opcode_bytes() const { return 2; } |
| 72 | virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); |
| 73 | |
| 74 | address_space_config m_program_config; |
| 75 | address_space_config m_io_config; |
| 76 | |
| 77 | int m_icount; |
| 78 | |
| 79 | address_space *m_program; |
| 80 | direct_read_data *m_direct; |
| 81 | address_space *m_io; |
| 82 | |
| 83 | UINT16 m_PC; // Program Counter |
| 84 | UINT16 m_AR; // Address Register |
| 85 | UINT16 m_IR; // Instruction Register |
| 86 | UINT8 m_AUX; // Auxiliary Register (second operand for AND, ADD, XOR) |
| 87 | UINT8 m_R1; |
| 88 | UINT8 m_R2; |
| 89 | UINT8 m_R3; |
| 90 | UINT8 m_R4; |
| 91 | UINT8 m_R5; |
| 92 | UINT8 m_R6; |
| 93 | UINT8 m_R11; |
| 94 | UINT8 m_IVL; // Interface vector (I/O) left bank (write-only) |
| 95 | UINT8 m_IVR; // Interface vector (I/O) right bank (write-only) |
| 96 | UINT8 m_OVF; // Overflow register (read-only) |
| 97 | UINT16 m_genPC; |
| 98 | |
| 99 | UINT8 m_left_IV; // IV bank contents, these are latched when IVL or IVR are set |
| 100 | UINT8 m_right_IV; |
| 101 | |
| 102 | private: |
| 103 | inline bool is_rot(UINT16 opcode) |
| 104 | { |
| 105 | if((opcode & 0x1000) || (opcode & 0x0010)) |
| 106 | return false; |
| 107 | else |
| 108 | return true; |
| 109 | } |
| 110 | inline bool is_src_reg(UINT16 opcode) |
| 111 | { |
| 112 | if((opcode & 0x1000)) |
| 113 | return false; |
| 114 | else |
| 115 | return true; |
| 116 | } |
| 117 | inline bool is_dst_reg(UINT16 opcode) |
| 118 | { |
| 119 | if((opcode & 0x0010)) |
| 120 | return false; |
| 121 | else |
| 122 | return true; |
| 123 | } |
| 124 | inline UINT8 rotate(UINT8 s, UINT8 n) // right rotate |
| 125 | { |
| 126 | return ((s & ((UINT8)0xff << n)) >> n) | ((s & ((UINT8)0xff >> (8-n))) << (8-n)); |
| 127 | } |
| 128 | void set_reg(UINT8 reg,UINT8 val); |
| 129 | UINT8 get_reg(UINT8 reg); |
| 130 | }; |
| 131 | |
| 132 | extern const device_type N8X300; |
| 133 | |
| 134 | #endif /* 8X300_H_ */ |
trunk/src/emu/cpu/8x300/8x300.c
| r0 | r26679 | |
| 1 | /* |
| 2 | * 8x300.c |
| 3 | * |
| 4 | * Implementation of the Scientific Micro Systems SMS300 / Signetics 8X300 CPU |
| 5 | * Created on: 18/12/2013 |
| 6 | * |
| 7 | * Written by Barry Rodewald |
| 8 | */ |
| 9 | |
| 10 | #include "debugger.h" |
| 11 | #include "8x300.h" |
| 12 | |
| 13 | #define FETCHOP(a) (m_direct->read_decrypted_word(a)) |
| 14 | #define CYCLES(x) do { m_icount -= (x); } while (0) |
| 15 | #define READPORT(a) (m_io->read_byte(a)) |
| 16 | #define WRITEPORT(a,v) (m_io->write_byte((a), (v))) |
| 17 | |
| 18 | #define SRC ((opcode & 0x1f00) >> 8) |
| 19 | #define DST (opcode & 0x001f) |
| 20 | #define ROTLEN ((opcode & 0x00e0) >> 5) |
| 21 | #define IMM8 (opcode & 0x00ff) |
| 22 | #define IMM5 (opcode & 0x001f) |
| 23 | #define ADDR (opcode & 0x1fff) |
| 24 | #define OP ((opcode & 0xe000) >> 13) |
| 25 | #define SRC_IS_RIGHT_BANK (opcode & 0x0800) |
| 26 | #define DST_IS_RIGHT_BANK (opcode & 0x0008) |
| 27 | #define SRC_LSB ((opcode & 0x0700) >> 8) |
| 28 | #define DST_LSB (opcode & 0x0007) |
| 29 | #define SET_PC(x) do { m_PC = (x); m_AR = m_PC; m_genPC = m_PC << 1; } while (0) |
| 30 | // for XEC intruction, which sets the AR, but not PC, so that after the instruction at the relative address is done, execution |
| 31 | // returns back to next instruction after XEC, unless a JMP or successful NZT is there. |
| 32 | #define SET_AR(x) do { m_AR = (x); m_genPC = m_AR << 1; m_PC--;} while (0) |
| 33 | #define SRC_LATCH do { if(SRC_IS_RIGHT_BANK) m_right_IV = READPORT(m_IVR+0x100); else m_left_IV = READPORT(m_IVL); } while (0) |
| 34 | #define DST_LATCH do { if(DST_IS_RIGHT_BANK) m_right_IV = READPORT(m_IVR+0x100); else m_left_IV = READPORT(m_IVL); } while (0) |
| 35 | #define SET_OVF do { if(result & 0xff00) m_OVF = 1; else m_OVF = 0; } while (0) |
| 36 | |
| 37 | const device_type N8X300 = &device_creator<n8x300_cpu_device>; |
| 38 | |
| 39 | |
| 40 | n8x300_cpu_device::n8x300_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 41 | : cpu_device(mconfig, N8X300, "Signetics 8X300", tag, owner, clock, "8x300", __FILE__) |
| 42 | , m_program_config("program", ENDIANNESS_BIG, 16, 14, 0) |
| 43 | , m_io_config("io", ENDIANNESS_BIG, 8, 9, 0) |
| 44 | { |
| 45 | } |
| 46 | |
| 47 | void n8x300_cpu_device::set_reg(UINT8 reg, UINT8 val) |
| 48 | { |
| 49 | switch(reg) |
| 50 | { |
| 51 | case 0x00: m_AUX = val; break; |
| 52 | case 0x01: m_R1 = val; break; |
| 53 | case 0x02: m_R2 = val; break; |
| 54 | case 0x03: m_R3 = val; break; |
| 55 | case 0x04: m_R4 = val; break; |
| 56 | case 0x05: m_R5 = val; break; |
| 57 | case 0x06: m_R6 = val; break; |
| 58 | case 0x07: m_IVL = val; break; |
| 59 | // OVF is read-only |
| 60 | case 0x09: m_R11 = val; break; |
| 61 | case 0x0f: m_IVR = val; break; |
| 62 | default: logerror("8X300: Invalid register %02x written to.\n",reg); break; |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | UINT8 n8x300_cpu_device::get_reg(UINT8 reg) |
| 67 | { |
| 68 | switch(reg) |
| 69 | { |
| 70 | case 0x00: return m_AUX; |
| 71 | case 0x01: return m_R1; |
| 72 | case 0x02: return m_R2; |
| 73 | case 0x03: return m_R3; |
| 74 | case 0x04: return m_R4; |
| 75 | case 0x05: return m_R5; |
| 76 | case 0x06: return m_R6; |
| 77 | // IVL is write-only |
| 78 | case 0x08: return m_OVF; |
| 79 | case 0x09: return m_R11; |
| 80 | // IVR is write-only |
| 81 | default: logerror("8X300: Invalid register %02x read.\n",reg); return 0; |
| 82 | } |
| 83 | return 0; |
| 84 | } |
| 85 | |
| 86 | void n8x300_cpu_device::device_start() |
| 87 | { |
| 88 | m_program = &space(AS_PROGRAM); |
| 89 | m_direct = &m_program->direct(); |
| 90 | m_io = &space(AS_IO); |
| 91 | |
| 92 | save_item(NAME(m_PC)); |
| 93 | save_item(NAME(m_AR)); |
| 94 | save_item(NAME(m_IR)); |
| 95 | save_item(NAME(m_R1)); |
| 96 | save_item(NAME(m_R2)); |
| 97 | save_item(NAME(m_R3)); |
| 98 | save_item(NAME(m_R4)); |
| 99 | save_item(NAME(m_R5)); |
| 100 | save_item(NAME(m_R6)); |
| 101 | save_item(NAME(m_R11)); |
| 102 | save_item(NAME(m_AUX)); |
| 103 | save_item(NAME(m_IVL)); |
| 104 | save_item(NAME(m_IVR)); |
| 105 | save_item(NAME(m_OVF)); |
| 106 | save_item(NAME(m_left_IV)); |
| 107 | save_item(NAME(m_right_IV)); |
| 108 | |
| 109 | // Register state for debugger |
| 110 | state_add( _8X300_PC, "PC", m_PC).mask(0x1fff).formatstr("%04X"); |
| 111 | state_add( _8X300_AR, "AR", m_AR).mask(0x1fff).formatstr("%04X"); |
| 112 | state_add( _8X300_IR, "IR", m_IR).mask(0xffff).formatstr("%04X"); |
| 113 | state_add( _8X300_AUX, "AUX", m_AUX).mask(0xff).formatstr("%02X"); |
| 114 | state_add( _8X300_R1, "R1", m_R1).mask(0xff).formatstr("%02X"); |
| 115 | state_add( _8X300_R2, "R2", m_R2).mask(0xff).formatstr("%02X"); |
| 116 | state_add( _8X300_R3, "R3", m_R3).mask(0xff).formatstr("%02X"); |
| 117 | state_add( _8X300_R4, "R4", m_R4).mask(0xff).formatstr("%02X"); |
| 118 | state_add( _8X300_R5, "R5", m_R5).mask(0xff).formatstr("%02X"); |
| 119 | state_add( _8X300_R6, "R6", m_R6).mask(0xff).formatstr("%02X"); |
| 120 | state_add( _8X300_R11, "R11", m_R11).mask(0xff).formatstr("%02X"); |
| 121 | state_add( _8X300_OVF, "OVF", m_OVF).mask(0x01).formatstr("%01X"); |
| 122 | state_add( _8X300_IVL, "IVL", m_IVL).mask(0xff).formatstr("%02X"); |
| 123 | state_add( _8X300_IVR, "IVR", m_IVR).mask(0xff).formatstr("%02X"); |
| 124 | state_add(STATE_GENPC, "curpc", m_genPC).noshow(); |
| 125 | |
| 126 | m_icountptr = &m_icount; |
| 127 | |
| 128 | // reset registers here, since they are unchanged when /RESET goes low. |
| 129 | m_R1 = 0; |
| 130 | m_R2 = 0; |
| 131 | m_R3 = 0; |
| 132 | m_R4 = 0; |
| 133 | m_R5 = 0; |
| 134 | m_R6 = 0; |
| 135 | m_R11 = 0; |
| 136 | m_IVL = 0; |
| 137 | m_IVR = 0; |
| 138 | m_AUX = 0; |
| 139 | } |
| 140 | |
| 141 | void n8x300_cpu_device::state_string_export(const device_state_entry &entry, astring &string) |
| 142 | { |
| 143 | switch (entry.index()) |
| 144 | { |
| 145 | // case STATE_GENFLAGS: |
| 146 | // string.printf("%c%c%c%c%c%c", |
| 147 | // break; |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | void n8x300_cpu_device::device_reset() |
| 152 | { |
| 153 | /* zero registers */ |
| 154 | m_PC = 0; |
| 155 | m_AR = 0; |
| 156 | m_IR = 0; |
| 157 | } |
| 158 | |
| 159 | void n8x300_cpu_device::execute_run() |
| 160 | { |
| 161 | do |
| 162 | { |
| 163 | UINT16 opcode; |
| 164 | UINT8 src = 0; |
| 165 | UINT8 dst; |
| 166 | UINT8 rotlen; // rotate amount or I/O field length |
| 167 | UINT8 mask; |
| 168 | UINT16 result; |
| 169 | |
| 170 | /* fetch the opcode */ |
| 171 | debugger_instruction_hook(this, m_genPC); |
| 172 | opcode = FETCHOP(m_genPC); |
| 173 | m_PC++; |
| 174 | m_PC &= 0x1fff; |
| 175 | m_AR = m_PC; |
| 176 | m_IR = opcode; |
| 177 | m_genPC = m_PC << 1; |
| 178 | |
| 179 | switch (OP) |
| 180 | { |
| 181 | case 0x00: // MOVE |
| 182 | rotlen = ROTLEN; |
| 183 | if(is_rot(opcode)) // MOVE reg,reg |
| 184 | { |
| 185 | src = get_reg(SRC); |
| 186 | dst = rotate(src,rotlen); |
| 187 | set_reg(DST,dst); |
| 188 | } |
| 189 | else |
| 190 | { |
| 191 | if(rotlen == 0) |
| 192 | rotlen = 8; // 0 = 8-bit I/O field length |
| 193 | if(is_src_reg(opcode) && !(is_dst_reg(opcode))) |
| 194 | { // MOVE reg,IV |
| 195 | DST_LATCH; |
| 196 | mask = ((1 << rotlen)-1); |
| 197 | src = (get_reg(SRC)) << (7-DST_LSB); |
| 198 | mask <<= (7-DST_LSB); |
| 199 | if(DST_IS_RIGHT_BANK) |
| 200 | { |
| 201 | dst = (m_right_IV & ~mask) | (src & mask); |
| 202 | m_right_IV = dst; |
| 203 | WRITEPORT(m_IVR+0x100,m_right_IV); |
| 204 | } |
| 205 | else |
| 206 | { |
| 207 | dst = (m_left_IV & ~mask) | (src & mask); |
| 208 | m_left_IV = dst; |
| 209 | WRITEPORT(m_IVL,m_left_IV); |
| 210 | } |
| 211 | } |
| 212 | else if(!(is_src_reg(opcode)) && is_dst_reg(opcode)) |
| 213 | { // MOVE IV,reg |
| 214 | SRC_LATCH; |
| 215 | if(SRC_IS_RIGHT_BANK) |
| 216 | src = rotate(m_right_IV,7-SRC_LSB); |
| 217 | else |
| 218 | src = rotate(m_left_IV,7-SRC_LSB); |
| 219 | mask = ((1 << rotlen)-1); |
| 220 | dst = src & mask; |
| 221 | set_reg(DST,dst); |
| 222 | } |
| 223 | else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode))) |
| 224 | { // MOVE IV,IV |
| 225 | SRC_LATCH; |
| 226 | if(SRC_IS_RIGHT_BANK) |
| 227 | src = rotate(m_right_IV,7-SRC_LSB); |
| 228 | else |
| 229 | src = rotate(m_left_IV,7-SRC_LSB); |
| 230 | mask = ((1 << rotlen)-1); |
| 231 | dst = src & mask; |
| 232 | dst <<= (7-DST_LSB); |
| 233 | mask <<= (7-DST_LSB); |
| 234 | if(SRC_IS_RIGHT_BANK) // untouched source IV bits are preserved and sent to destination IV |
| 235 | { |
| 236 | dst = (m_right_IV & ~mask) | (dst & mask); |
| 237 | m_right_IV = dst; |
| 238 | WRITEPORT(m_IVR+0x100,m_right_IV); |
| 239 | } |
| 240 | else |
| 241 | { |
| 242 | dst = (m_left_IV & ~mask) | (dst & mask); |
| 243 | m_left_IV = dst; |
| 244 | WRITEPORT(m_IVL,m_left_IV); |
| 245 | } |
| 246 | } |
| 247 | } |
| 248 | break; |
| 249 | case 0x01: // ADD |
| 250 | rotlen = ROTLEN; |
| 251 | if(is_rot(opcode)) |
| 252 | { // ADD reg,reg |
| 253 | src = rotate(get_reg(SRC),rotlen); |
| 254 | result = src + m_AUX; |
| 255 | set_reg(DST,result & 0xff); |
| 256 | SET_OVF; |
| 257 | } |
| 258 | else |
| 259 | { |
| 260 | if(rotlen == 0) |
| 261 | rotlen = 8; // 0 = 8-bit I/O field length |
| 262 | if(is_src_reg(opcode) && !(is_dst_reg(opcode))) |
| 263 | { // ADD reg,IV |
| 264 | DST_LATCH; |
| 265 | result = get_reg(SRC) + m_AUX; |
| 266 | mask = ((1 << rotlen)-1); |
| 267 | dst = (result & 0xff) << DST_LSB; |
| 268 | mask <<= DST_LSB; |
| 269 | SET_OVF; |
| 270 | if(DST_IS_RIGHT_BANK) |
| 271 | { |
| 272 | dst = (m_right_IV & ~mask) | (dst & mask); |
| 273 | m_right_IV = dst; |
| 274 | WRITEPORT(m_IVR+0x100,m_right_IV); |
| 275 | } |
| 276 | else |
| 277 | { |
| 278 | dst = (m_left_IV & ~mask) | (dst & mask); |
| 279 | m_left_IV = dst; |
| 280 | WRITEPORT(m_IVL,m_left_IV); |
| 281 | } |
| 282 | } |
| 283 | else if(!(is_src_reg(opcode)) && is_dst_reg(opcode)) |
| 284 | { // ADD IV,reg |
| 285 | SRC_LATCH; |
| 286 | mask = ((1 << rotlen)-1); |
| 287 | if(SRC_IS_RIGHT_BANK) |
| 288 | src = rotate(m_right_IV,7-SRC_LSB) & mask; |
| 289 | else |
| 290 | src = rotate(m_left_IV,7-SRC_LSB) & mask; |
| 291 | result = src + m_AUX; |
| 292 | SET_OVF; |
| 293 | set_reg(DST,result & 0xff); |
| 294 | } |
| 295 | else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode))) |
| 296 | { // ADD IV,IV |
| 297 | SRC_LATCH; |
| 298 | DST_LATCH; |
| 299 | mask = ((1 << rotlen)-1); |
| 300 | if(SRC_IS_RIGHT_BANK) |
| 301 | src = rotate(m_right_IV,7-SRC_LSB) & mask; |
| 302 | else |
| 303 | src = rotate(m_left_IV,7-SRC_LSB) & mask; |
| 304 | result = src + m_AUX; |
| 305 | SET_OVF; |
| 306 | dst = (result << (7-DST_LSB)) & 0xff; |
| 307 | mask <<= (7-DST_LSB); |
| 308 | if(SRC_IS_RIGHT_BANK) // unused destination IV data is not preserved, is merged with input IV data |
| 309 | { |
| 310 | dst = (m_right_IV & ~mask) | (dst & mask); |
| 311 | m_right_IV = dst; |
| 312 | WRITEPORT(m_IVR+0x100,m_right_IV); |
| 313 | } |
| 314 | else |
| 315 | { |
| 316 | dst = (m_left_IV & ~mask) | (dst & mask); |
| 317 | m_left_IV = dst; |
| 318 | WRITEPORT(m_IVL,m_left_IV); |
| 319 | } |
| 320 | } |
| 321 | } |
| 322 | break; |
| 323 | case 0x02: // AND |
| 324 | rotlen = ROTLEN; |
| 325 | if(is_rot(opcode)) |
| 326 | { // AND reg,reg |
| 327 | src = rotate(get_reg(SRC),rotlen); |
| 328 | dst = src & m_AUX; |
| 329 | set_reg(DST,dst); |
| 330 | } |
| 331 | else |
| 332 | { |
| 333 | if(rotlen == 0) |
| 334 | rotlen = 8; // 0 = 8-bit I/O field length |
| 335 | if(is_src_reg(opcode) && !(is_dst_reg(opcode))) |
| 336 | { // AND reg,IV |
| 337 | DST_LATCH; |
| 338 | src = get_reg(SRC) & m_AUX; |
| 339 | mask = ((1 << rotlen)-1); |
| 340 | src <<= (7-DST_LSB); |
| 341 | mask <<= (7-DST_LSB); |
| 342 | if(DST_IS_RIGHT_BANK) |
| 343 | { |
| 344 | dst = (m_right_IV & ~mask) | (src & mask); |
| 345 | m_right_IV = dst; |
| 346 | WRITEPORT(m_IVR+0x100,m_right_IV); |
| 347 | } |
| 348 | else |
| 349 | { |
| 350 | dst = (m_left_IV & ~mask) | (src & mask); |
| 351 | m_left_IV = dst; |
| 352 | WRITEPORT(m_IVL,m_left_IV); |
| 353 | } |
| 354 | } |
| 355 | else if(!(is_src_reg(opcode)) && is_dst_reg(opcode)) |
| 356 | { // AND IV,reg |
| 357 | SRC_LATCH; |
| 358 | mask = ((1 << rotlen)-1); |
| 359 | if(SRC_IS_RIGHT_BANK) |
| 360 | src = rotate(m_right_IV,7-SRC_LSB) & mask; |
| 361 | else |
| 362 | src = rotate(m_left_IV,7-SRC_LSB) & mask; |
| 363 | src &= mask; |
| 364 | dst = src & m_AUX; |
| 365 | set_reg(DST,dst); |
| 366 | } |
| 367 | else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode))) |
| 368 | { // AND IV,IV |
| 369 | SRC_LATCH; |
| 370 | DST_LATCH; |
| 371 | mask = ((1 << rotlen)-1); |
| 372 | if(SRC_IS_RIGHT_BANK) |
| 373 | src = rotate(m_right_IV,7-SRC_LSB) & mask; |
| 374 | else |
| 375 | src = rotate(m_left_IV,7-SRC_LSB) & mask; |
| 376 | src &= mask; |
| 377 | dst = src & m_AUX; |
| 378 | dst <<= (7-DST_LSB); |
| 379 | mask <<= (7-DST_LSB); |
| 380 | if(SRC_IS_RIGHT_BANK) |
| 381 | { |
| 382 | dst = (m_right_IV & ~mask) | (src & mask); |
| 383 | m_right_IV = dst; |
| 384 | WRITEPORT(m_IVR+0x100,m_right_IV); |
| 385 | } |
| 386 | else |
| 387 | { |
| 388 | dst = (m_left_IV & ~mask) | (src & mask); |
| 389 | m_left_IV = dst; |
| 390 | WRITEPORT(m_IVL,m_left_IV); |
| 391 | } |
| 392 | } |
| 393 | } |
| 394 | break; |
| 395 | case 0x03: // XOR |
| 396 | rotlen = ROTLEN; |
| 397 | if(is_rot(opcode)) |
| 398 | { // AND reg,reg |
| 399 | src = rotate(get_reg(SRC),rotlen); |
| 400 | dst = src ^ m_AUX; |
| 401 | set_reg(DST,dst); |
| 402 | } |
| 403 | else |
| 404 | { |
| 405 | if(rotlen == 0) |
| 406 | rotlen = 8; // 0 = 8-bit I/O field length |
| 407 | if(is_src_reg(opcode) && !(is_dst_reg(opcode))) |
| 408 | { // AND reg,IV |
| 409 | DST_LATCH; |
| 410 | src = get_reg(SRC) ^ m_AUX; |
| 411 | mask = ((1 << rotlen)-1); |
| 412 | src <<= (7-DST_LSB); |
| 413 | mask <<= (7-DST_LSB); |
| 414 | if(DST_IS_RIGHT_BANK) |
| 415 | { |
| 416 | dst = (m_right_IV & ~mask) | (src & mask); |
| 417 | m_right_IV = dst; |
| 418 | WRITEPORT(m_IVR+0x100,m_right_IV); |
| 419 | } |
| 420 | else |
| 421 | { |
| 422 | dst = (m_left_IV & ~mask) | (src & mask); |
| 423 | m_left_IV = dst; |
| 424 | WRITEPORT(m_IVL,m_left_IV); |
| 425 | } |
| 426 | } |
| 427 | else if(!(is_src_reg(opcode)) && is_dst_reg(opcode)) |
| 428 | { // AND IV,reg |
| 429 | SRC_LATCH; |
| 430 | mask = ((1 << rotlen)-1); |
| 431 | if(SRC_IS_RIGHT_BANK) |
| 432 | src = rotate(m_right_IV,7-SRC_LSB) & mask; |
| 433 | else |
| 434 | src = rotate(m_left_IV,7-SRC_LSB) & mask; |
| 435 | src &= mask; |
| 436 | dst = src ^ m_AUX; |
| 437 | set_reg(DST,dst); |
| 438 | } |
| 439 | else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode))) |
| 440 | { // AND IV,IV |
| 441 | SRC_LATCH; |
| 442 | DST_LATCH; |
| 443 | mask = ((1 << rotlen)-1); |
| 444 | if(SRC_IS_RIGHT_BANK) |
| 445 | src = rotate(m_right_IV,7-SRC_LSB) & mask; |
| 446 | else |
| 447 | src = rotate(m_left_IV,7-SRC_LSB) & mask; |
| 448 | src &= mask; |
| 449 | dst = src ^ m_AUX; |
| 450 | dst <<= (7-DST_LSB); |
| 451 | mask <<= (7-DST_LSB); |
| 452 | if(SRC_IS_RIGHT_BANK) |
| 453 | { |
| 454 | dst = (m_right_IV & ~mask) | (src & mask); |
| 455 | m_right_IV = dst; |
| 456 | WRITEPORT(m_IVR+0x100,m_right_IV); |
| 457 | } |
| 458 | else |
| 459 | { |
| 460 | dst = (m_left_IV & ~mask) | (src & mask); |
| 461 | m_left_IV = dst; |
| 462 | WRITEPORT(m_IVL,m_left_IV); |
| 463 | } |
| 464 | } |
| 465 | } |
| 466 | break; |
| 467 | case 0x04: // XEC (Execute) |
| 468 | if(is_src_reg(opcode)) |
| 469 | { |
| 470 | src = get_reg(SRC); |
| 471 | src += IMM8; |
| 472 | SET_AR((m_AR & 0x1f00) | src); |
| 473 | } |
| 474 | else |
| 475 | { |
| 476 | SRC_LATCH; |
| 477 | rotlen = ROTLEN; |
| 478 | if(rotlen == 0) |
| 479 | rotlen = 8; // 0 = 8-bit I/O field length |
| 480 | mask = ((1 << rotlen)-1); |
| 481 | if(SRC_IS_RIGHT_BANK) |
| 482 | src = rotate(m_right_IV,7-SRC_LSB); |
| 483 | else |
| 484 | src = rotate(m_left_IV,7-SRC_LSB); |
| 485 | src &= mask; |
| 486 | src += IMM5; |
| 487 | SET_AR((m_AR & 0x1fe0) | (src & 0x1f)); |
| 488 | } |
| 489 | break; |
| 490 | case 0x05: // NZT (Non-zero transfer) |
| 491 | if(is_src_reg(opcode)) |
| 492 | { |
| 493 | src = get_reg(SRC); |
| 494 | if(src != 0) |
| 495 | SET_PC((m_PC & 0x1f00) | IMM8); |
| 496 | } |
| 497 | else |
| 498 | { |
| 499 | SRC_LATCH; |
| 500 | rotlen = ROTLEN; |
| 501 | if(rotlen == 0) |
| 502 | rotlen = 8; // 0 = 8-bit I/O field length |
| 503 | mask = ((1 << rotlen)-1); |
| 504 | if(SRC_IS_RIGHT_BANK) |
| 505 | src = rotate(m_right_IV,7-SRC_LSB); |
| 506 | else |
| 507 | src = rotate(m_left_IV,7-SRC_LSB); |
| 508 | rotate(src,SRC_LSB); |
| 509 | src &= mask; |
| 510 | if(src != 0) |
| 511 | SET_PC((m_PC & 0x1fe0) | IMM5); |
| 512 | } |
| 513 | break; |
| 514 | case 0x06: // XMIT (Transmit) |
| 515 | // the source is actually the destination for this instruction |
| 516 | if(is_src_reg(opcode)) |
| 517 | set_reg(SRC,IMM8); |
| 518 | else |
| 519 | { |
| 520 | SRC_LATCH; |
| 521 | rotlen = ROTLEN; |
| 522 | if(rotlen == 0) |
| 523 | rotlen = 8; // 0 = 8-bit I/O field length |
| 524 | mask = ((1 << rotlen)-1); |
| 525 | dst = IMM5; |
| 526 | mask <<= (7-SRC_LSB); |
| 527 | dst <<= (7-SRC_LSB); |
| 528 | if(SRC_IS_RIGHT_BANK) |
| 529 | { |
| 530 | m_right_IV = (m_right_IV & ~mask) | (dst & mask); |
| 531 | WRITEPORT(m_IVR+0x100,m_right_IV); |
| 532 | } |
| 533 | else |
| 534 | { |
| 535 | m_left_IV = (m_left_IV & ~mask) | (dst & mask); |
| 536 | WRITEPORT(m_IVL,m_left_IV); |
| 537 | } |
| 538 | } |
| 539 | break; |
| 540 | case 0x07: // JMP |
| 541 | SET_PC(ADDR); |
| 542 | break; |
| 543 | } |
| 544 | CYCLES(1); // all instructions take 1 cycle (250ns) |
| 545 | } while (m_icount > 0); |
| 546 | } |
| 547 | |
| 548 | offs_t n8x300_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 549 | { |
| 550 | extern CPU_DISASSEMBLE( n8x300 ); |
| 551 | return CPU_DISASSEMBLE_NAME(n8x300)(this, buffer, pc, oprom, opram, options); |
| 552 | } |
| 553 | |
trunk/src/mess/drivers/wicat.c
| r26678 | r26679 | |
| 11 | 11 | #include "emu.h" |
| 12 | 12 | #include "cpu/m68000/m68000.h" |
| 13 | 13 | #include "cpu/z8000/z8000.h" |
| 14 | #include "cpu/8x300/8x300.h" |
| 14 | 15 | #include "machine/serial.h" |
| 15 | 16 | #include "machine/6522via.h" |
| 16 | 17 | #include "machine/mm58274c.h" |
| r26678 | r26679 | |
| 19 | 20 | #include "video/i8275x.h" |
| 20 | 21 | #include "machine/am9517a.h" |
| 21 | 22 | #include "machine/x2212.h" |
| 23 | #include "machine/wd17xx.h" |
| 22 | 24 | #include "wicat.lh" |
| 23 | 25 | |
| 24 | 26 | class wicat_state : public driver_device |
| r26678 | r26679 | |
| 159 | 161 | AM_RANGE(0x9000,0x9fff) AM_ROM AM_REGION("g2char",0x0000) |
| 160 | 162 | ADDRESS_MAP_END |
| 161 | 163 | |
| 164 | static ADDRESS_MAP_START(wicat_flop_mem, AS_PROGRAM, 16, wicat_state) |
| 165 | AM_RANGE(0x0000, 0x17ff) AM_ROM AM_REGION("wd3", 0x0000) |
| 166 | AM_RANGE(0x1800, 0x1fff) AM_NOP |
| 167 | ADDRESS_MAP_END |
| 162 | 168 | |
| 169 | static ADDRESS_MAP_START(wicat_flop_io, AS_IO, 8, wicat_state) |
| 170 | AM_RANGE(0x0000, 0x00ff) AM_RAM // left bank |
| 171 | AM_RANGE(0x0100, 0x01ff) AM_RAM // right bank -- one of these probably is RAM... |
| 172 | ADDRESS_MAP_END |
| 173 | |
| 174 | |
| 163 | 175 | /* Input ports */ |
| 164 | 176 | static INPUT_PORTS_START( wicat ) |
| 165 | 177 | INPUT_PORTS_END |
| r26678 | r26679 | |
| 673 | 685 | MCFG_X2212_ADD("videosram") // XD2210 |
| 674 | 686 | |
| 675 | 687 | MCFG_SCREEN_ADD("screen",RASTER) |
| 676 | | MCFG_SCREEN_SIZE(400,300) |
| 677 | | MCFG_SCREEN_VISIBLE_AREA(0,400-1,0,300-1) |
| 688 | MCFG_SCREEN_SIZE(720,300) |
| 689 | MCFG_SCREEN_VISIBLE_AREA(0,720-1,0,300-1) |
| 678 | 690 | MCFG_SCREEN_REFRESH_RATE(60) |
| 679 | 691 | MCFG_SCREEN_UPDATE_DEVICE("video",i8275x_device,screen_update) |
| 680 | 692 | |
| r26678 | r26679 | |
| 684 | 696 | |
| 685 | 697 | MCFG_DEFAULT_LAYOUT(layout_wicat) |
| 686 | 698 | |
| 699 | /* Winchester Floppy Controller */ |
| 700 | MCFG_CPU_ADD("floppycpu",N8X300,XTAL_8MHz) |
| 701 | MCFG_CPU_PROGRAM_MAP(wicat_flop_mem) |
| 702 | MCFG_CPU_IO_MAP(wicat_flop_io) |
| 703 | // MCFG_FD1795_ADD("fdc") |
| 704 | |
| 687 | 705 | MACHINE_CONFIG_END |
| 688 | 706 | |
| 689 | 707 | /* ROM definition */ |
| r26678 | r26679 | |
| 750 | 768 | ROM_LOAD ("apl.chr", 0x00800, 0x0800, CRC(8c6d698e) SHA1(147dd9296fe2efc6140fa148a6edf673c33f9371) ) |
| 751 | 769 | |
| 752 | 770 | // Winchester Floppy Controller (Signetics N8X300I + FD1795) |
| 753 | | ROM_REGION(0x1800, "wd3", 0) |
| 754 | | ROM_LOAD ("wd3.u95", 0x00000, 0x0800, CRC(80bb0617) SHA1(ac0f3194fcbef77532571baa3fec78b3010528bf) ) |
| 755 | | ROM_LOAD ("wd3.u96", 0x00800, 0x0800, CRC(52736e61) SHA1(71c7c9170c733c483393969cb1cb3798b3eb980c) ) |
| 756 | | ROM_LOAD ("wd3.u97", 0x01000, 0x0800, CRC(a66619ec) SHA1(5d091ac7c88f2f45b4a05e78bfc7a16c206b31ff) ) |
| 771 | ROM_REGION16_BE(0x1800, "wd3", 0) |
| 772 | ROM_LOAD16_BYTE("wd3.u96", 0x00000, 0x0800, CRC(52736e61) SHA1(71c7c9170c733c483393969cb1cb3798b3eb980c) ) |
| 773 | ROM_LOAD16_BYTE("wd3.u97", 0x00001, 0x0800, CRC(a66619ec) SHA1(5d091ac7c88f2f45b4a05e78bfc7a16c206b31ff) ) |
| 774 | ROM_LOAD ("wd3.u95", 0x01000, 0x0800, CRC(80bb0617) SHA1(ac0f3194fcbef77532571baa3fec78b3010528bf) ) |
| 757 | 775 | ROM_END |
| 758 | 776 | |
| 759 | 777 | |
| 760 | 778 | /* Driver */ |
| 761 | 779 | |
| 762 | 780 | /* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ |
| 763 | | COMP( 198?, wicat, 0, 0, wicat, wicat, driver_device, 0, "Millennium Systems", "Wicat", GAME_NOT_WORKING | GAME_NO_SOUND_HW ) |
| 781 | COMP( 1982, wicat, 0, 0, wicat, wicat, driver_device, 0, "Millennium Systems", "Wicat System 150", GAME_NOT_WORKING | GAME_NO_SOUND_HW ) |