trunk/src/emu/cpu/hmcs40/hmcs40.c
| r244799 | r244800 | |
| 10 | 10 | |
| 11 | 11 | */ |
| 12 | 12 | |
| 13 | enum |
| 14 | { |
| 15 | FAMILY_HMCS42 = 0, |
| 16 | FAMILY_HMCS43, |
| 17 | FAMILY_HMCS44, |
| 18 | FAMILY_HMCS45, |
| 19 | FAMILY_HMCS46, |
| 20 | FAMILY_HMCS47, |
| 21 | }; |
| 22 | |
| 23 | #define IS_CMOS true |
| 24 | #define IS_PMOS false |
| 25 | |
| 13 | 26 | #include "hmcs40.h" |
| 14 | 27 | #include "debugger.h" |
| 15 | 28 | |
| r244799 | r244800 | |
| 75 | 88 | |
| 76 | 89 | |
| 77 | 90 | // device definitions |
| 91 | hmcs43_cpu_device::hmcs43_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, bool is_cmos, const char *shortname) |
| 92 | : hmcs40_cpu_device(mconfig, type, name, tag, owner, clock, FAMILY_HMCS43, is_cmos, 3, 12, ADDRESS_MAP_NAME(program_1k), 7, ADDRESS_MAP_NAME(data_80x4), shortname, __FILE__) |
| 93 | { } |
| 94 | |
| 78 | 95 | hd38750_device::hd38750_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 79 | | : hmcs40_cpu_device(mconfig, HD38750, "HD38750", tag, owner, clock, 3, 12, ADDRESS_MAP_NAME(program_1k), 7, ADDRESS_MAP_NAME(data_80x4), "hd38750", __FILE__) |
| 96 | : hmcs43_cpu_device(mconfig, HD38750, "HD38750", tag, owner, clock, IS_PMOS, "hd38750") |
| 80 | 97 | { } |
| 81 | 98 | |
| 99 | |
| 100 | hmcs44_cpu_device::hmcs44_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, bool is_cmos, const char *shortname) |
| 101 | : hmcs40_cpu_device(mconfig, type, name, tag, owner, clock, FAMILY_HMCS44, is_cmos, 4, 13, ADDRESS_MAP_NAME(program_2k), 8, ADDRESS_MAP_NAME(data_160x4), shortname, __FILE__) |
| 102 | { } |
| 103 | |
| 82 | 104 | hd38800_device::hd38800_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 83 | | : hmcs40_cpu_device(mconfig, HD38800, "HD38800", tag, owner, clock, 4, 13, ADDRESS_MAP_NAME(program_2k), 8, ADDRESS_MAP_NAME(data_160x4), "hd38800", __FILE__) |
| 105 | : hmcs44_cpu_device(mconfig, HD38800, "HD38800", tag, owner, clock, IS_PMOS, "hd38800") |
| 84 | 106 | { } |
| 85 | 107 | |
| 108 | |
| 109 | hmcs45_cpu_device::hmcs45_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, bool is_cmos, const char *shortname) |
| 110 | : hmcs40_cpu_device(mconfig, type, name, tag, owner, clock, FAMILY_HMCS45, is_cmos, 4, 13, ADDRESS_MAP_NAME(program_2k), 8, ADDRESS_MAP_NAME(data_160x4), shortname, __FILE__) |
| 111 | { } |
| 112 | |
| 86 | 113 | hd38820_device::hd38820_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 87 | | : hmcs40_cpu_device(mconfig, HD38820, "HD38820", tag, owner, clock, 4, 13, ADDRESS_MAP_NAME(program_2k), 8, ADDRESS_MAP_NAME(data_160x4), "hd38820", __FILE__) |
| 114 | : hmcs45_cpu_device(mconfig, HD38820, "HD38820", tag, owner, clock, IS_PMOS, "hd38820") |
| 88 | 115 | { } |
| 89 | 116 | |
| 90 | 117 | |
| r244799 | r244800 | |
| 101 | 128 | break; |
| 102 | 129 | |
| 103 | 130 | case STATE_GENPC: |
| 104 | | string.printf("%03X", m_pc << 1); |
| 131 | string.printf("%04X", m_pc << 1); |
| 105 | 132 | break; |
| 106 | 133 | |
| 107 | 134 | default: break; |
| r244799 | r244800 | |
| 132 | 159 | m_data = &space(AS_DATA); |
| 133 | 160 | m_prgmask = (1 << m_prgwidth) - 1; |
| 134 | 161 | m_datamask = (1 << m_datawidth) - 1; |
| 135 | | m_xmask = (1 << (m_datawidth - 4)) - 1; |
| 162 | |
| 163 | UINT8 defval = (m_is_cmos) ? 0xf : 0; |
| 164 | m_read_r0.resolve_safe(defval); |
| 165 | m_read_r1.resolve_safe(defval); |
| 166 | m_read_r2.resolve_safe(defval); |
| 167 | m_read_r3.resolve_safe(defval); |
| 168 | m_read_r4.resolve_safe(defval); |
| 169 | m_read_r5.resolve_safe(defval); |
| 170 | m_read_r6.resolve_safe(defval); |
| 171 | m_read_r7.resolve_safe(defval); |
| 172 | |
| 173 | m_write_r0.resolve_safe(); |
| 174 | m_write_r1.resolve_safe(); |
| 175 | m_write_r2.resolve_safe(); |
| 176 | m_write_r3.resolve_safe(); |
| 177 | m_write_r4.resolve_safe(); |
| 178 | m_write_r5.resolve_safe(); |
| 179 | m_write_r6.resolve_safe(); |
| 180 | m_write_r7.resolve_safe(); |
| 136 | 181 | |
| 137 | | m_read_d.resolve_safe(0); |
| 182 | m_read_d.resolve_safe((m_is_cmos) ? 0xffff : 0); |
| 138 | 183 | m_write_d.resolve_safe(); |
| 139 | 184 | |
| 140 | 185 | // zerofill |
| 141 | 186 | memset(m_stack, 0, sizeof(m_stack)); |
| 142 | 187 | m_op = 0; |
| 143 | 188 | m_prev_op = 0; |
| 144 | | m_arg = 0; |
| 145 | 189 | m_pc = 0; |
| 190 | m_prev_pc = 0; |
| 146 | 191 | m_page = 0; |
| 147 | 192 | m_a = 0; |
| 148 | 193 | m_b = 0; |
| r244799 | r244800 | |
| 150 | 195 | m_spx = 0; |
| 151 | 196 | m_y = 0; |
| 152 | 197 | m_spy = 0; |
| 153 | | m_s = 0; |
| 198 | m_s = 1; |
| 154 | 199 | m_c = 0; |
| 200 | memset(m_r, 0, sizeof(m_r)); |
| 201 | m_d = 0; |
| 155 | 202 | |
| 156 | 203 | // register for savestates |
| 157 | 204 | save_item(NAME(m_stack)); |
| 158 | 205 | save_item(NAME(m_op)); |
| 159 | 206 | save_item(NAME(m_prev_op)); |
| 160 | | save_item(NAME(m_arg)); |
| 161 | 207 | save_item(NAME(m_pc)); |
| 208 | save_item(NAME(m_prev_pc)); |
| 162 | 209 | save_item(NAME(m_page)); |
| 163 | 210 | save_item(NAME(m_a)); |
| 164 | 211 | save_item(NAME(m_b)); |
| r244799 | r244800 | |
| 168 | 215 | save_item(NAME(m_spy)); |
| 169 | 216 | save_item(NAME(m_s)); |
| 170 | 217 | save_item(NAME(m_c)); |
| 218 | save_item(NAME(m_r)); |
| 219 | save_item(NAME(m_d)); |
| 171 | 220 | |
| 172 | 221 | // register state for debugger |
| 173 | 222 | state_add(HMCS40_PC, "PC", m_pc).formatstr("%04X"); |
| r244799 | r244800 | |
| 178 | 227 | state_add(HMCS40_Y, "Y", m_y).formatstr("%01X"); |
| 179 | 228 | state_add(HMCS40_SPY, "SPY", m_spy).formatstr("%01X"); |
| 180 | 229 | |
| 181 | | state_add(STATE_GENPC, "curpc", m_pc).formatstr("%03X").noshow(); |
| 230 | state_add(STATE_GENPC, "curpc", m_pc).formatstr("%04X").noshow(); |
| 182 | 231 | state_add(STATE_GENFLAGS, "GENFLAGS", m_s).formatstr("%2s").noshow(); |
| 183 | 232 | |
| 184 | 233 | m_icountptr = &m_icount; |
| r244799 | r244800 | |
| 192 | 241 | |
| 193 | 242 | void hmcs40_cpu_device::device_reset() |
| 194 | 243 | { |
| 195 | | m_pc = 0xffff & m_prgmask; |
| 196 | | m_op = 0; |
| 244 | m_pc = m_prgmask; |
| 245 | m_prev_op = m_op = 0; |
| 246 | |
| 247 | // clear i/o |
| 248 | m_d = (m_is_cmos) ? 0xffff : 0; |
| 249 | for (int i = 0; i < 16; i++) |
| 250 | hmcs40_cpu_device::write_d(i, (m_is_cmos) ? 1 : 0); |
| 251 | |
| 252 | for (int i = 0; i < 8; i++) |
| 253 | hmcs40_cpu_device::write_r(i, (m_is_cmos) ? 0xf : 0); |
| 197 | 254 | } |
| 198 | 255 | |
| 199 | 256 | |
| r244799 | r244800 | |
| 217 | 274 | m_pc = (m_pc & ~mask) | ((m_pc << 1 | fb) & mask); |
| 218 | 275 | } |
| 219 | 276 | |
| 220 | | inline void hmcs40_cpu_device::fetch_arg() |
| 221 | | { |
| 222 | | // P is the only 2-byte opcode |
| 223 | | if ((m_op & 0x3f8) == 0x368) |
| 224 | | { |
| 225 | | m_icount--; |
| 226 | | m_arg = m_program->read_word(m_pc << 1); |
| 227 | | increment_pc(); |
| 228 | | } |
| 229 | | } |
| 230 | | |
| 231 | 277 | void hmcs40_cpu_device::execute_run() |
| 232 | 278 | { |
| 233 | 279 | while (m_icount > 0) |
| r244799 | r244800 | |
| 238 | 284 | if ((m_prev_op & 0x3e0) == 0x340) |
| 239 | 285 | m_pc = ((m_page << 6) | (m_pc & 0x3f)) & m_prgmask; |
| 240 | 286 | |
| 241 | | // remember previous opcode |
| 287 | // remember previous state |
| 242 | 288 | m_prev_op = m_op; |
| 289 | m_prev_pc = m_pc; |
| 243 | 290 | |
| 244 | 291 | // fetch next opcode |
| 245 | 292 | debugger_instruction_hook(this, m_pc << 1); |
| 246 | 293 | m_op = m_program->read_word(m_pc << 1); |
| 247 | 294 | increment_pc(); |
| 248 | | fetch_arg(); |
| 249 | 295 | } |
| 250 | 296 | } |
trunk/src/emu/cpu/hmcs40/hmcs40.h
| r244799 | r244800 | |
| 13 | 13 | |
| 14 | 14 | |
| 15 | 15 | // I/O ports setup |
| 16 | |
| 17 | // max 8 4-bit R ports |
| 18 | #define MCFG_HMCS40_READ_R_CB(_r, _devcb) \ |
| 19 | hmcs40_cpu_device::set_read_r##_r_callback(*device, DEVCB_##_devcb); |
| 20 | #define MCFG_HMCS40_WRITE_R_CB(_r, _devcb) \ |
| 21 | hmcs40_cpu_device::set_write_r##_r_callback(*device, DEVCB_##_devcb); |
| 22 | |
| 23 | // 16-bit discrete |
| 16 | 24 | #define MCFG_HMCS40_READ_A_CB(_devcb) \ |
| 17 | 25 | hmcs40_cpu_device::set_read_d_callback(*device, DEVCB_##_devcb); |
| 18 | 26 | #define MCFG_HMCS40_WRITE_D_CB(_devcb) \ |
| r244799 | r244800 | |
| 24 | 32 | { |
| 25 | 33 | public: |
| 26 | 34 | // construction/destruction |
| 27 | | hmcs40_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source) |
| 35 | hmcs40_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int family, bool is_cmos, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source) |
| 28 | 36 | : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source) |
| 29 | 37 | , m_program_config("program", ENDIANNESS_LITTLE, 16, prgwidth, 0, program) |
| 30 | 38 | , m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data) |
| 31 | 39 | , m_prgwidth(prgwidth-1) |
| 32 | 40 | , m_datawidth(datawidth) |
| 41 | , m_family(family) |
| 42 | , m_is_cmos(is_cmos) |
| 33 | 43 | , m_stack_levels(stack_levels) |
| 44 | , m_read_r0(*this), m_read_r1(*this), m_read_r2(*this), m_read_r3(*this), m_read_r4(*this), m_read_r5(*this), m_read_r6(*this), m_read_r7(*this) |
| 45 | , m_write_r0(*this), m_write_r1(*this), m_write_r2(*this), m_write_r3(*this), m_write_r4(*this), m_write_r5(*this), m_write_r6(*this), m_write_r7(*this) |
| 34 | 46 | , m_read_d(*this) |
| 35 | 47 | , m_write_d(*this) |
| 36 | 48 | { } |
| 37 | 49 | |
| 38 | 50 | // static configuration helpers |
| 51 | template<class _Object> static devcb_base &set_read_r0_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r0.set_callback(object); } |
| 52 | template<class _Object> static devcb_base &set_read_r1_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r1.set_callback(object); } |
| 53 | template<class _Object> static devcb_base &set_read_r2_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r2.set_callback(object); } |
| 54 | template<class _Object> static devcb_base &set_read_r3_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r3.set_callback(object); } |
| 55 | template<class _Object> static devcb_base &set_read_r4_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r4.set_callback(object); } |
| 56 | template<class _Object> static devcb_base &set_read_r5_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r5.set_callback(object); } |
| 57 | template<class _Object> static devcb_base &set_read_r6_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r6.set_callback(object); } |
| 58 | template<class _Object> static devcb_base &set_read_r7_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r7.set_callback(object); } |
| 59 | |
| 60 | template<class _Object> static devcb_base &set_write_r0_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r0.set_callback(object); } |
| 61 | template<class _Object> static devcb_base &set_write_r1_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r1.set_callback(object); } |
| 62 | template<class _Object> static devcb_base &set_write_r2_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r2.set_callback(object); } |
| 63 | template<class _Object> static devcb_base &set_write_r3_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r3.set_callback(object); } |
| 64 | template<class _Object> static devcb_base &set_write_r4_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r4.set_callback(object); } |
| 65 | template<class _Object> static devcb_base &set_write_r5_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r5.set_callback(object); } |
| 66 | template<class _Object> static devcb_base &set_write_r6_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r6.set_callback(object); } |
| 67 | template<class _Object> static devcb_base &set_write_r7_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r7.set_callback(object); } |
| 68 | |
| 39 | 69 | template<class _Object> static devcb_base &set_read_d_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_d.set_callback(object); } |
| 40 | 70 | template<class _Object> static devcb_base &set_write_d_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_d.set_callback(object); } |
| 41 | 71 | |
| r244799 | r244800 | |
| 54 | 84 | virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return(spacenum == AS_PROGRAM) ? &m_program_config :((spacenum == AS_DATA) ? &m_data_config : NULL); } |
| 55 | 85 | |
| 56 | 86 | // device_disasm_interface overrides |
| 57 | | virtual UINT32 disasm_min_opcode_bytes() const { return 1; } |
| 87 | virtual UINT32 disasm_min_opcode_bytes() const { return 2; } |
| 58 | 88 | virtual UINT32 disasm_max_opcode_bytes() const { return 2; } |
| 59 | 89 | virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); |
| 60 | 90 | void state_string_export(const device_state_entry &entry, astring &string); |
| r244799 | r244800 | |
| 68 | 98 | int m_datawidth; |
| 69 | 99 | int m_prgmask; |
| 70 | 100 | int m_datamask; |
| 71 | | int m_xmask; |
| 101 | int m_family; // MCU family (42-47) |
| 102 | bool m_is_cmos; |
| 72 | 103 | int m_stack_levels; // number of callstack levels |
| 73 | 104 | UINT16 m_stack[4]; // max 4 |
| 74 | | UINT16 m_op; |
| 105 | UINT16 m_op; // current opcode |
| 75 | 106 | UINT16 m_prev_op; |
| 76 | | UINT16 m_arg; |
| 77 | 107 | int m_icount; |
| 78 | 108 | |
| 79 | 109 | UINT16 m_pc; // Program Counter |
| 110 | UINT16 m_prev_pc; |
| 80 | 111 | UINT8 m_page; // LPU prepared page |
| 81 | 112 | UINT8 m_a; // 4-bit Accumulator |
| 82 | 113 | UINT8 m_b; // 4-bit B register |
| r244799 | r244800 | |
| 86 | 117 | UINT8 m_spy; // 4-bit SPY register |
| 87 | 118 | UINT8 m_s; // Status F/F |
| 88 | 119 | UINT8 m_c; // Carry F/F |
| 120 | UINT8 m_r[8]; // R outputs state |
| 121 | UINT16 m_d; // D pins state |
| 89 | 122 | |
| 90 | 123 | // i/o handlers |
| 124 | devcb_read8 m_read_r0, m_read_r1, m_read_r2, m_read_r3, m_read_r4, m_read_r5, m_read_r6, m_read_r7; |
| 125 | devcb_write8 m_write_r0, m_write_r1, m_write_r2, m_write_r3, m_write_r4, m_write_r5, m_write_r6, m_write_r7; |
| 91 | 126 | devcb_read16 m_read_d; |
| 92 | 127 | devcb_write16 m_write_d; |
| 93 | 128 | |
| 94 | 129 | // misc internal helpers |
| 95 | 130 | void increment_pc(); |
| 96 | | void fetch_arg(); |
| 97 | | |
| 131 | |
| 98 | 132 | UINT8 ram_r(); |
| 99 | 133 | void ram_w(UINT8 data); |
| 100 | 134 | void pop_stack(); |
| 101 | 135 | void push_stack(); |
| 102 | 136 | |
| 137 | virtual UINT8 read_r(int index); |
| 138 | virtual void write_r(int index, UINT8 data); |
| 139 | virtual int read_d(int index); |
| 140 | virtual void write_d(int index, int state); |
| 141 | |
| 103 | 142 | // opcode handlers |
| 104 | 143 | void op_lab(); |
| 105 | 144 | void op_lba(); |
| r244799 | r244800 | |
| 202 | 241 | }; |
| 203 | 242 | |
| 204 | 243 | |
| 205 | | class hd38750_device : public hmcs40_cpu_device |
| 244 | class hmcs43_cpu_device : public hmcs40_cpu_device |
| 206 | 245 | { |
| 207 | 246 | public: |
| 247 | hmcs43_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, bool is_cmos, const char *shortname); |
| 248 | |
| 249 | protected: |
| 250 | // overrides |
| 251 | virtual UINT8 read_r(int index); |
| 252 | virtual void write_r(int index, UINT8 data); |
| 253 | virtual int read_d(int index); |
| 254 | }; |
| 255 | |
| 256 | class hd38750_device : public hmcs43_cpu_device |
| 257 | { |
| 258 | public: |
| 208 | 259 | hd38750_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 209 | 260 | }; |
| 210 | 261 | |
| 211 | 262 | |
| 212 | | class hd38800_device : public hmcs40_cpu_device |
| 263 | class hmcs44_cpu_device : public hmcs40_cpu_device |
| 213 | 264 | { |
| 214 | 265 | public: |
| 266 | hmcs44_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, bool is_cmos, const char *shortname); |
| 267 | |
| 268 | protected: |
| 269 | // overrides |
| 270 | virtual UINT8 read_r(int index); |
| 271 | virtual void write_r(int index, UINT8 data); |
| 272 | }; |
| 273 | |
| 274 | class hd38800_device : public hmcs44_cpu_device |
| 275 | { |
| 276 | public: |
| 215 | 277 | hd38800_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 216 | 278 | }; |
| 217 | 279 | |
| 218 | 280 | |
| 219 | | class hd38820_device : public hmcs40_cpu_device |
| 281 | class hmcs45_cpu_device : public hmcs40_cpu_device |
| 220 | 282 | { |
| 221 | 283 | public: |
| 284 | hmcs45_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, bool is_cmos, const char *shortname); |
| 285 | |
| 286 | protected: |
| 287 | // overrides |
| 288 | virtual UINT8 read_r(int index); |
| 289 | virtual void write_r(int index, UINT8 data); |
| 290 | }; |
| 291 | |
| 292 | class hd38820_device : public hmcs45_cpu_device |
| 293 | { |
| 294 | public: |
| 222 | 295 | hd38820_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 223 | 296 | }; |
| 224 | 297 | |
trunk/src/emu/cpu/hmcs40/hmcs40op.inc
| r244799 | r244800 | |
| 28 | 28 | m_stack[0] = m_pc; |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | | void hmcs40_cpu_device::op_illegal() |
| 31 | |
| 32 | // i/o |
| 33 | |
| 34 | UINT8 hmcs40_cpu_device::read_r(int index) |
| 32 | 35 | { |
| 33 | | logerror("%s unknown opcode $%03X at $%04X\n", tag(), m_op, m_pc); |
| 36 | index &= 7; |
| 37 | UINT8 inp = 0xf; |
| 38 | |
| 39 | switch (index) |
| 40 | { |
| 41 | case 0: inp = m_read_r0(index, 0xff); break; |
| 42 | case 1: inp = m_read_r1(index, 0xff); break; |
| 43 | case 2: inp = m_read_r2(index, 0xff); break; |
| 44 | case 3: inp = m_read_r3(index, 0xff); break; |
| 45 | case 4: inp = m_read_r4(index, 0xff); break; |
| 46 | case 5: inp = m_read_r5(index, 0xff); break; |
| 47 | case 6: inp = m_read_r6(index, 0xff); break; |
| 48 | case 7: inp = m_read_r7(index, 0xff); break; |
| 49 | } |
| 50 | |
| 51 | if (m_is_cmos) |
| 52 | return inp & m_r[index]; |
| 53 | else |
| 54 | return inp | m_r[index]; |
| 34 | 55 | } |
| 35 | 56 | |
| 57 | void hmcs40_cpu_device::write_r(int index, UINT8 data) |
| 58 | { |
| 59 | index &= 7; |
| 60 | m_r[index] = data & 0xf; |
| 61 | |
| 62 | switch (index) |
| 63 | { |
| 64 | case 0: m_write_r0(index, m_r[index], 0xff); break; |
| 65 | case 1: m_write_r1(index, m_r[index], 0xff); break; |
| 66 | case 2: m_write_r2(index, m_r[index], 0xff); break; |
| 67 | case 3: m_write_r3(index, m_r[index], 0xff); break; |
| 68 | case 4: m_write_r4(index, m_r[index], 0xff); break; |
| 69 | case 5: m_write_r5(index, m_r[index], 0xff); break; |
| 70 | case 6: m_write_r6(index, m_r[index], 0xff); break; |
| 71 | case 7: m_write_r7(index, m_r[index], 0xff); break; |
| 72 | } |
| 73 | } |
| 36 | 74 | |
| 75 | int hmcs40_cpu_device::read_d(int index) |
| 76 | { |
| 77 | index &= 15; |
| 78 | |
| 79 | if (m_is_cmos) |
| 80 | return (m_read_d(index, 0xffff) & m_d) >> index & 1; |
| 81 | else |
| 82 | return (m_read_d(index, 0xffff) | m_d) >> index & 1; |
| 83 | } |
| 37 | 84 | |
| 85 | void hmcs40_cpu_device::write_d(int index, int state) |
| 86 | { |
| 87 | index &= 15; |
| 88 | |
| 89 | m_d = (m_d & ~(1 << index)) | (state << index); |
| 90 | m_write_d(index, m_d, 0xffff); |
| 91 | } |
| 92 | |
| 93 | // HMCS43: |
| 94 | // R0 is input-only, R1 is i/o, R2,R3 are output-only, no R4-R7 |
| 95 | // D0-D3 are i/o, D4-D15 are output-only |
| 96 | |
| 97 | UINT8 hmcs43_cpu_device::read_r(int index) |
| 98 | { |
| 99 | if ((index & 7) >= 4) |
| 100 | logerror("%s read from unknown port R%d at $%04X\n", tag(), index & 7, m_prev_pc << 1); |
| 101 | |
| 102 | return hmcs40_cpu_device::read_r(index); |
| 103 | } |
| 104 | |
| 105 | void hmcs43_cpu_device::write_r(int index, UINT8 data) |
| 106 | { |
| 107 | index &= 7; |
| 108 | |
| 109 | if (index != 0 && index < 4) |
| 110 | hmcs40_cpu_device::write_r(index, data); |
| 111 | else |
| 112 | logerror("%s ineffective write to port R%d = $%X at $%04X\n", tag(), index, data & 0xf, m_prev_pc << 1); |
| 113 | } |
| 114 | |
| 115 | int hmcs43_cpu_device::read_d(int index) |
| 116 | { |
| 117 | if ((index & 15) >= 4) |
| 118 | return m_d >> index & 1; |
| 119 | else |
| 120 | return hmcs40_cpu_device::read_d(index); |
| 121 | } |
| 122 | |
| 123 | // HMCS44: |
| 124 | // R0-R3 are i/o, R4,R5 are extra registers, no R6,R7 |
| 125 | // D0-D15 are i/o |
| 126 | |
| 127 | UINT8 hmcs44_cpu_device::read_r(int index) |
| 128 | { |
| 129 | if ((index & 7) >= 6) |
| 130 | logerror("%s read from unknown port R%d at $%04X\n", tag(), index & 7, m_prev_pc << 1); |
| 131 | |
| 132 | return hmcs40_cpu_device::read_r(index); |
| 133 | } |
| 134 | |
| 135 | void hmcs44_cpu_device::write_r(int index, UINT8 data) |
| 136 | { |
| 137 | index &= 7; |
| 138 | |
| 139 | if (index < 6) |
| 140 | hmcs40_cpu_device::write_r(index, data); |
| 141 | else |
| 142 | logerror("%s ineffective write to port R%d = $%X at $%04X\n", tag(), index, data & 0xf, m_prev_pc << 1); |
| 143 | } |
| 144 | |
| 145 | // HMCS45: |
| 146 | // R0-R5 are i/o, R6 is output-only, no R7 |
| 147 | // D0-D15 are i/o |
| 148 | |
| 149 | UINT8 hmcs45_cpu_device::read_r(int index) |
| 150 | { |
| 151 | if ((index & 7) == 7) |
| 152 | logerror("%s read from unknown port R%d at $%04X\n", tag(), index & 7, m_prev_pc << 1); |
| 153 | |
| 154 | return hmcs40_cpu_device::read_r(index); |
| 155 | } |
| 156 | |
| 157 | void hmcs45_cpu_device::write_r(int index, UINT8 data) |
| 158 | { |
| 159 | index &= 7; |
| 160 | |
| 161 | if (index != 7) |
| 162 | hmcs40_cpu_device::write_r(index, data); |
| 163 | else |
| 164 | logerror("%s ineffective write to port R%d = $%X at $%04X\n", tag(), index, data & 0xf, m_prev_pc << 1); |
| 165 | } |
| 166 | |
| 167 | |
| 168 | |
| 169 | |
| 170 | |
| 38 | 171 | // instruction set |
| 39 | 172 | |
| 40 | 173 | // Register-to-Register Instruction |
| r244799 | r244800 | |
| 461 | 594 | void hmcs40_cpu_device::op_tbr() |
| 462 | 595 | { |
| 463 | 596 | // TBR p: Table Branch |
| 464 | | m_pc = (m_a | m_b << 4 | m_c << 8 | ((m_op & 7) << 9)) & m_prgmask; |
| 597 | m_pc = (m_a | m_b << 4 | m_c << 8 | (m_op & 7) << 9) & m_prgmask; |
| 465 | 598 | } |
| 466 | 599 | |
| 467 | 600 | void hmcs40_cpu_device::op_rtn() |
| r244799 | r244800 | |
| 593 | 726 | void hmcs40_cpu_device::op_sed() |
| 594 | 727 | { |
| 595 | 728 | // SED: Set Discrete I/O Latch |
| 596 | | op_illegal(); |
| 729 | write_d(m_y, 1); |
| 597 | 730 | } |
| 598 | 731 | |
| 599 | 732 | void hmcs40_cpu_device::op_red() |
| 600 | 733 | { |
| 601 | 734 | // RED: Reset Discrete I/O Latch |
| 602 | | op_illegal(); |
| 735 | write_d(m_y, 0); |
| 603 | 736 | } |
| 604 | 737 | |
| 605 | 738 | void hmcs40_cpu_device::op_td() |
| 606 | 739 | { |
| 607 | 740 | // TD: Test Discrete I/O Latch |
| 608 | | op_illegal(); |
| 741 | m_s = read_d(m_y); |
| 609 | 742 | } |
| 610 | 743 | |
| 611 | 744 | void hmcs40_cpu_device::op_sedd() |
| 612 | 745 | { |
| 613 | 746 | // SEDD n: Set Discrete I/O Latch Direct |
| 614 | | op_illegal(); |
| 747 | write_d(m_op & 0xf, 1); |
| 615 | 748 | } |
| 616 | 749 | |
| 617 | 750 | void hmcs40_cpu_device::op_redd() |
| 618 | 751 | { |
| 619 | 752 | // REDD n: Reset Discrete I/O Latch Direct |
| 620 | | op_illegal(); |
| 753 | write_d(m_op & 0xf, 0); |
| 621 | 754 | } |
| 622 | 755 | |
| 623 | 756 | void hmcs40_cpu_device::op_lar() |
| 624 | 757 | { |
| 625 | 758 | // LAR p: Load A from R-Port Register |
| 626 | | op_illegal(); |
| 759 | m_a = read_r(m_op & 7); |
| 627 | 760 | } |
| 628 | 761 | |
| 629 | 762 | void hmcs40_cpu_device::op_lbr() |
| 630 | 763 | { |
| 631 | 764 | // LBR p: Load B from R-Port Register |
| 632 | | op_illegal(); |
| 765 | m_b = read_r(m_op & 7); |
| 633 | 766 | } |
| 634 | 767 | |
| 635 | 768 | void hmcs40_cpu_device::op_lra() |
| 636 | 769 | { |
| 637 | 770 | // LRA p: Load R-Port Register from A |
| 638 | | op_illegal(); |
| 771 | write_r(m_op & 7, m_a); |
| 639 | 772 | } |
| 640 | 773 | |
| 641 | 774 | void hmcs40_cpu_device::op_lrb() |
| 642 | 775 | { |
| 643 | 776 | // LRB p: Load R-Port Register from B |
| 644 | | op_illegal(); |
| 777 | write_r(m_op & 7, m_b); |
| 645 | 778 | } |
| 646 | 779 | |
| 647 | 780 | void hmcs40_cpu_device::op_p() |
| 648 | 781 | { |
| 649 | 782 | // P p: Pattern Generation |
| 650 | | op_illegal(); |
| 783 | m_icount--; |
| 784 | UINT16 address = (m_a | m_b << 4 | m_c << 8 | (m_op & 7) << 9) | (m_pc & ~0x3f); |
| 785 | UINT16 o = m_program->read_word(address << 1); |
| 786 | |
| 787 | // destination is determined by the 2 highest bits |
| 788 | if (o & 0x100) |
| 789 | { |
| 790 | m_a = o & 0xf; |
| 791 | m_b = o >> 4 & 0xf; |
| 792 | } |
| 793 | if (o & 0x200) |
| 794 | { |
| 795 | write_r(2, o >> 4 & 0xf); |
| 796 | write_r(3, o & 0xf); |
| 797 | } |
| 651 | 798 | } |
| 652 | 799 | |
| 653 | 800 | |
| r244799 | r244800 | |
| 657 | 804 | { |
| 658 | 805 | // NOP: No Operation |
| 659 | 806 | } |
| 807 | |
| 808 | |
| 809 | void hmcs40_cpu_device::op_illegal() |
| 810 | { |
| 811 | logerror("%s unknown opcode $%03X at $%04X\n", tag(), m_op, m_prev_pc << 1); |
| 812 | } |