trunk/src/emu/cpu/amis2000/amis2000.c
| r0 | r243243 | |
| 1 | // license:BSD-3-Clause |
| 2 | // copyright-holders:hap |
| 3 | /* |
| 4 | |
| 5 | American Microsystems, Inc.(AMI) S2000-family 4-bit MCU cores, introduced late 1970s |
| 6 | |
| 7 | TODO: |
| 8 | - x |
| 9 | - add S2200/S2400 |
| 10 | |
| 11 | */ |
| 12 | |
| 13 | #include "amis2000.h" |
| 14 | #include "debugger.h" |
| 15 | |
| 16 | |
| 17 | // S2000 is the most basic one, 64 nibbles internal RAM and 1KB internal ROM |
| 18 | // S2150 increased RAM to 80 nibbles and ROM to 1.5KB |
| 19 | // high-voltage output versions of these chips (S2000C and S2150C) are identical overall |
| 20 | const device_type AMI_S2000 = &device_creator<amis2000_device>; |
| 21 | const device_type AMI_S2150 = &device_creator<amis2150_device>; |
| 22 | |
| 23 | |
| 24 | // internal memory maps |
| 25 | static ADDRESS_MAP_START(program_1k, AS_PROGRAM, 8, amis2000_device) |
| 26 | AM_RANGE(0x000, 0x3ff) AM_ROM |
| 27 | ADDRESS_MAP_END |
| 28 | |
| 29 | static ADDRESS_MAP_START(program_1_5k, AS_PROGRAM, 8, amis2000_device) |
| 30 | AM_RANGE(0x000, 0x3ff) AM_ROM |
| 31 | AM_RANGE(0x400, 0x5ff) AM_ROM |
| 32 | ADDRESS_MAP_END |
| 33 | |
| 34 | |
| 35 | static ADDRESS_MAP_START(data_64x4, AS_DATA, 8, amis2000_device) |
| 36 | AM_RANGE(0x00, 0x3f) AM_RAM |
| 37 | ADDRESS_MAP_END |
| 38 | |
| 39 | static ADDRESS_MAP_START(data_80x4, AS_DATA, 8, amis2000_device) |
| 40 | AM_RANGE(0x00, 0x3f) AM_RAM |
| 41 | AM_RANGE(0x40, 0x4f) AM_RAM |
| 42 | ADDRESS_MAP_END |
| 43 | |
| 44 | |
| 45 | // device definitions |
| 46 | amis2000_device::amis2000_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 47 | : cpu_device(mconfig, AMI_S2000, "AMI S2000", tag, owner, clock, "amis2000", __FILE__), |
| 48 | m_program_config("program", ENDIANNESS_BIG, 8, 13, 0, ADDRESS_MAP_NAME(program_1k)), |
| 49 | m_data_config("data", ENDIANNESS_BIG, 8, 6, 0, ADDRESS_MAP_NAME(data_64x4)), |
| 50 | m_bu_bits(2), |
| 51 | m_stack_bits(10), |
| 52 | m_read_k(*this), |
| 53 | m_read_i(*this), |
| 54 | m_read_d(*this), |
| 55 | m_write_d(*this), |
| 56 | m_write_a(*this) |
| 57 | { |
| 58 | } |
| 59 | |
| 60 | amis2000_device::amis2000_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT8 bu_bits, UINT8 stack_bits, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source) |
| 61 | : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source), |
| 62 | m_program_config("program", ENDIANNESS_BIG, 8, prgwidth, 0, program), |
| 63 | m_data_config("data", ENDIANNESS_BIG, 8, datawidth, 0, data), |
| 64 | m_bu_bits(bu_bits), |
| 65 | m_stack_bits(stack_bits), |
| 66 | m_read_k(*this), |
| 67 | m_read_i(*this), |
| 68 | m_read_d(*this), |
| 69 | m_write_d(*this), |
| 70 | m_write_a(*this) |
| 71 | { |
| 72 | } |
| 73 | |
| 74 | amis2150_device::amis2150_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 75 | : amis2000_device(mconfig, AMI_S2150, "AMI S2150", tag, owner, clock, 3, 11, 13, ADDRESS_MAP_NAME(program_1_5k), 7, ADDRESS_MAP_NAME(data_80x4), "amis2150", __FILE__) |
| 76 | { |
| 77 | } |
| 78 | |
| 79 | |
| 80 | // disasm |
| 81 | void amis2000_device::state_string_export(const device_state_entry &entry, astring &string) |
| 82 | { |
| 83 | switch (entry.index()) |
| 84 | { |
| 85 | case STATE_GENFLAGS: |
| 86 | string.printf("%c%c%c%c%c%c", |
| 87 | m_f & 0x20 ? '6':'.', |
| 88 | m_f & 0x10 ? '5':'.', |
| 89 | m_f & 0x08 ? '4':'.', |
| 90 | m_f & 0x04 ? '3':'.', |
| 91 | m_f & 0x02 ? '2':'.', |
| 92 | m_f & 0x01 ? '1':'.' |
| 93 | ); |
| 94 | break; |
| 95 | |
| 96 | default: break; |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | offs_t amis2000_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 101 | { |
| 102 | extern CPU_DISASSEMBLE(amis2000); |
| 103 | return CPU_DISASSEMBLE_NAME(amis2000)(this, buffer, pc, oprom, opram, options); |
| 104 | } |
| 105 | |
| 106 | |
| 107 | |
| 108 | //------------------------------------------------- |
| 109 | // device_start - device-specific startup |
| 110 | //------------------------------------------------- |
| 111 | |
| 112 | enum |
| 113 | { |
| 114 | S2000_PC=1, S2000_BL, S2000_BU, |
| 115 | S2000_A, S2000_E |
| 116 | }; |
| 117 | |
| 118 | void amis2000_device::device_start() |
| 119 | { |
| 120 | m_program = &space(AS_PROGRAM); |
| 121 | m_data = &space(AS_DATA); |
| 122 | |
| 123 | m_read_k.resolve_safe(0); |
| 124 | m_read_i.resolve_safe(0); |
| 125 | m_read_d.resolve_safe(0); |
| 126 | m_write_d.resolve_safe(); |
| 127 | m_write_a.resolve_safe(); |
| 128 | |
| 129 | m_bu_mask = (1 << m_bu_bits) - 1; |
| 130 | m_stack_mask = (1 << m_stack_bits) - 1; |
| 131 | |
| 132 | // zerofill |
| 133 | m_stack[0] = m_stack[1] = m_stack[2] = 0; |
| 134 | m_pc = 0; |
| 135 | m_op = 0; |
| 136 | m_f = 0; |
| 137 | m_bl = 0; |
| 138 | m_bu = 0; |
| 139 | m_a = 0; |
| 140 | m_e = 0; |
| 141 | |
| 142 | // register for savestates |
| 143 | save_item(NAME(m_stack)); |
| 144 | save_item(NAME(m_pc)); |
| 145 | save_item(NAME(m_op)); |
| 146 | save_item(NAME(m_f)); |
| 147 | save_item(NAME(m_bl)); |
| 148 | save_item(NAME(m_bu)); |
| 149 | save_item(NAME(m_a)); |
| 150 | save_item(NAME(m_e)); |
| 151 | |
| 152 | // register state for debugger |
| 153 | state_add(S2000_PC, "PC", m_pc ).formatstr("%04X"); |
| 154 | state_add(S2000_BL, "BL", m_bl ).formatstr("%01X"); |
| 155 | state_add(S2000_BU, "BU", m_bu ).formatstr("%01X"); |
| 156 | state_add(S2000_A, "A", m_a ).formatstr("%01X"); |
| 157 | state_add(S2000_E, "E", m_a ).formatstr("%01X"); |
| 158 | |
| 159 | state_add(STATE_GENPC, "curpc", m_pc).formatstr("%04X").noshow(); |
| 160 | state_add(STATE_GENFLAGS, "GENFLAGS", m_f).formatstr("%6s").noshow(); |
| 161 | |
| 162 | m_icountptr = &m_icount; |
| 163 | } |
| 164 | |
| 165 | |
| 166 | |
| 167 | //------------------------------------------------- |
| 168 | // device_reset - device-specific reset |
| 169 | //------------------------------------------------- |
| 170 | |
| 171 | void amis2000_device::device_reset() |
| 172 | { |
| 173 | m_pc = 0; |
| 174 | } |
| 175 | |
| 176 | |
| 177 | |
| 178 | //------------------------------------------------- |
| 179 | // execute |
| 180 | //------------------------------------------------- |
| 181 | |
| 182 | #include "amis2000op.inc" |
| 183 | |
| 184 | void amis2000_device::execute_run() |
| 185 | { |
| 186 | do |
| 187 | { |
| 188 | m_icount--; |
| 189 | |
| 190 | debugger_instruction_hook(this, m_pc); |
| 191 | m_op = m_program->read_byte(m_pc); |
| 192 | m_pc = (m_pc + 1) & 0x1fff; |
| 193 | |
| 194 | switch (m_op) |
| 195 | { |
| 196 | default: break; |
| 197 | } |
| 198 | |
| 199 | } while (m_icount > 0); |
| 200 | } |
trunk/src/emu/cpu/amis2000/amis2000.h
| r0 | r243243 | |
| 1 | // license:BSD-3-Clause |
| 2 | // copyright-holders:hap |
| 3 | /* |
| 4 | |
| 5 | AMI S2000-family MCU cores |
| 6 | |
| 7 | */ |
| 8 | |
| 9 | #ifndef _AMIS2000_H_ |
| 10 | #define _AMIS2000_H_ |
| 11 | |
| 12 | #include "emu.h" |
| 13 | |
| 14 | |
| 15 | // generic input pins (4 bits each) |
| 16 | #define MCFG_AMI_S2000_READ_K_CB(_devcb) \ |
| 17 | amis2000_device::set_read_k_callback(*device, DEVCB_##_devcb); |
| 18 | |
| 19 | #define MCFG_AMI_S2000_READ_I_CB(_devcb) \ |
| 20 | amis2000_device::set_read_i_callback(*device, DEVCB_##_devcb); |
| 21 | |
| 22 | // 8-bit external databus coupled as input/output pins |
| 23 | #define MCFG_AMI_S2000_READ_D_CB(_devcb) \ |
| 24 | amis2000_device::set_read_d_callback(*device, DEVCB_##_devcb); |
| 25 | |
| 26 | #define MCFG_AMI_S2000_WRITE_D_CB(_devcb) \ |
| 27 | amis2000_device::set_write_d_callback(*device, DEVCB_##_devcb); |
| 28 | |
| 29 | // 13-bit external addressbus coupled as output pins |
| 30 | #define MCFG_AMI_S2000_WRITE_A_CB(_devcb) \ |
| 31 | amis2000_device::set_write_a_callback(*device, DEVCB_##_devcb); |
| 32 | |
| 33 | |
| 34 | class amis2000_device : public cpu_device |
| 35 | { |
| 36 | public: |
| 37 | // construction/destruction |
| 38 | amis2000_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 39 | amis2000_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT8 bu_bits, UINT8 stack_bits, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source); |
| 40 | |
| 41 | // static configuration helpers |
| 42 | template<class _Object> static devcb_base &set_read_k_callback(device_t &device, _Object object) { return downcast<amis2000_device &>(device).m_read_k.set_callback(object); } |
| 43 | template<class _Object> static devcb_base &set_read_i_callback(device_t &device, _Object object) { return downcast<amis2000_device &>(device).m_read_i.set_callback(object); } |
| 44 | template<class _Object> static devcb_base &set_read_d_callback(device_t &device, _Object object) { return downcast<amis2000_device &>(device).m_read_d.set_callback(object); } |
| 45 | template<class _Object> static devcb_base &set_write_d_callback(device_t &device, _Object object) { return downcast<amis2000_device &>(device).m_write_d.set_callback(object); } |
| 46 | template<class _Object> static devcb_base &set_write_a_callback(device_t &device, _Object object) { return downcast<amis2000_device &>(device).m_write_a.set_callback(object); } |
| 47 | |
| 48 | protected: |
| 49 | // device-level overrides |
| 50 | virtual void device_start(); |
| 51 | virtual void device_reset(); |
| 52 | |
| 53 | // device_execute_interface overrides |
| 54 | virtual UINT32 execute_min_cycles() const { return 1; } |
| 55 | virtual UINT32 execute_max_cycles() const { return 2; } |
| 56 | virtual UINT32 execute_input_lines() const { return 1; } |
| 57 | virtual void execute_run(); |
| 58 | |
| 59 | // device_memory_interface overrides |
| 60 | 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); } |
| 61 | |
| 62 | // device_disasm_interface overrides |
| 63 | virtual UINT32 disasm_min_opcode_bytes() const { return 1; } |
| 64 | virtual UINT32 disasm_max_opcode_bytes() const { return 1; } |
| 65 | virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); |
| 66 | void state_string_export(const device_state_entry &entry, astring &string); |
| 67 | |
| 68 | address_space_config m_program_config; |
| 69 | address_space_config m_data_config; |
| 70 | address_space *m_program; |
| 71 | address_space *m_data; |
| 72 | |
| 73 | UINT8 m_bu_bits; |
| 74 | UINT16 m_bu_mask; |
| 75 | UINT8 m_stack_bits; |
| 76 | UINT16 m_stack_mask; |
| 77 | UINT16 m_stack[3]; |
| 78 | |
| 79 | UINT16 m_pc; |
| 80 | UINT8 m_op; |
| 81 | UINT8 m_f; |
| 82 | UINT8 m_bl; |
| 83 | UINT8 m_bu; |
| 84 | UINT8 m_a; |
| 85 | UINT8 m_e; |
| 86 | |
| 87 | devcb_read8 m_read_k; |
| 88 | devcb_read8 m_read_i; |
| 89 | devcb_read8 m_read_d; |
| 90 | devcb_write8 m_write_d; |
| 91 | devcb_write16 m_write_a; |
| 92 | |
| 93 | int m_icount; |
| 94 | }; |
| 95 | |
| 96 | |
| 97 | class amis2150_device : public amis2000_device |
| 98 | { |
| 99 | public: |
| 100 | amis2150_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 101 | }; |
| 102 | |
| 103 | |
| 104 | |
| 105 | extern const device_type AMI_S2000; |
| 106 | extern const device_type AMI_S2150; |
| 107 | |
| 108 | |
| 109 | #endif /* _AMIS2000_H_ */ |
trunk/src/emu/cpu/amis2000/amis2000d.c
| r0 | r243243 | |
| 1 | // license:BSD-3-Clause |
| 2 | // copyright-holders:hap |
| 3 | /* |
| 4 | |
| 5 | AMI S2000-family disassembler |
| 6 | |
| 7 | */ |
| 8 | |
| 9 | #include "emu.h" |
| 10 | #include "debugger.h" |
| 11 | #include "amis2000.h" |
| 12 | |
| 13 | |
| 14 | enum e_mnemonics |
| 15 | { |
| 16 | mLAB = 0, mLAE, mLAI, mLBE, mLBEP, mLBF, mLBZ, mXAB, mXABU, mXAE, |
| 17 | mLAM, mXC, mXCI, mXCD, mSTM, mRSM, |
| 18 | mADD, mADCS, mADIS, mAND, mXOR, mCMA, mSTC, mRSC, mSF1, mRF1, mSF2, mRF2, |
| 19 | mSAM, mSZM, mSBE, mSZC, mSOS, mSZK, mSZI, mTF1, mTF2, |
| 20 | mPP, mJMP, mJMS, mRT, mRTS, mNOP, |
| 21 | mINP, mOUT, mDISB, mDISN, mMVS, mPSH, mPSL, mEUR, |
| 22 | mILL |
| 23 | }; |
| 24 | |
| 25 | static const char *const s_mnemonics[] = |
| 26 | { |
| 27 | "LAB", "LAE", "LAI", "LBE", "LBEP", "LBF", "LBZ", "XAB", "XABU", "XAE", |
| 28 | "LAM", "XC", "XCI", "XCD", "STM", "RSM", |
| 29 | "ADD", "ADCS", "ADIS", "AND", "XOR", "CMA", "STC", "RSC", "SF1", "RF1", "SF2", "RF2", |
| 30 | "SAM", "SZM", "SBE", "SZC", "SOS", "SZK", "SZI", "TF1", "TF2", |
| 31 | "PP", "JMP", "JMS", "RT", "RTS", "NOP", |
| 32 | "INP", "OUT", "DISB", "DISN", "MVS", "PSH", "PSL", "EUR", |
| 33 | "?" |
| 34 | }; |
| 35 | |
| 36 | |
| 37 | #define _OVER DASMFLAG_STEP_OVER |
| 38 | #define _OUT DASMFLAG_STEP_OUT |
| 39 | |
| 40 | static const UINT32 s_flags[] = |
| 41 | { |
| 42 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 43 | 0, 0, 0, 0, 0, 0, |
| 44 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 45 | 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 46 | 0, 0, _OVER, _OUT, _OUT, 0, |
| 47 | 0, 0, 0, 0, 0, 0, 0, 0, |
| 48 | 0 |
| 49 | }; |
| 50 | |
| 51 | |
| 52 | static const int s_bits[] = |
| 53 | { |
| 54 | 0, 0, 4, 2, 2, 2, 2, 0, 0, 0, |
| 55 | -2, -2, -2, -2, 2, 2, |
| 56 | 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 57 | 0, 2, 0, 0, 0, 0, 0, 0, 0, |
| 58 | -4, 6, 6, 0, 0, 0, |
| 59 | 0, 0, 0, 0, 0, 0, 0, 0, |
| 60 | 0 |
| 61 | }; |
| 62 | |
| 63 | |
| 64 | static const UINT8 s2000_mnemonic[0x100] = |
| 65 | { |
| 66 | /* 0x00 */ |
| 67 | mNOP, mILL, mRT, mRTS, mPSH, mPSL, mAND, mSOS, |
| 68 | mSBE, mSZC, mSTC, mRSC, mLAE, mXAE, mINP, mEUR, |
| 69 | /* 0x10 */ |
| 70 | mCMA, mXABU, mLAB, mXAB, mADCS, mXOR, mADD, mSAM, |
| 71 | mDISB, mMVS, mOUT, mDISN, mSZM, mSZM, mSZM, mSZM, |
| 72 | /* 0x20 */ |
| 73 | mSTM, mSTM, mSTM, mSTM, mRSM, mRSM, mRSM, mRSM, |
| 74 | mSZK, mSZI, mRF1, mSF1, mRF2, mSF2, mTF1, mTF2, |
| 75 | mXCI, mXCI, mXCI, mXCI, mXCD, mXCD, mXCD, mXCD, |
| 76 | mXC, mXC, mXC, mXC, mLAM, mLAM, mLAM, mLAM, |
| 77 | /* 0x40 */ |
| 78 | mLBZ, mLBZ, mLBZ, mLBZ, mLBF, mLBF, mLBF, mLBF, |
| 79 | mLBE, mLBE, mLBE, mLBE, mLBEP, mLBEP, mLBEP, mLBEP, |
| 80 | mADIS, mADIS, mADIS, mADIS, mADIS, mADIS, mADIS, mADIS, |
| 81 | mADIS, mADIS, mADIS, mADIS, mADIS, mADIS, mADIS, mADIS, |
| 82 | mPP, mPP, mPP, mPP, mPP, mPP, mPP, mPP, |
| 83 | mPP, mPP, mPP, mPP, mPP, mPP, mPP, mPP, |
| 84 | mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, |
| 85 | mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, |
| 86 | /* 0x80 */ |
| 87 | mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, |
| 88 | mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, |
| 89 | mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, |
| 90 | mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, |
| 91 | mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, |
| 92 | mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, |
| 93 | mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, |
| 94 | mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, mJMS, |
| 95 | /* 0xc0 */ |
| 96 | mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, |
| 97 | mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, |
| 98 | mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, |
| 99 | mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, |
| 100 | mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, |
| 101 | mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, |
| 102 | mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, |
| 103 | mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP |
| 104 | }; |
| 105 | |
| 106 | |
| 107 | |
| 108 | CPU_DISASSEMBLE( amis2000 ) |
| 109 | { |
| 110 | int pos = 0; |
| 111 | UINT8 op = oprom[pos++]; |
| 112 | UINT8 instr = s2000_mnemonic[op]; |
| 113 | |
| 114 | char *dst = buffer; |
| 115 | dst += sprintf(dst, "%-5s ", s_mnemonics[instr]); |
| 116 | |
| 117 | // opcode parameter |
| 118 | int mask = s_bits[instr]; |
| 119 | bool complement = (mask < 0); |
| 120 | if (mask < 0) |
| 121 | mask = -mask; |
| 122 | mask = (1 << mask) - 1; |
| 123 | |
| 124 | if (mask != 0) |
| 125 | { |
| 126 | UINT8 param = op; |
| 127 | if (complement) |
| 128 | param = ~param; |
| 129 | param &= mask; |
| 130 | |
| 131 | if (mask < 0x10) |
| 132 | dst += sprintf(dst, "%d", param); |
| 133 | else |
| 134 | dst += sprintf(dst, "$%02X", param); |
| 135 | } |
| 136 | |
| 137 | return pos | s_flags[instr] | DASMFLAG_SUPPORTED; |
| 138 | } |