trunk/src/emu/cpu/amis2000/amis2000.c
| r243301 | r243302 | |
| 5 | 5 | American Microsystems, Inc.(AMI) S2000-family 4-bit MCU cores, introduced late 1970s |
| 6 | 6 | |
| 7 | 7 | TODO: |
| 8 | | - bug(s)? - MESS wildfire.c doesn't work yet |
| 9 | 8 | - unemulated opcodes (need more testing material) |
| 10 | 9 | - support external program map |
| 10 | - STATUS pin(wildfire.c sound?) |
| 11 | 11 | - add 50/60hz timer |
| 12 | 12 | - add S2200/S2400 |
| 13 | 13 | |
| r243301 | r243302 | |
| 16 | 16 | #include "amis2000.h" |
| 17 | 17 | #include "debugger.h" |
| 18 | 18 | |
| 19 | #include "amis2000op.inc" |
| 19 | 20 | |
| 21 | |
| 20 | 22 | // S2000 is the most basic one, 64 nibbles internal RAM and 1KB internal ROM |
| 21 | 23 | // S2150 increased RAM to 80 nibbles and ROM to 1.5KB |
| 22 | 24 | // high-voltage output versions of these chips (S2000A and S2150A) are identical overall |
| r243301 | r243302 | |
| 31 | 33 | |
| 32 | 34 | static ADDRESS_MAP_START(program_1_5k, AS_PROGRAM, 8, amis2000_device) |
| 33 | 35 | AM_RANGE(0x0000, 0x03ff) AM_ROM |
| 34 | | AM_RANGE(0x0400, 0x05ff) AM_ROM AM_MIRROR(0x200) |
| 36 | AM_RANGE(0x0400, 0x05ff) AM_NOP |
| 37 | AM_RANGE(0x0600, 0x07ff) AM_ROM |
| 35 | 38 | ADDRESS_MAP_END |
| 36 | 39 | |
| 37 | 40 | |
| r243301 | r243302 | |
| 151 | 154 | m_i = 0; |
| 152 | 155 | m_k = 0; |
| 153 | 156 | m_d = 0; |
| 157 | m_d_active = false; |
| 158 | m_d_polarity = 0; |
| 154 | 159 | m_a = 0; |
| 155 | 160 | |
| 156 | 161 | // register for savestates |
| r243301 | r243302 | |
| 170 | 175 | save_item(NAME(m_i)); |
| 171 | 176 | save_item(NAME(m_k)); |
| 172 | 177 | save_item(NAME(m_d)); |
| 178 | save_item(NAME(m_d_active)); |
| 179 | save_item(NAME(m_d_polarity)); |
| 173 | 180 | save_item(NAME(m_a)); |
| 174 | 181 | |
| 175 | 182 | // register state for debugger |
| r243301 | r243302 | |
| 199 | 206 | m_op = 0; |
| 200 | 207 | |
| 201 | 208 | // clear i/o |
| 209 | m_d_polarity = 0; |
| 210 | m_d = 0; d_latch_out(false); |
| 211 | m_a = 0; m_write_a(0, 0, 0xffff); |
| 202 | 212 | m_i = 0; |
| 203 | 213 | m_k = 0; |
| 204 | | m_d = 0; m_write_d(0, 0, 0xff); |
| 205 | | m_a = 0; m_write_a(0, 0, 0xffff); |
| 206 | 214 | } |
| 207 | 215 | |
| 208 | 216 | |
| r243301 | r243302 | |
| 211 | 219 | // execute |
| 212 | 220 | //------------------------------------------------- |
| 213 | 221 | |
| 214 | | #include "amis2000op.inc" |
| 215 | | |
| 216 | 222 | void amis2000_device::execute_run() |
| 217 | 223 | { |
| 218 | 224 | while (m_icount > 0) |
| r243301 | r243302 | |
| 246 | 252 | switch (m_op) |
| 247 | 253 | { |
| 248 | 254 | case 0x00: op_nop(); break; |
| 249 | | case 0x01: op_illegal(); break; // reserved for devkit-use |
| 255 | case 0x01: op_halt(); break; |
| 250 | 256 | case 0x02: op_rt(); break; |
| 251 | 257 | case 0x03: op_rts(); break; |
| 252 | 258 | case 0x04: op_psh(); break; |
trunk/src/emu/cpu/amis2000/amis2000d.c
| r243301 | r243302 | |
| 17 | 17 | mLAM, mXC, mXCI, mXCD, mSTM, mRSM, |
| 18 | 18 | mADD, mADCS, mADIS, mAND, mXOR, mCMA, mSTC, mRSC, mSF1, mRF1, mSF2, mRF2, |
| 19 | 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 |
| 20 | mPP, mJMP, mJMS, mRT, mRTS, mNOP, mHALT, |
| 21 | mINP, mOUT, mDISB, mDISN, mMVS, mPSH, mPSL, mEUR |
| 23 | 22 | }; |
| 24 | 23 | |
| 25 | 24 | static const char *const s_mnemonics[] = |
| r243301 | r243302 | |
| 28 | 27 | "LAM", "XC", "XCI", "XCD", "STM", "RSM", |
| 29 | 28 | "ADD", "ADCS", "ADIS", "AND", "XOR", "CMA", "STC", "RSC", "SF1", "RF1", "SF2", "RF2", |
| 30 | 29 | "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 | | "?" |
| 30 | "PP", "JMP", "JMS", "RT", "RTS", "NOP", "HALT", |
| 31 | "INP", "OUT", "DISB", "DISN", "MVS", "PSH", "PSL", "EUR" |
| 34 | 32 | }; |
| 35 | 33 | |
| 36 | 34 | |
| r243301 | r243302 | |
| 43 | 41 | 0, 0, 0, 0, 0, 0, |
| 44 | 42 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 45 | 43 | 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 |
| 44 | 0, 0, _OVER, _OUT, _OUT, 0, 0, |
| 45 | 0, 0, 0, 0, 0, 0, 0, 0 |
| 49 | 46 | }; |
| 50 | 47 | |
| 51 | 48 | |
| r243301 | r243302 | |
| 55 | 52 | -2, -2, -2, -2, 2, 2, |
| 56 | 53 | 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 57 | 54 | 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 |
| 55 | -4, 6, 6, 0, 0, 0, 0, |
| 56 | 0, 0, 0, 0, 0, 0, 0, 0 |
| 61 | 57 | }; |
| 62 | 58 | |
| 63 | 59 | |
| 64 | 60 | static const UINT8 s2000_mnemonic[0x100] = |
| 65 | 61 | { |
| 66 | 62 | /* 0x00 */ |
| 67 | | mNOP, mILL, mRT, mRTS, mPSH, mPSL, mAND, mSOS, |
| 63 | mNOP, mHALT, mRT, mRTS, mPSH, mPSL, mAND, mSOS, |
| 68 | 64 | mSBE, mSZC, mSTC, mRSC, mLAE, mXAE, mINP, mEUR, |
| 69 | 65 | /* 0x10 */ |
| 70 | 66 | mCMA, mXABU, mLAB, mXAB, mADCS, mXOR, mADD, mSAM, |
trunk/src/emu/cpu/amis2000/amis2000op.inc
| r243301 | r243302 | |
| 33 | 33 | m_callstack[0] = m_pc & m_callstack_mask; |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | | void amis2000_device::op_illegal() |
| 36 | void amis2000_device::d_latch_out(bool active) |
| 37 | 37 | { |
| 38 | | logerror("%s unknown opcode $%02X at $%04X\n", tag(), m_op, m_pc); |
| 38 | m_write_d(0, active ? (m_d ^ m_d_polarity) : 0, 0xff); |
| 39 | m_d_active = active; |
| 39 | 40 | } |
| 40 | 41 | |
| 41 | 42 | |
| r243301 | r243302 | |
| 195 | 196 | void amis2000_device::op_inp() |
| 196 | 197 | { |
| 197 | 198 | // INP: input D-pins to ACC and RAM |
| 198 | | op_illegal(); |
| 199 | UINT8 in = m_d_active ? m_d : m_read_d(0, 0xff); |
| 200 | m_acc = in & 0xf; |
| 201 | ram_w(in >> 4 & 0xf); |
| 199 | 202 | } |
| 200 | 203 | |
| 201 | 204 | void amis2000_device::op_out() |
| 202 | 205 | { |
| 203 | 206 | // OUT: pulse output ACC and RAM to D-pins |
| 204 | | op_illegal(); |
| 207 | logerror("%s unknown opcode $%02X at $%04X\n", tag(), m_op, m_pc); |
| 205 | 208 | } |
| 206 | 209 | |
| 207 | 210 | void amis2000_device::op_disb() |
| 208 | 211 | { |
| 209 | 212 | // DISB: set D-latch to ACC and RAM directly |
| 210 | 213 | m_d = m_acc | ram_r() << 4; |
| 211 | | m_write_d(0, m_d, 0xff); |
| 212 | | // TODO: exit from floating mode on D-pins |
| 214 | d_latch_out(true); |
| 213 | 215 | } |
| 214 | 216 | |
| 215 | 217 | void amis2000_device::op_disn() |
| r243301 | r243302 | |
| 221 | 223 | 0x7e, 0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b, 0x77, 0x1f, 0x4e, 0x3d, 0x4f, 0x47 |
| 222 | 224 | }; |
| 223 | 225 | m_d = lut_segment_decoder[m_acc] | (m_carry ? 0x80 : 0x00); |
| 224 | | m_write_d(0, m_d, 0xff); |
| 225 | | // TODO: exit from floating mode on D-pins |
| 226 | d_latch_out(true); |
| 226 | 227 | } |
| 227 | 228 | |
| 228 | 229 | void amis2000_device::op_mvs() |
| 229 | 230 | { |
| 230 | 231 | // MVS: output master strobe latch to A-pins |
| 232 | d_latch_out(false); |
| 231 | 233 | m_write_a(0, m_a, 0xffff); |
| 232 | | // TODO: enter floating mode on D-pins |
| 233 | 234 | } |
| 234 | 235 | |
| 235 | 236 | void amis2000_device::op_psh() |
| r243301 | r243302 | |
| 244 | 245 | |
| 245 | 246 | case 0xe: |
| 246 | 247 | // exit from floating mode on D-pins |
| 247 | | // ? |
| 248 | d_latch_out(true); |
| 248 | 249 | break; |
| 249 | 250 | |
| 250 | 251 | case 0xf: |
| r243301 | r243302 | |
| 271 | 272 | |
| 272 | 273 | case 0xe: |
| 273 | 274 | // enter floating mode on D-pins |
| 274 | | // ? |
| 275 | d_latch_out(false); |
| 275 | 276 | break; |
| 276 | 277 | |
| 277 | 278 | case 0xf: |
| r243301 | r243302 | |
| 288 | 289 | |
| 289 | 290 | void amis2000_device::op_eur() |
| 290 | 291 | { |
| 291 | | // EUR: set timer frequency(European) and D-latch polarity |
| 292 | | op_illegal(); |
| 292 | // EUR: set timer frequency(European) and D-latch polarity, via ACC |
| 293 | m_d_polarity = (m_acc & 1) ? 0x00 : 0xff; |
| 294 | d_latch_out(m_d_active); // refresh |
| 293 | 295 | } |
| 294 | 296 | |
| 295 | 297 | |
| r243301 | r243302 | |
| 350 | 352 | // NOP: no operation |
| 351 | 353 | } |
| 352 | 354 | |
| 355 | void amis2000_device::op_halt() |
| 356 | { |
| 357 | // HALT: debugger breakpoint for devkit-use |
| 358 | logerror("%s unknown opcode $%02X at $%04X\n", tag(), m_op, m_pc); |
| 359 | } |
| 353 | 360 | |
| 361 | |
| 354 | 362 | // Skip Instructions |
| 355 | 363 | |
| 356 | 364 | void amis2000_device::op_szc() |
| r243301 | r243302 | |
| 393 | 401 | void amis2000_device::op_sos() |
| 394 | 402 | { |
| 395 | 403 | // SOS: skip next on SF(timer output), clear SF |
| 396 | | op_illegal(); |
| 404 | logerror("%s unknown opcode $%02X at $%04X\n", tag(), m_op, m_pc); |
| 397 | 405 | } |
| 398 | 406 | |
| 399 | 407 | void amis2000_device::op_tf1() |