1 /* CPU emulation loop and memory access
3 * (C) 2018 by Andreas Eversberg <jolly@eversberg.eu>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 #define IOMASK 0xfffff000
31 #define IOBASE 0x00dff000
33 static uint8_t *memory = NULL;
34 static uint32_t memory_size = 0;
35 static uint16_t *chipreg = NULL;
37 static uint16_t read_io(unsigned int address)
40 printf("Chip read from 0x%08x\n", address);
42 return emulate_io_read(address);
45 static void write_io(unsigned int address, uint16_t value)
48 printf("Chip write to 0x%08x\n", address);
50 if ((address & IOMASK) == IOBASE)
51 chipreg[address & ~IOMASK] = value;
52 emulate_io_write(address, value);
55 unsigned int m68k_read_memory_8(unsigned int address)
57 if (address > memory_size - 1) {
59 /* read lower (right) byte */
60 return read_io(address & ~1);
62 /* read upper (left) byte */
63 return read_io(address) >> 8;
66 return *((uint8_t *)(memory + address));
69 unsigned int m68k_read_memory_16(unsigned int address)
71 if (address > memory_size - 2) {
72 return read_io(address);
74 return be16toh(*((uint16_t *)(memory + address)));
77 unsigned int m68k_read_memory_32(unsigned int address)
79 if (address > memory_size - 4) {
81 value = read_io(address) << 16;
82 value |= read_io(address + 2);
85 return be32toh(*((uint32_t *)(memory + address)));
88 void m68k_write_memory_8(unsigned int address, unsigned int value)
90 if (address > memory_size - 1) {
92 /* write lower (right) byte */
93 write_io(address & ~1, 0xff00 | value);
95 /* write upper (left) byte */
96 write_io(address, 0x00ff | (value << 8));
100 *((uint8_t *)(memory + address)) = value;
103 void m68k_write_memory_16(unsigned int address, unsigned int value)
105 if (address > memory_size - 2) {
106 write_io(address, value);
109 *((uint16_t *)(memory + address)) = htobe16(value);
112 void m68k_write_memory_32(unsigned int address, unsigned int value)
114 if (address > memory_size - 4) {
115 write_io(address, value >> 16);
116 write_io(address + 2, value);
119 *((uint32_t *)(memory + address)) = htobe32(value);
122 void execute_init(int32_t _memory_size, uint8_t *_memory, uint16_t *_chipreg)
124 memory_size = _memory_size;
130 m68k_set_cpu_type(M68K_CPU_TYPE_68000);
138 int execute_cpu(int irq, const struct cpu_stop stop_at[], int *event)
141 int instruction_count = 0;
148 /* loop until we returned from interrupt */
150 /* execute one opcode */
151 cycle_count += m68k_execute(0);
153 } while (REG_PC != save_pc);
155 printf("interrupt %d took %d opcodes\n", irq, instruction_count);
159 /* execute one opcode */
160 cycle_count += m68k_execute(0);
163 /* checking if game does not hit any 'stop_at' break point, give error output */
164 if (instruction_count >= 10000000) {
165 if (instruction_count == 10000000)
166 fprintf(stderr, "!!! games seems to got stuck in an endless loop, please fix !!!\n");
167 fprintf(stderr, "program counter at: %06x\n", REG_PC);
168 if (instruction_count == 10000020)
172 for (i = 0; stop_at[i].event; i++) {
173 if (REG_PC == stop_at[i].pc) {
175 printf("execution to address 0x%06x took %d opcodes\n", REG_PC, instruction_count);
177 *event = stop_at[i].event;