Previous 199869 Revisions Next

r19737 Sunday 23rd December, 2012 at 02:26:27 UTC by Ryan Holtz
- ssem.c: Modernized the SSEM core. [MooglyGuy]
[src/emu/cpu/ssem]ssem.c ssem.h

trunk/src/emu/cpu/ssem/ssem.c
r19736r19737
1414#define SSEM_DISASM_ON_UNIMPL           0
1515#define SSEM_DUMP_MEM_ON_UNIMPL         0
1616
17struct ssem_state
18{
19    UINT32 pc;
20    UINT32 a;
21    UINT32 halt;
22
23    legacy_cpu_device *device;
24    address_space *program;
25    int icount;
26};
27
28INLINE ssem_state *get_safe_token(device_t *device)
29{
30    assert(device != NULL);
31    assert(device->type() == SSEM);
32    return (ssem_state *)downcast<legacy_cpu_device *>(device)->token();
33}
34
3517#define INSTR       ((op >> 13) & 7)
3618#define ADDR        (op & 0x1f)
3719
r19736r19737
5840    return v;
5941}
6042
61INLINE UINT32 READ32(ssem_state *cpustate, UINT32 address)
43inline UINT32 ssem_device::program_read32(UINT32 address)
6244{
6345    UINT32 v = 0;
6446    // The MAME core does not have a good way of specifying a minimum datum size that is more than
r19736r19737
6648    // the address value to get the appropriate byte index.
6749    address <<= 2;
6850
69    v |= cpustate->program->read_byte(address + 0) << 24;
70    v |= cpustate->program->read_byte(address + 1) << 16;
71    v |= cpustate->program->read_byte(address + 2) <<  8;
72    v |= cpustate->program->read_byte(address + 3) <<  0;
51    v |= m_program->read_byte(address + 0) << 24;
52    v |= m_program->read_byte(address + 1) << 16;
53    v |= m_program->read_byte(address + 2) <<  8;
54    v |= m_program->read_byte(address + 3) <<  0;
7355
7456    return reverse(v);
7557}
7658
77INLINE void WRITE32(ssem_state *cpustate, UINT32 address, UINT32 data)
59inline void ssem_device::program_write32(UINT32 address, UINT32 data)
7860{
7961    UINT32 v = reverse(data);
8062
r19736r19737
8365    // the address value to get the appropriate byte index.
8466    address <<= 2;
8567
86    cpustate->program->write_byte(address + 0, (v >> 24) & 0x000000ff);
87    cpustate->program->write_byte(address + 1, (v >> 16) & 0x000000ff);
88    cpustate->program->write_byte(address + 2, (v >>  8) & 0x000000ff);
89    cpustate->program->write_byte(address + 3, (v >>  0) & 0x000000ff);
68    m_program->write_byte(address + 0, (v >> 24) & 0x000000ff);
69    m_program->write_byte(address + 1, (v >> 16) & 0x000000ff);
70    m_program->write_byte(address + 2, (v >>  8) & 0x000000ff);
71    m_program->write_byte(address + 3, (v >>  0) & 0x000000ff);
9072    return;
9173}
9274
9375/*****************************************************************************/
9476
95static void unimplemented_opcode(ssem_state *cpustate, UINT32 op)
77ssem_device::ssem_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
78   : cpu_device(mconfig, SSEM, "SSEM", tag, owner, clock),
79     m_program_config("program", ENDIANNESS_LITTLE, 8, 16),
80     m_pc(1),
81     m_shifted_pc(1<<2),
82     m_a(0),
83     m_halt(0),
84      m_icount(0)
9685{
97    if((cpustate->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
98    {
99        char string[200];
100        ssem_dasm_one(string, cpustate->pc-1, op);
101        mame_printf_debug("%08X: %s\n", cpustate->pc-1, string);
102    }
86    // Allocate & setup
87}
10388
104#if SSEM_DISASM_ON_UNIMPL
105    {
106        char string[200] = { 0 };
107        UINT32 i = 0;
108        FILE *disasm = fopen("ssemdasm.txt", "wt");
10989
110        if(disasm)
111        {
112            for(i = 0; i < 0x20; i++)
113            {
114                UINT32 opcode = reverse(READ32(cpustate, i));
115                ssem_dasm_one(string, i, opcode);
116                fprintf(disasm, "%02X: %08X    %s\n", i, opcode, string);
117            }
90void ssem_device::device_start()
91{
92   m_program = &space(AS_PROGRAM);
11893
119            fclose(disasm);
120        }
121    }
122#endif
123#if SSEM_DUMP_MEM_ON_UNIMPL
124    {
125        UINT32 i = 0;
126        FILE *store = fopen("ssemmem.bin", "wb");
94   // register our state for the debugger
95   astring tempstr;
96   state_add(STATE_GENPC,     "GENPC",     m_pc).noshow();
97   state_add(STATE_GENFLAGS,  "GENFLAGS",  m_halt).callimport().callexport().formatstr("%1s").noshow();
98   state_add(SSEM_PC,         "PC",       m_shifted_pc).mask(0xffff);
99   state_add(SSEM_A,          "A",          m_a).mask(0xffffffff);
100   state_add(SSEM_HALT,       "HALT",     m_halt).mask(0xf);
127101
128        if(store)
129        {
130            for( i = 0; i < 0x80; i++ )
131            {
132                fputc(cpustate->program->read_byte(i), store);
133            }
134            fclose(store);
135        }
136    }
137#endif
102   /* setup regtable */
103   save_item(NAME(m_pc));
104   save_item(NAME(m_a));
105   save_item(NAME(m_halt));
138106
139    fatalerror("SSEM: unknown opcode %d (%08X) at %d\n", reverse(op) & 7, reverse(op), cpustate->pc);
107   // set our instruction counter
108   m_icountptr = &m_icount;
140109}
141110
142/*****************************************************************************/
111void ssem_device::device_stop()
112{
113}
143114
144static CPU_INIT( ssem )
115void ssem_device::device_reset()
145116{
146    ssem_state *cpustate = get_safe_token(device);
147    cpustate->pc = 1;
148    cpustate->a = 0;
149    cpustate->halt = 0;
117    m_pc = 1;
118    m_shifted_pc = m_pc << 2;
119    m_a = 0;
120    m_halt = 0;
121}
150122
151    cpustate->device = device;
152    cpustate->program = &device->space(AS_PROGRAM);
123
124//-------------------------------------------------
125//  memory_space_config - return the configuration
126//  of the specified address space, or NULL if
127//  the space doesn't exist
128//-------------------------------------------------
129
130const address_space_config *ssem_device::memory_space_config(address_spacenum spacenum) const
131{
132   if (spacenum == AS_PROGRAM)
133   {
134      return &m_program_config;
135   }
136   return NULL;
153137}
154138
155static CPU_EXIT( ssem )
139
140//-------------------------------------------------
141//  state_string_export - export state as a string
142//  for the debugger
143//-------------------------------------------------
144
145void ssem_device::state_string_export(const device_state_entry &entry, astring &string)
156146{
147   switch (entry.index())
148   {
149      case STATE_GENFLAGS:
150         string.printf("%c", m_halt ? 'H' : '.');
151         break;
152   }
157153}
158154
159static CPU_RESET( ssem )
155
156//-------------------------------------------------
157//  disasm_min_opcode_bytes - return the length
158//  of the shortest instruction, in bytes
159//-------------------------------------------------
160
161UINT32 ssem_device::disasm_min_opcode_bytes() const
160162{
161    ssem_state *cpustate = get_safe_token(device);
163   return 4;
164}
162165
163    cpustate->pc = 1;
164    cpustate->a = 0;
165    cpustate->halt = 0;
166
167//-------------------------------------------------
168//  disasm_max_opcode_bytes - return the length
169//  of the longest instruction, in bytes
170//-------------------------------------------------
171
172UINT32 ssem_device::disasm_max_opcode_bytes() const
173{
174   return 4;
166175}
167176
168static CPU_EXECUTE( ssem )
177
178//-------------------------------------------------
179//  disasm_disassemble - call the disassembly
180//  helper function
181//-------------------------------------------------
182
183offs_t ssem_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
169184{
170    ssem_state *cpustate = get_safe_token(device);
185   extern CPU_DISASSEMBLE( ssem );
186   return disassemble(buffer, pc, oprom, opram, 0);
187}
188
189
190//**************************************************************************
191//  CORE EXECUTION LOOP
192//**************************************************************************
193
194//-------------------------------------------------
195//  execute_min_cycles - return minimum number of
196//  cycles it takes for one instruction to execute
197//-------------------------------------------------
198
199UINT32 ssem_device::execute_min_cycles() const
200{
201   return 1;
202}
203
204
205//-------------------------------------------------
206//  execute_max_cycles - return maximum number of
207//  cycles it takes for one instruction to execute
208//-------------------------------------------------
209
210UINT32 ssem_device::execute_max_cycles() const
211{
212   return 1;
213}
214
215
216//-------------------------------------------------
217//  execute_input_lines - return the number of
218//  input/interrupt lines
219//-------------------------------------------------
220
221UINT32 ssem_device::execute_input_lines() const
222{
223   return 0;
224}
225
226
227//-------------------------------------------------
228//  execute_set_input - set the state of an input
229//  line during execution
230//-------------------------------------------------
231
232void ssem_device::execute_set_input(int inputnum, int state)
233{
234}
235
236
237//-------------------------------------------------
238//  execute_run - execute a timeslice's worth of
239//  opcodes
240//-------------------------------------------------
241
242void ssem_device::execute_run()
243{
171244    UINT32 op;
172245
173    cpustate->pc &= 0x1f;
246    m_pc &= 0x1f;
247    m_shifted_pc = m_pc << 2;
174248
175    while (cpustate->icount > 0)
249    while (m_icount > 0)
176250    {
177        debugger_instruction_hook(device, cpustate->pc);
251        debugger_instruction_hook(this, m_pc);
178252
179        op = READ32(cpustate, cpustate->pc);
253        op = program_read32(m_pc);
180254
181        if( !cpustate->halt )
255        if( !m_halt )
182256        {
183            cpustate->pc++;
257            m_pc++;
258          m_shifted_pc = m_pc << 2;
184259        }
185260        else
186261        {
r19736r19737
191266        {
192267            case 0:
193268                // JMP: Move the value at the specified address into the Program Counter.
194                cpustate->pc = READ32(cpustate, ADDR) + 1;
269                m_pc = program_read32(ADDR) + 1;
270             m_shifted_pc = m_pc << 2;
195271                break;
196272            case 1:
197273                // JRP: Add the value at the specified address to the Program Counter.
198                cpustate->pc += (INT32)READ32(cpustate, ADDR);
274                m_pc += (INT32)program_read32(ADDR);
275             m_shifted_pc = m_pc << 2;
199276                break;
200277            case 2:
201278                // LDN: Load the accumulator with the two's-complement negation of the value at the specified address.
202                cpustate->a = (UINT32)(0 - (INT32)READ32(cpustate, ADDR));
279                m_a = (UINT32)(0 - (INT32)program_read32(ADDR));
203280                break;
204281            case 3:
205282                // STO: Store the value in the accumulator at the specified address.
206                WRITE32(cpustate, ADDR, cpustate->a);
283                program_write32(ADDR, m_a);
207284                break;
208285            case 4:
209286            case 5:
210287                // SUB: Subtract the value at the specified address from the accumulator.
211                cpustate->a -= READ32(cpustate, ADDR);
288                m_a -= program_read32(ADDR);
212289                break;
213290            case 6:
214291                // CMP: If the accumulator is less than zero, skip the next opcode.
215                if((INT32)(cpustate->a) < 0)
292                if((INT32)(m_a) < 0)
216293                {
217                    cpustate->pc++;
294                   m_pc++;
295                m_shifted_pc = m_pc << 2;
218296                }
219297                break;
220298            case 7:
221299                // STP: Halt the computer.
222                cpustate->halt = 1;
300                m_halt = 1;
223301                break;
224302            default:
225                // This is impossible, but it's better to be safe than sorry.
226                unimplemented_opcode(cpustate, op);
303               break;
227304        }
228305
229        --cpustate->icount;
306        --m_icount;
230307    }
231308}
232
233
234/*****************************************************************************/
235
236static CPU_SET_INFO( ssem )
237{
238    ssem_state *cpustate = get_safe_token(device);
239
240    switch (state)
241    {
242        /* --- the following bits of info are set as 64-bit signed integers --- */
243        case CPUINFO_INT_PC:
244        case CPUINFO_INT_REGISTER + SSEM_PC:            cpustate->pc = info->i;         break;
245        case CPUINFO_INT_REGISTER + SSEM_A:             cpustate->a = info->i;          break;
246        case CPUINFO_INT_REGISTER + SSEM_HALT:          cpustate->halt = info->i;       break;
247    }
248}
249
250CPU_GET_INFO( ssem )
251{
252    ssem_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
253
254    switch(state)
255    {
256        /* --- the following bits of info are returned as 64-bit signed integers --- */
257        case CPUINFO_INT_CONTEXT_SIZE:          info->i = sizeof(ssem_state);   break;
258        case CPUINFO_INT_INPUT_LINES:           info->i = 0;                    break;
259        case CPUINFO_INT_DEFAULT_IRQ_VECTOR:    info->i = 0;                    break;
260        case CPUINFO_INT_ENDIANNESS:            info->i = ENDIANNESS_LITTLE;    break;
261        case CPUINFO_INT_CLOCK_MULTIPLIER:      info->i = 1;                    break;
262        case CPUINFO_INT_CLOCK_DIVIDER:         info->i = 1;                    break;
263        case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4;                    break;
264        case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4;                    break;
265        case CPUINFO_INT_MIN_CYCLES:            info->i = 1;                    break;
266        case CPUINFO_INT_MAX_CYCLES:            info->i = 1;                    break;
267
268        case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8;                    break;
269        case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16;                   break;
270        case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0;                    break;
271        case CPUINFO_INT_DATABUS_WIDTH + AS_DATA:    info->i = 0;                    break;
272        case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA:    info->i = 0;                    break;
273        case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA:    info->i = 0;                    break;
274        case CPUINFO_INT_DATABUS_WIDTH + AS_IO:      info->i = 0;                    break;
275        case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO:      info->i = 0;                    break;
276        case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO:      info->i = 0;                    break;
277
278        case CPUINFO_INT_PC:    /* intentional fallthrough */
279        case CPUINFO_INT_REGISTER + SSEM_PC:    info->i = cpustate->pc << 2;    break;
280        case CPUINFO_INT_REGISTER + SSEM_A:     info->i = cpustate->a;          break;
281        case CPUINFO_INT_REGISTER + SSEM_HALT:  info->i = cpustate->halt;       break;
282
283        /* --- the following bits of info are returned as pointers to data or functions --- */
284        case CPUINFO_FCT_SET_INFO:              info->setinfo = CPU_SET_INFO_NAME(ssem);        break;
285        case CPUINFO_FCT_INIT:                  info->init = CPU_INIT_NAME(ssem);               break;
286        case CPUINFO_FCT_RESET:                 info->reset = CPU_RESET_NAME(ssem);             break;
287        case CPUINFO_FCT_EXIT:                  info->exit = CPU_EXIT_NAME(ssem);               break;
288        case CPUINFO_FCT_EXECUTE:               info->execute = CPU_EXECUTE_NAME(ssem);         break;
289        case CPUINFO_FCT_BURN:                  info->burn = NULL;                              break;
290        case CPUINFO_FCT_DISASSEMBLE:           info->disassemble = CPU_DISASSEMBLE_NAME(ssem); break;
291        case CPUINFO_PTR_INSTRUCTION_COUNTER:   info->icount = &cpustate->icount;               break;
292
293        /* --- the following bits of info are returned as NULL-terminated strings --- */
294        case CPUINFO_STR_NAME:                          strcpy(info->s, "SSEM");                break;
295        case CPUINFO_STR_FAMILY:                   strcpy(info->s, "SSEM");                break;
296        case CPUINFO_STR_VERSION:                  strcpy(info->s, "1.0");                 break;
297        case CPUINFO_STR_SOURCE_FILE:                     strcpy(info->s, __FILE__);              break;
298        case CPUINFO_STR_CREDITS:                  strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
299
300        case CPUINFO_STR_FLAGS:                         strcpy(info->s, " ");                   break;
301
302        case CPUINFO_STR_REGISTER + SSEM_PC:            sprintf(info->s, "PC: %08X", cpustate->pc);     break;
303        case CPUINFO_STR_REGISTER + SSEM_A:             sprintf(info->s, "A: %08X", cpustate->a);       break;
304        case CPUINFO_STR_REGISTER + SSEM_HALT:          sprintf(info->s, "HALT: %d", cpustate->halt);   break;
305    }
306}
307
308DEFINE_LEGACY_CPU_DEVICE(SSEM, ssem);
trunk/src/emu/cpu/ssem/ssem.h
r19736r19737
99#ifndef __SSEM_H__
1010#define __SSEM_H__
1111
12//**************************************************************************
13//  TYPE DEFINITIONS
14//**************************************************************************
15
16class ssem_device;
17
18// ======================> ssem_device
19
20// Used by core CPU interface
21class ssem_device : public cpu_device
22{
23public:
24   // construction/destruction
25   ssem_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
26
27   // device-level overrides
28   virtual void device_start();
29   virtual void device_reset();
30   virtual void device_stop();
31
32   // device_execute_interface overrides
33   virtual UINT32 execute_min_cycles() const;
34   virtual UINT32 execute_max_cycles() const;
35   virtual UINT32 execute_input_lines() const;
36   virtual void execute_run();
37   virtual void execute_set_input(int inputnum, int state);
38
39   // device_memory_interface overrides
40   virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
41
42   // device_disasm_interface overrides
43   virtual UINT32 disasm_min_opcode_bytes() const;
44   virtual UINT32 disasm_max_opcode_bytes() const;
45   virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
46
47   // device_state_interface overrides
48   virtual void state_string_export(const device_state_entry &entry, astring &string);
49
50   // address spaces
51   const address_space_config m_program_config;
52
53   // memory access
54   inline UINT32 program_read32(UINT32 addr);
55   inline void program_write32(UINT32 addr, UINT32 data);
56
57   // CPU registers
58    UINT32 m_pc;
59    UINT32 m_shifted_pc;
60    UINT32 m_a;
61    UINT32 m_halt;
62
63   // other internal states
64    int m_icount;
65
66   // address spaces
67    address_space *m_program;
68};
69
70// device type definition
71extern const device_type SSEM;
72
73/***************************************************************************
74    REGISTER ENUMERATION
75***************************************************************************/
76
1277enum
1378{
1479    SSEM_PC = 1,
r19736r19737
1681    SSEM_HALT,
1782};
1883
19DECLARE_LEGACY_CPU_DEVICE(SSEM, ssem);
84CPU_DISASSEMBLE( ssem );
2085
21extern offs_t ssem_dasm_one(char *buffer, offs_t pc, UINT32 op);
22
2386#endif /* __SSEM_H__ */

Previous 199869 Revisions Next


© 1997-2024 The MAME Team