trunk/src/emu/cpu/ucom4/ucom4.c
| r243438 | r243439 | |
| 4 | 4 | |
| 5 | 5 | NEC uCOM-4 MCU family cores |
| 6 | 6 | |
| 7 | | reference: 1981 NEC Microcomputers Catalog (later editions may have errors!) |
| 8 | | also looked at asterick's JavaScript D553 emulator for verification, with permission |
| 7 | References: |
| 8 | - 1981 NEC Microcomputers Catalog (later editions may have errors!) |
| 9 | - Supplement to uCOM-43 Single Chip Microcomputer Users' Manual |
| 10 | I've also looked at asterick's JavaScript D553 emulator for verification, with permission. |
| 9 | 11 | |
| 10 | 12 | TODO: |
| 11 | 13 | - what happens with uCOM-43 opcodes on an uCOM-44/45 MCU? |
| r243438 | r243439 | |
| 52 | 54 | |
| 53 | 55 | static ADDRESS_MAP_START(data_96x4, AS_DATA, 8, ucom4_cpu_device) |
| 54 | 56 | AM_RANGE(0x00, 0x3f) AM_RAM |
| 55 | | AM_RANGE(0x40, 0x5f) AM_RAM AM_MIRROR(0x20) |
| 57 | AM_RANGE(0x40, 0x4f) AM_RAM |
| 58 | AM_RANGE(0x70, 0x7f) AM_RAM |
| 56 | 59 | ADDRESS_MAP_END |
| 57 | 60 | |
| 58 | 61 | |
| r243438 | r243439 | |
| 199 | 202 | // execute |
| 200 | 203 | //------------------------------------------------- |
| 201 | 204 | |
| 205 | void ucom4_cpu_device::increment_pc() |
| 206 | { |
| 207 | // upper bits (field register) don't auto-increment |
| 208 | m_pc = (m_pc & ~0xff) | ((m_pc + 1) & 0xff); |
| 209 | } |
| 210 | |
| 202 | 211 | void ucom4_cpu_device::fetch_arg() |
| 203 | 212 | { |
| 204 | 213 | // 2-byte opcodes: STM/LDI/CLI/CI, JMP/CAL, OCD |
| r243438 | r243439 | |
| 206 | 215 | { |
| 207 | 216 | m_icount--; |
| 208 | 217 | m_arg = m_program->read_byte(m_pc); |
| 209 | | m_pc = (m_pc + 1) & m_prgmask; |
| 218 | increment_pc(); |
| 210 | 219 | } |
| 211 | 220 | } |
| 212 | 221 | |
| r243438 | r243439 | |
| 222 | 231 | debugger_instruction_hook(this, m_pc); |
| 223 | 232 | m_op = m_program->read_byte(m_pc); |
| 224 | 233 | m_bitmask = 1 << (m_op & 0x03); |
| 225 | | m_pc = (m_pc + 1) & m_prgmask; |
| 234 | increment_pc(); |
| 226 | 235 | fetch_arg(); |
| 227 | 236 | |
| 228 | 237 | if (m_skip) |
trunk/src/emu/cpu/ucom4/ucom4.h
| r243438 | r243439 | |
| 110 | 110 | virtual UINT32 execute_input_lines() const { return 1; } |
| 111 | 111 | virtual void execute_run(); |
| 112 | 112 | |
| 113 | | void fetch_arg(); |
| 114 | | |
| 115 | 113 | // device_memory_interface overrides |
| 116 | 114 | 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); } |
| 117 | 115 | |
| r243438 | r243439 | |
| 167 | 165 | devcb_write8 m_write_h; |
| 168 | 166 | devcb_write8 m_write_i; |
| 169 | 167 | |
| 170 | | // opcode handlers |
| 168 | // misc internal helpers |
| 169 | void increment_pc(); |
| 170 | void fetch_arg(); |
| 171 | |
| 171 | 172 | UINT8 ram_r(); |
| 172 | 173 | void ram_w(UINT8 data); |
| 173 | 174 | void pop_stack(); |
| 174 | 175 | void push_stack(); |
| 175 | 176 | UINT8 input_r(int index); |
| 176 | 177 | void output_w(int index, UINT8 data); |
| 177 | | void op_illegal(); |
| 178 | |
| 178 | 179 | bool check_op_43(); |
| 180 | UINT8 ucom43_reg_r(int index); |
| 181 | void ucom43_reg_w(int index, UINT8 data); |
| 179 | 182 | |
| 183 | // opcode handlers |
| 184 | void op_illegal(); |
| 185 | |
| 180 | 186 | void op_li(); |
| 181 | 187 | void op_lm(); |
| 182 | 188 | void op_ldi(); |
trunk/src/emu/cpu/ucom4/ucom4op.inc
| r243438 | r243439 | |
| 326 | 326 | // JMP A: Jump to Address / CAL A: Call Address |
| 327 | 327 | if (m_op & 0x08) |
| 328 | 328 | push_stack(); |
| 329 | | m_pc = (m_op & 0x07) << 8 | m_arg; |
| 329 | m_pc = ((m_op & 0x07) << 8 | m_arg) & m_prgmask; |
| 330 | 330 | } |
| 331 | 331 | |
| 332 | 332 | void ucom4_cpu_device::op_jcp() |
| r243438 | r243439 | |
| 338 | 338 | void ucom4_cpu_device::op_jpa() |
| 339 | 339 | { |
| 340 | 340 | // JPA: Jump to (ACC) in current page |
| 341 | m_icount--; |
| 341 | 342 | m_pc = (m_pc & ~0x3f) | (m_acc << 2); |
| 342 | 343 | } |
| 343 | 344 | |
| r243438 | r243439 | |
| 358 | 359 | void ucom4_cpu_device::op_rts() |
| 359 | 360 | { |
| 360 | 361 | // RTS: Return from subroutine, skip next |
| 361 | | pop_stack(); |
| 362 | op_rt(); |
| 362 | 363 | m_skip = true; |
| 363 | 364 | } |
| 364 | 365 | |
| r243438 | r243439 | |
| 434 | 435 | void ucom4_cpu_device::op_ia() |
| 435 | 436 | { |
| 436 | 437 | // IA: Input port A to ACC |
| 438 | m_icount--; |
| 437 | 439 | m_acc = input_r(NEC_UCOM4_PORTA); |
| 438 | 440 | } |
| 439 | 441 | |
| r243438 | r243439 | |
| 446 | 448 | void ucom4_cpu_device::op_oe() |
| 447 | 449 | { |
| 448 | 450 | // OE: Output ACC to port E |
| 451 | m_icount--; |
| 449 | 452 | output_w(NEC_UCOM4_PORTE, m_acc); |
| 450 | 453 | } |
| 451 | 454 | |
| r243438 | r243439 | |
| 483 | 486 | return (m_family == NEC_UCOM43); |
| 484 | 487 | } |
| 485 | 488 | |
| 489 | // extra registers reside in RAM |
| 490 | enum |
| 491 | { |
| 492 | UCOM43_X = 0, |
| 493 | UCOM43_Y, |
| 494 | UCOM43_R, |
| 495 | UCOM43_S, |
| 496 | UCOM43_W, |
| 497 | UCOM43_Z, |
| 498 | UCOM43_F |
| 499 | }; |
| 500 | |
| 501 | inline UINT8 ucom4_cpu_device::ucom43_reg_r(int index) |
| 502 | { |
| 503 | return m_data->read_byte(m_datamask - index) & 0xf; |
| 504 | } |
| 505 | |
| 506 | inline void ucom4_cpu_device::ucom43_reg_w(int index, UINT8 data) |
| 507 | { |
| 508 | m_data->write_byte(m_datamask - index, data & 0xf); |
| 509 | } |
| 510 | |
| 511 | |
| 486 | 512 | // Transfer |
| 487 | 513 | |
| 488 | 514 | void ucom4_cpu_device::op_taw() |