mirror of
https://github.com/InvisibleUp/uvmac.git
synced 2025-02-21 02:29:00 +00:00
Move libraries around
This commit is contained in:
parent
53d2e6953f
commit
2afb2906da
5
.gitmodules
vendored
5
.gitmodules
vendored
@ -1,6 +1,3 @@
|
||||
[submodule "src/incbin"]
|
||||
path = src/incbin
|
||||
url = https://github.com/graphitemaster/incbin
|
||||
[submodule "src/tomlc99"]
|
||||
path = src/tomlc99
|
||||
path = lib/tomlc99
|
||||
url = https://github.com/cktan/tomlc99
|
||||
|
@ -1,42 +0,0 @@
|
||||
EXENAME = sim
|
||||
|
||||
OSD_DOS = osd_dos.c
|
||||
|
||||
OSDFILES = osd_linux.c # $(OSD_DOS)
|
||||
MAINFILES = sim.c
|
||||
MUSASHIFILES = m68kcpu.c m68kdasm.c softfloat/softfloat.c
|
||||
MUSASHIGENCFILES = m68kops.c
|
||||
MUSASHIGENHFILES = m68kops.h
|
||||
MUSASHIGENERATOR = m68kmake
|
||||
|
||||
# EXE = .exe
|
||||
# EXEPATH = .\\
|
||||
EXE =
|
||||
EXEPATH = ./
|
||||
|
||||
.CFILES = $(MAINFILES) $(OSDFILES) $(MUSASHIFILES) $(MUSASHIGENCFILES)
|
||||
.OFILES = $(.CFILES:%.c=%.o)
|
||||
|
||||
CC = gcc
|
||||
WARNINGS = -Wall -Wextra -pedantic
|
||||
CFLAGS = $(WARNINGS)
|
||||
LFLAGS = $(WARNINGS)
|
||||
|
||||
TARGET = $(EXENAME)$(EXE)
|
||||
|
||||
DELETEFILES = $(MUSASHIGENCFILES) $(MUSASHIGENHFILES) $(.OFILES) $(TARGET) $(MUSASHIGENERATOR)$(EXE)
|
||||
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
rm -f $(DELETEFILES)
|
||||
|
||||
$(TARGET): $(MUSASHIGENHFILES) $(.OFILES) Makefile
|
||||
$(CC) -o $@ $(.OFILES) $(LFLAGS) -lm
|
||||
|
||||
$(MUSASHIGENCFILES) $(MUSASHIGENHFILES): $(MUSASHIGENERATOR)$(EXE)
|
||||
$(EXEPATH)$(MUSASHIGENERATOR)$(EXE)
|
||||
|
||||
$(MUSASHIGENERATOR)$(EXE): $(MUSASHIGENERATOR).c
|
||||
$(CC) -o $(MUSASHIGENERATOR)$(EXE) $(MUSASHIGENERATOR).c
|
@ -1,290 +0,0 @@
|
||||
EXAMPLE:
|
||||
-------
|
||||
As an example, I'll build an imaginary hardware platform.
|
||||
|
||||
|
||||
The system is fairly simple, comprising a 68000, an input device, an output
|
||||
device, a non-maskable-interrupt device, and an interrupt controller.
|
||||
|
||||
|
||||
The input device receives input from the user and asserts its interrupt
|
||||
request line until its value is read. Reading from the input device's
|
||||
memory-mapped port will both clear its interrupt request and read an ASCII
|
||||
representation (8 bits) of what the user entered.
|
||||
|
||||
The output device reads value when it is selected through its memory-mapped
|
||||
port and outputs it to a display. The value it reads will be interpreted as
|
||||
an ASCII value and output to the display. The output device is fairly slow
|
||||
(it can only process 1 byte per second), and so it asserts its interrupt
|
||||
request line when it is ready to receive a byte. Writing to the output device
|
||||
sends a byte to it. If the output device is not ready, the write is ignored.
|
||||
Reading from the output device returns 0 and clears its interrupt request line
|
||||
until another byte is written to it and 1 second elapses.
|
||||
|
||||
The non-maskable-interrupt (NMI) device, as can be surmised from the name,
|
||||
generates a non-maskable-interrupt. This is connected to some kind of external
|
||||
switch that the user can push to generate a NMI.
|
||||
|
||||
Since there are 3 devices interrupting the CPU, an interrupt controller is
|
||||
needed. The interrupt controller takes 7 inputs and encodes the highest
|
||||
priority asserted line on the 3 output pins. the input device is wired to IN2
|
||||
and the output device is wired to IN1 on the controller. The NMI device is
|
||||
wired to IN7 and all the other inputs are wired low.
|
||||
|
||||
The bus is also connected to a 1K ROM and a 256 byte RAM.
|
||||
Beware: This platform places ROM and RAM in the same address range and uses
|
||||
the FC pins to select the correct address space!
|
||||
(You didn't expect me to make it easy, did you? =)
|
||||
|
||||
|
||||
|
||||
Here is the schematic in all its ASCII splendour:
|
||||
-------------------------------------------------
|
||||
|
||||
NMI TIED
|
||||
SWITCH LOW
|
||||
| |
|
||||
| +-+-+-+
|
||||
| | | | | +------------------------------------------------+
|
||||
| | | | | | +------------------------------------+ |
|
||||
| | | | | | | | |
|
||||
+-------------+ | |
|
||||
|7 6 5 4 3 2 1| | |
|
||||
| | | |
|
||||
| INT CONTRLR | | |
|
||||
| | | |
|
||||
|i i i | | |
|
||||
|2 1 0 | | |
|
||||
+-------------+ | |
|
||||
| | | | |
|
||||
| | | +--------------------------------+--+ | |
|
||||
o o o | | | | |
|
||||
+--------------+ +-------+ +----------+ +---------+ +----------+
|
||||
| I I I a | | | | | | r a i | | i |
|
||||
| 2 1 0 23 | | | | | | e c | | |
|
||||
| | | | | | | a k | | |
|
||||
| | | | | | | d | | |
|
||||
| | | | | | | | | |
|
||||
| M68000 | | ROM | | RAM | | IN | | OUT |
|
||||
| | | | | | | | | |
|
||||
| a9|--|a9 |--| |--| |--| |
|
||||
| a8|--|a8 |--| |--| |--| |
|
||||
| a7|--|a7 |--|a7 |--| |--| |
|
||||
| a6|--|a6 |--|a6 |--| |--| |
|
||||
| a5|--|a5 |--|a5 |--| |--| |
|
||||
| a4|--|a4 |--|a4 |--| |--| |
|
||||
| a3|--|a3 |--|a3 |--| |--| |
|
||||
| a2|--|a2 |--|a2 |--| |--| |
|
||||
| a1|--|a1 |--|a1 |--| |--| |
|
||||
| a0|--|a0 |--|a0 |--| |--| |
|
||||
| | | | | | | | | |
|
||||
| d15|--|d15 |--|d15 |--| |--| |
|
||||
| d14|--|d14 |--|d14 |--| |--| |
|
||||
| d13|--|d13 |--|d13 |--| |--| |
|
||||
| d12|--|d12 |--|d12 |--| |--| |
|
||||
| d11|--|d11 |--|d11 |--| |--| |
|
||||
| d10|--|d10 |--|d10 |--| |--| |
|
||||
| d9|--|d9 |--|d9 |--| |--| |
|
||||
| d8|--|d8 |--|d8 |--| |--| |
|
||||
| d7|--|d7 |--|d7 |--|d7 |--|d7 |
|
||||
| d6|--|d6 |--|d6 |--|d6 |--|d6 |
|
||||
| d5|--|d5 |--|d5 |--|d5 |--|d5 |
|
||||
| d4|--|d4 |--|d4 |--|d4 |--|d4 |
|
||||
| d3|--|d3 |--|d3 |--|d3 |--|d3 |
|
||||
| d2|--|d2 |--|d2 |--|d2 |--|d2 |
|
||||
| d1|--|d1 |--|d1 |--|d1 |--|d1 w |
|
||||
| d0|--|d0 |--|d0 |--|d0 |--|d0 r |
|
||||
| | | | | | | | | i a |
|
||||
| a F F F | | | | | | | | t c |
|
||||
|22 rW 2 1 0 | | cs | | cs rW | | | | e k |
|
||||
+--------------+ +-------+ +----------+ +---------+ +----------+
|
||||
| | | | | | | | | |
|
||||
| | | | | | | | | |
|
||||
| | | | | +-------+ +-----+ | +---+ |
|
||||
| | | | | | IC1 | | IC2 | | |AND| |
|
||||
| | | | | |a b c d| |a b c| | +---+ |
|
||||
| | | | | +-------+ +-----+ | | | |
|
||||
| | | | | | | | | | | | | | +--+
|
||||
| | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | |
|
||||
| | | | | | | | | | | | | | |
|
||||
| | | | +-----)-)-+-)----)-)-+ | | |
|
||||
| | | +-------)-+---)----)-+ | | |
|
||||
| | +---------+-----)----+ | | |
|
||||
| | | | | |
|
||||
| +------------------+-----------+----------------------+ |
|
||||
| |
|
||||
+-----------------------------------------------------------+
|
||||
|
||||
IC1: output=1 if a=0 and b=1 and c=0 and d=0
|
||||
IC2: output=1 if a=0 and b=0 and c=1
|
||||
|
||||
|
||||
|
||||
Here is the listing for program.bin:
|
||||
-----------------------------------
|
||||
|
||||
INPUT_ADDRESS equ $800000
|
||||
OUTPUT_ADDRESS equ $400000
|
||||
CIRCULAR_BUFFER equ $c0
|
||||
CAN_OUTPUT equ $d0
|
||||
STACK_AREA equ $100
|
||||
|
||||
vector_table:
|
||||
00000000 0000 0100 dc.l STACK_AREA * 0: SP
|
||||
00000004 0000 00c0 dc.l init * 1: PC
|
||||
00000008 0000 0148 dc.l unhandled_exception * 2: bus error
|
||||
0000000c 0000 0148 dc.l unhandled_exception * 3: address error
|
||||
00000010 0000 0148 dc.l unhandled_exception * 4: illegal instruction
|
||||
00000014 0000 0148 dc.l unhandled_exception * 5: zero divide
|
||||
00000018 0000 0148 dc.l unhandled_exception * 6: chk
|
||||
0000001c 0000 0148 dc.l unhandled_exception * 7: trapv
|
||||
00000020 0000 0148 dc.l unhandled_exception * 8: privilege violation
|
||||
00000024 0000 0148 dc.l unhandled_exception * 9: trace
|
||||
00000028 0000 0148 dc.l unhandled_exception * 10: 1010
|
||||
0000002c 0000 0148 dc.l unhandled_exception * 11: 1111
|
||||
00000030 0000 0148 dc.l unhandled_exception * 12: -
|
||||
00000034 0000 0148 dc.l unhandled_exception * 13: -
|
||||
00000038 0000 0148 dc.l unhandled_exception * 14: -
|
||||
0000003c 0000 0148 dc.l unhandled_exception * 15: uninitialized interrupt
|
||||
00000040 0000 0148 dc.l unhandled_exception * 16: -
|
||||
00000044 0000 0148 dc.l unhandled_exception * 17: -
|
||||
00000048 0000 0148 dc.l unhandled_exception * 18: -
|
||||
0000004c 0000 0148 dc.l unhandled_exception * 19: -
|
||||
00000050 0000 0148 dc.l unhandled_exception * 20: -
|
||||
00000054 0000 0148 dc.l unhandled_exception * 21: -
|
||||
00000058 0000 0148 dc.l unhandled_exception * 22: -
|
||||
0000005c 0000 0148 dc.l unhandled_exception * 23: -
|
||||
00000060 0000 0148 dc.l unhandled_exception * 24: spurious interrupt
|
||||
00000064 0000 0136 dc.l output_ready * 25: l1 irq
|
||||
00000068 0000 010e dc.l input_ready * 26: l2 irq
|
||||
0000006c 0000 0148 dc.l unhandled_exception * 27: l3 irq
|
||||
00000070 0000 0148 dc.l unhandled_exception * 28: l4 irq
|
||||
00000074 0000 0148 dc.l unhandled_exception * 29: l5 irq
|
||||
00000078 0000 0148 dc.l unhandled_exception * 30: l6 irq
|
||||
0000007c 0000 014e dc.l nmi * 31: l7 irq
|
||||
00000080 0000 0148 dc.l unhandled_exception * 32: trap 0
|
||||
00000084 0000 0148 dc.l unhandled_exception * 33: trap 1
|
||||
00000088 0000 0148 dc.l unhandled_exception * 34: trap 2
|
||||
0000008c 0000 0148 dc.l unhandled_exception * 35: trap 3
|
||||
00000090 0000 0148 dc.l unhandled_exception * 36: trap 4
|
||||
00000094 0000 0148 dc.l unhandled_exception * 37: trap 5
|
||||
00000098 0000 0148 dc.l unhandled_exception * 38: trap 6
|
||||
0000009c 0000 0148 dc.l unhandled_exception * 39: trap 7
|
||||
000000a0 0000 0148 dc.l unhandled_exception * 40: trap 8
|
||||
000000a4 0000 0148 dc.l unhandled_exception * 41: trap 9
|
||||
000000a8 0000 0148 dc.l unhandled_exception * 42: trap 10
|
||||
000000ac 0000 0148 dc.l unhandled_exception * 43: trap 11
|
||||
000000b0 0000 0148 dc.l unhandled_exception * 44: trap 12
|
||||
000000b4 0000 0148 dc.l unhandled_exception * 45: trap 13
|
||||
000000b8 0000 0148 dc.l unhandled_exception * 46: trap 14
|
||||
000000bc 0000 0148 dc.l unhandled_exception * 47: trap 15
|
||||
* This is the end of the useful part of the table.
|
||||
* We will now do the Capcom thing and put code starting at $c0.
|
||||
|
||||
init:
|
||||
* Copy the exception vector table to RAM.
|
||||
000000c0 227c 0000 0000 move.l #0, a1 * a1 is RAM index
|
||||
000000c6 303c 002f move.w #47, d0 * d0 is counter (48 vectors)
|
||||
000000ca 41fa 0006 lea.l (copy_table,PC), a0 * a0 is scratch
|
||||
000000ce 2208 move.l a0, d1 * d1 is ROM index
|
||||
000000d0 4481 neg.l d1
|
||||
copy_table:
|
||||
000000d2 22fb 18fe dc.l $22fb18fe * stoopid as68k generates 020 code here
|
||||
* move.l (copy_table,PC,d1.l), (a1)+
|
||||
000000d6 5841 addq #4, d1
|
||||
000000d8 51c8 fff8 dbf d0, copy_table
|
||||
|
||||
main_init:
|
||||
* Initialize main program
|
||||
000000dc 11fc 0000 00d0 move.b #0, CAN_OUTPUT
|
||||
000000e2 4df8 00c0 lea.l CIRCULAR_BUFFER, a6
|
||||
000000e6 7c00 moveq #0, d6 * output buffer ptr
|
||||
000000e8 7e00 moveq #0, d7 * input buffer ptr
|
||||
000000ea 027c f8ff andi #$f8ff, SR * clear interrupt mask
|
||||
main:
|
||||
* Main program
|
||||
000000ee 4a38 00d0 tst.b CAN_OUTPUT * can we output?
|
||||
000000f2 67fa beq main
|
||||
000000f4 be06 cmp.b d6, d7 * is there data?
|
||||
000000f6 67f6 beq main
|
||||
000000f8 11fc 0000 00d0 move.b #0, CAN_OUTPUT
|
||||
000000fe 13f6 6000 0040 move.b (0,a6,d6.w), OUTPUT_ADDRESS * write data
|
||||
0000
|
||||
00000106 5246 addq #1, d6
|
||||
00000108 0206 000f andi.b #15, d6 * update circular buffer
|
||||
0000010c 60e0 bra main
|
||||
|
||||
|
||||
input_ready:
|
||||
0000010e 2f00 move.l d0, -(a7)
|
||||
00000110 2f01 move.l d1, -(a7)
|
||||
00000112 1239 0080 0000 move.b INPUT_ADDRESS, d1 * read data
|
||||
00000118 1007 move.b d7, d0 * check if buffer full
|
||||
0000011a 5240 addq #1, d0
|
||||
0000011c 0200 000f andi.b #15, d0
|
||||
00000120 bc00 cmp.b d0, d6
|
||||
00000122 6700 000c beq input_ready_quit * throw away if full
|
||||
00000126 1d81 7000 move.b d1, (0,a6,d7.w) * store the data
|
||||
0000012a 5247 addq #1, d7
|
||||
0000012c 0207 000f andi.b #15, d7 * update circular buffer
|
||||
input_ready_quit:
|
||||
00000130 221f move.l (a7)+, d1
|
||||
00000132 201f move.l (a7)+, d0
|
||||
00000134 4e73 rte
|
||||
|
||||
output_ready:
|
||||
00000136 2f00 move.l d0, -(a7)
|
||||
00000138 11fc 0001 00d0 move.b #1, CAN_OUTPUT
|
||||
0000013e 1039 0040 0000 move.b OUTPUT_ADDRESS, d0 * acknowledge the interrupt
|
||||
00000144 201f move.l (a7)+, d0
|
||||
00000146 4e73 rte
|
||||
|
||||
unhandled_exception:
|
||||
00000148 4e72 2700 stop #$2700 * wait for NMI
|
||||
0000014c 60fa bra unhandled_exception * shouldn't get here
|
||||
|
||||
nmi:
|
||||
* perform a soft reset
|
||||
0000014e 46fc 2700 move #$2700, SR * set status register
|
||||
00000152 2e7a feac move.l (vector_table,PC), a7 * reset stack pointer
|
||||
00000156 4e70 reset * reset peripherals
|
||||
00000158 4efa feaa jmp (vector_table+4,PC) * reset program counter
|
||||
|
||||
END
|
||||
|
||||
|
||||
|
||||
Compiling the example host environment:
|
||||
--------------------------------------
|
||||
|
||||
I've only put in an os-dependant portion for dos/windows, so you'll either
|
||||
have to compile for that system or make your own osd code based on osd_dos.c
|
||||
and modify the makefile accordingly.
|
||||
|
||||
I compiled this example using the compiler from mingw (www.mingw.org) but you
|
||||
could also use djgpp (www.delorie.com).
|
||||
|
||||
- Copy the m68k files to a directory. Then extract the files from example.zip to
|
||||
the same directory, overwriting m68kconf.h. program.bin is the actual 68000
|
||||
program you will be running.
|
||||
- Make your own osd_get_key() in the same fashion as in osd_dos.c if you're not
|
||||
compiling for dos/windows.
|
||||
- Type make
|
||||
- Perform the necessary animal sacrifices.
|
||||
- Type sim program.bin
|
||||
|
||||
|
||||
Keys:
|
||||
ESC - quits the simulator
|
||||
~ - generates an NMI interrupt
|
||||
Any other key - Genearate input for the input device
|
||||
|
||||
|
||||
Note: I've cheated a bit in the emulation. There is no speed control
|
||||
to set the speed the CPU runs at; it simply runs as fast as your
|
||||
processor can run it.
|
||||
To add speed control, you will need a high-precision timestamp
|
||||
function (like the RDTSC instruction for newer Pentium CPUs)
|
||||
and a bit of arithmetic to make the cycles argument for m68k_execute().
|
||||
I'll leave that as an excercise to the reader.
|
@ -1 +0,0 @@
|
||||
../m68k.h
|
@ -1 +0,0 @@
|
||||
../m68k_in.c
|
@ -1,220 +0,0 @@
|
||||
/* ======================================================================== */
|
||||
/* ========================= LICENSING & COPYRIGHT ======================== */
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
* MUSASHI
|
||||
* Version 3.32
|
||||
*
|
||||
* A portable Motorola M680x0 processor emulation engine.
|
||||
* Copyright Karl Stenerud. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef M68KCONF__HEADER
|
||||
#define M68KCONF__HEADER
|
||||
|
||||
|
||||
/* Configuration switches.
|
||||
* Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks.
|
||||
* OPT_SPECIFY_HANDLER causes the core to link directly to the function
|
||||
* or macro you specify, rather than using callback functions whose pointer
|
||||
* must be passed in using m68k_set_xxx_callback().
|
||||
*/
|
||||
#define OPT_OFF 0
|
||||
#define OPT_ON 1
|
||||
#define OPT_SPECIFY_HANDLER 2
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== MAME STUFF ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* If you're compiling this for MAME, only change M68K_COMPILE_FOR_MAME
|
||||
* to OPT_ON and use m68kmame.h to configure the 68k core.
|
||||
*/
|
||||
#ifndef M68K_COMPILE_FOR_MAME
|
||||
#define M68K_COMPILE_FOR_MAME OPT_OFF
|
||||
#endif /* M68K_COMPILE_FOR_MAME */
|
||||
|
||||
|
||||
#if M68K_COMPILE_FOR_MAME == OPT_OFF
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================= CONFIGURATION ============================ */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Turn ON if you want to use the following M68K variants */
|
||||
#define M68K_EMULATE_010 OPT_ON
|
||||
#define M68K_EMULATE_EC020 OPT_ON
|
||||
#define M68K_EMULATE_020 OPT_ON
|
||||
#define M68K_EMULATE_040 OPT_ON
|
||||
|
||||
|
||||
/* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing
|
||||
* and m68k_read_pcrelative_xx() for PC-relative addressing.
|
||||
* If off, all read requests from the CPU will be redirected to m68k_read_xx()
|
||||
*/
|
||||
#define M68K_SEPARATE_READS OPT_OFF
|
||||
|
||||
/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a
|
||||
* predecrement destination EA mode instead of m68k_write_32().
|
||||
* To simulate real 68k behavior, m68k_write_32_pd() must first write the high
|
||||
* word to [address+2], and then write the low word to [address].
|
||||
*/
|
||||
#define M68K_SIMULATE_PD_WRITES OPT_OFF
|
||||
|
||||
/* If ON, CPU will call the interrupt acknowledge callback when it services an
|
||||
* interrupt.
|
||||
* If off, all interrupts will be autovectored and all interrupt requests will
|
||||
* auto-clear when the interrupt is serviced.
|
||||
*/
|
||||
#define M68K_EMULATE_INT_ACK OPT_SPECIFY_HANDLER
|
||||
#define M68K_INT_ACK_CALLBACK(A) cpu_irq_ack(A)
|
||||
|
||||
|
||||
/* If ON, CPU will call the breakpoint acknowledge callback when it encounters
|
||||
* a breakpoint instruction and it is running a 68010+.
|
||||
*/
|
||||
#define M68K_EMULATE_BKPT_ACK OPT_OFF
|
||||
#define M68K_BKPT_ACK_CALLBACK() your_bkpt_ack_handler_function()
|
||||
|
||||
|
||||
/* If ON, the CPU will monitor the trace flags and take trace exceptions
|
||||
*/
|
||||
#define M68K_EMULATE_TRACE OPT_OFF
|
||||
|
||||
|
||||
/* If ON, CPU will call the output reset callback when it encounters a reset
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_EMULATE_RESET OPT_SPECIFY_HANDLER
|
||||
#define M68K_RESET_CALLBACK() cpu_pulse_reset()
|
||||
|
||||
/* If ON, CPU will call the callback when it encounters a cmpi.l #v, dn
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_CMPILD_HAS_CALLBACK OPT_OFF
|
||||
#define M68K_CMPILD_CALLBACK(v,r) your_cmpild_handler_function(v,r)
|
||||
|
||||
|
||||
/* If ON, CPU will call the callback when it encounters a rte
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_RTE_HAS_CALLBACK OPT_OFF
|
||||
#define M68K_RTE_CALLBACK() your_rte_handler_function()
|
||||
|
||||
/* If ON, CPU will call the callback when it encounters a tas
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_TAS_HAS_CALLBACK OPT_OFF
|
||||
#define M68K_TAS_CALLBACK() your_tas_handler_function()
|
||||
|
||||
/* If ON, CPU will call the callback when it encounters an illegal instruction
|
||||
* passing the opcode as argument. If the callback returns 1, then it's considered
|
||||
* as a normal instruction, and the illegal exception in canceled. If it returns 0,
|
||||
* the exception occurs normally.
|
||||
* The callback looks like int callback(int opcode)
|
||||
* You should put OPT_SPECIFY_HANDLER here if you cant to use it, otherwise it will
|
||||
* use a dummy default handler and you'll have to call m68k_set_illg_instr_callback explicitely
|
||||
*/
|
||||
#define M68K_ILLG_HAS_CALLBACK OPT_OFF
|
||||
#define M68K_ILLG_CALLBACK(opcode) op_illg(opcode)
|
||||
|
||||
/* If ON, CPU will call the set fc callback on every memory access to
|
||||
* differentiate between user/supervisor, program/data access like a real
|
||||
* 68000 would. This should be enabled and the callback should be set if you
|
||||
* want to properly emulate the m68010 or higher. (moves uses function codes
|
||||
* to read/write data from different address spaces)
|
||||
*/
|
||||
#define M68K_EMULATE_FC OPT_SPECIFY_HANDLER
|
||||
#define M68K_SET_FC_CALLBACK(A) cpu_set_fc(A)
|
||||
|
||||
/* If ON, CPU will call the pc changed callback when it changes the PC by a
|
||||
* large value. This allows host programs to be nicer when it comes to
|
||||
* fetching immediate data and instructions on a banked memory system.
|
||||
*/
|
||||
#define M68K_MONITOR_PC OPT_OFF
|
||||
#define M68K_SET_PC_CALLBACK(A) your_pc_changed_handler_function(A)
|
||||
|
||||
|
||||
/* If ON, CPU will call the instruction hook callback before every
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_INSTRUCTION_HOOK OPT_SPECIFY_HANDLER
|
||||
#define M68K_INSTRUCTION_CALLBACK(pc) cpu_instr_callback(pc)
|
||||
|
||||
|
||||
/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */
|
||||
#define M68K_EMULATE_PREFETCH OPT_ON
|
||||
|
||||
|
||||
/* If ON, the CPU will generate address error exceptions if it tries to
|
||||
* access a word or longword at an odd address.
|
||||
* NOTE: This is only emulated properly for 68000 mode.
|
||||
*/
|
||||
#define M68K_EMULATE_ADDRESS_ERROR OPT_ON
|
||||
|
||||
|
||||
/* Turn ON to enable logging of illegal instruction calls.
|
||||
* M68K_LOG_FILEHANDLE must be #defined to a stdio file stream.
|
||||
* Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls.
|
||||
*/
|
||||
#define M68K_LOG_ENABLE OPT_OFF
|
||||
#define M68K_LOG_1010_1111 OPT_OFF
|
||||
#define M68K_LOG_FILEHANDLE some_file_handle
|
||||
|
||||
|
||||
/* ----------------------------- COMPATIBILITY ---------------------------- */
|
||||
|
||||
/* The following options set optimizations that violate the current ANSI
|
||||
* standard, but will be compliant under the forthcoming C9X standard.
|
||||
*/
|
||||
|
||||
|
||||
/* If ON, the enulation core will use 64-bit integers to speed up some
|
||||
* operations.
|
||||
*/
|
||||
#define M68K_USE_64_BIT OPT_ON
|
||||
|
||||
|
||||
#include "sim.h"
|
||||
|
||||
#define m68k_read_memory_8(A) cpu_read_byte(A)
|
||||
#define m68k_read_memory_16(A) cpu_read_word(A)
|
||||
#define m68k_read_memory_32(A) cpu_read_long(A)
|
||||
|
||||
#define m68k_read_disassembler_16(A) cpu_read_word_dasm(A)
|
||||
#define m68k_read_disassembler_32(A) cpu_read_long_dasm(A)
|
||||
|
||||
#define m68k_write_memory_8(A, V) cpu_write_byte(A, V)
|
||||
#define m68k_write_memory_16(A, V) cpu_write_word(A, V)
|
||||
#define m68k_write_memory_32(A, V) cpu_write_long(A, V)
|
||||
|
||||
|
||||
#endif /* M68K_COMPILE_FOR_MAME */
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
#endif /* M68KCONF__HEADER */
|
@ -1 +0,0 @@
|
||||
../m68kcpu.c
|
@ -1 +0,0 @@
|
||||
../m68kcpu.h
|
@ -1 +0,0 @@
|
||||
../m68kdasm.c
|
@ -1 +0,0 @@
|
||||
../m68kfpu.c
|
@ -1 +0,0 @@
|
||||
../m68kmake.c
|
@ -1 +0,0 @@
|
||||
../m68kmmu.h
|
@ -1,6 +0,0 @@
|
||||
#ifndef HEADER__OSD
|
||||
#define HEADER__OSD
|
||||
|
||||
int osd_get_char(void);
|
||||
|
||||
#endif /* HEADER__OSD */
|
@ -1,16 +0,0 @@
|
||||
#include "osd.h"
|
||||
|
||||
/* OS-dependant code to get a character from the user.
|
||||
* This function must not block, and must either return an ASCII code or -1.
|
||||
*/
|
||||
#include <conio.h>
|
||||
int osd_get_char(void)
|
||||
{
|
||||
int ch = -1;
|
||||
if(kbhit())
|
||||
{
|
||||
while(kbhit())
|
||||
ch = getch();
|
||||
}
|
||||
return ch;
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
void changemode(int dir)
|
||||
{
|
||||
static struct termios oldt, newt;
|
||||
|
||||
if ( dir == 1 )
|
||||
{
|
||||
tcgetattr( STDIN_FILENO, &oldt);
|
||||
newt = oldt;
|
||||
newt.c_lflag &= ~( ICANON | ECHO );
|
||||
tcsetattr( STDIN_FILENO, TCSANOW, &newt);
|
||||
}
|
||||
else
|
||||
tcsetattr( STDIN_FILENO, TCSANOW, &oldt);
|
||||
}
|
||||
|
||||
int kbhit (void)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set rdfs;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
FD_ZERO(&rdfs);
|
||||
FD_SET (STDIN_FILENO, &rdfs);
|
||||
|
||||
select(STDIN_FILENO+1, &rdfs, NULL, NULL, &tv);
|
||||
return FD_ISSET(STDIN_FILENO, &rdfs);
|
||||
|
||||
}
|
||||
|
||||
int osd_get_char() {
|
||||
changemode(1);
|
||||
int ch = -1;
|
||||
while(kbhit())
|
||||
ch = getchar();
|
||||
changemode(0);
|
||||
return ch;
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 348 B |
@ -1,563 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include "sim.h"
|
||||
#include "m68k.h"
|
||||
#include "osd.h"
|
||||
|
||||
void disassemble_program();
|
||||
|
||||
/* Memory-mapped IO ports */
|
||||
#define INPUT_ADDRESS 0x800000
|
||||
#define OUTPUT_ADDRESS 0x400000
|
||||
|
||||
/* IRQ connections */
|
||||
#define IRQ_NMI_DEVICE 7
|
||||
#define IRQ_INPUT_DEVICE 2
|
||||
#define IRQ_OUTPUT_DEVICE 1
|
||||
|
||||
/* Time between characters sent to output device (seconds) */
|
||||
#define OUTPUT_DEVICE_PERIOD 1
|
||||
|
||||
/* ROM and RAM sizes */
|
||||
#define MAX_ROM 0xfff
|
||||
#define MAX_RAM 0xff
|
||||
|
||||
|
||||
/* Read/write macros */
|
||||
#define READ_BYTE(BASE, ADDR) (BASE)[ADDR]
|
||||
#define READ_WORD(BASE, ADDR) (((BASE)[ADDR]<<8) | \
|
||||
(BASE)[(ADDR)+1])
|
||||
#define READ_LONG(BASE, ADDR) (((BASE)[ADDR]<<24) | \
|
||||
((BASE)[(ADDR)+1]<<16) | \
|
||||
((BASE)[(ADDR)+2]<<8) | \
|
||||
(BASE)[(ADDR)+3])
|
||||
|
||||
#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[ADDR] = (VAL)&0xff
|
||||
#define WRITE_WORD(BASE, ADDR, VAL) (BASE)[ADDR] = ((VAL)>>8) & 0xff; \
|
||||
(BASE)[(ADDR)+1] = (VAL)&0xff
|
||||
#define WRITE_LONG(BASE, ADDR, VAL) (BASE)[ADDR] = ((VAL)>>24) & 0xff; \
|
||||
(BASE)[(ADDR)+1] = ((VAL)>>16)&0xff; \
|
||||
(BASE)[(ADDR)+2] = ((VAL)>>8)&0xff; \
|
||||
(BASE)[(ADDR)+3] = (VAL)&0xff
|
||||
|
||||
|
||||
/* Prototypes */
|
||||
void exit_error(char* fmt, ...);
|
||||
|
||||
unsigned int cpu_read_byte(unsigned int address);
|
||||
unsigned int cpu_read_word(unsigned int address);
|
||||
unsigned int cpu_read_long(unsigned int address);
|
||||
void cpu_write_byte(unsigned int address, unsigned int value);
|
||||
void cpu_write_word(unsigned int address, unsigned int value);
|
||||
void cpu_write_long(unsigned int address, unsigned int value);
|
||||
void cpu_pulse_reset(void);
|
||||
void cpu_set_fc(unsigned int fc);
|
||||
int cpu_irq_ack(int level);
|
||||
|
||||
void nmi_device_reset(void);
|
||||
void nmi_device_update(void);
|
||||
int nmi_device_ack(void);
|
||||
|
||||
void input_device_reset(void);
|
||||
void input_device_update(void);
|
||||
int input_device_ack(void);
|
||||
unsigned int input_device_read(void);
|
||||
void input_device_write(unsigned int value);
|
||||
|
||||
void output_device_reset(void);
|
||||
void output_device_update(void);
|
||||
int output_device_ack(void);
|
||||
unsigned int output_device_read(void);
|
||||
void output_device_write(unsigned int value);
|
||||
|
||||
void int_controller_set(unsigned int value);
|
||||
void int_controller_clear(unsigned int value);
|
||||
|
||||
void get_user_input(void);
|
||||
|
||||
|
||||
/* Data */
|
||||
unsigned int g_quit = 0; /* 1 if we want to quit */
|
||||
unsigned int g_nmi = 0; /* 1 if nmi pending */
|
||||
|
||||
int g_input_device_value = -1; /* Current value in input device */
|
||||
|
||||
unsigned int g_output_device_ready = 0; /* 1 if output device is ready */
|
||||
time_t g_output_device_last_output; /* Time of last char output */
|
||||
|
||||
unsigned int g_int_controller_pending = 0; /* list of pending interrupts */
|
||||
unsigned int g_int_controller_highest_int = 0; /* Highest pending interrupt */
|
||||
|
||||
unsigned char g_rom[MAX_ROM+1]; /* ROM */
|
||||
unsigned char g_ram[MAX_RAM+1]; /* RAM */
|
||||
unsigned int g_fc; /* Current function code from CPU */
|
||||
|
||||
|
||||
/* Exit with an error message. Use printf syntax. */
|
||||
void exit_error(char* fmt, ...)
|
||||
{
|
||||
static int guard_val = 0;
|
||||
char buff[100];
|
||||
unsigned int pc;
|
||||
va_list args;
|
||||
|
||||
if(guard_val)
|
||||
return;
|
||||
else
|
||||
guard_val = 1;
|
||||
|
||||
va_start(args, fmt);
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
pc = m68k_get_reg(NULL, M68K_REG_PPC);
|
||||
m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);
|
||||
fprintf(stderr, "At %04x: %s\n", pc, buff);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
/* Read data from RAM, ROM, or a device */
|
||||
unsigned int cpu_read_byte(unsigned int address)
|
||||
{
|
||||
if(g_fc & 2) /* Program */
|
||||
{
|
||||
if(address > MAX_ROM)
|
||||
exit_error("Attempted to read byte from ROM address %08x", address);
|
||||
return READ_BYTE(g_rom, address);
|
||||
}
|
||||
|
||||
/* Otherwise it's data space */
|
||||
switch(address)
|
||||
{
|
||||
case INPUT_ADDRESS:
|
||||
return input_device_read();
|
||||
case OUTPUT_ADDRESS:
|
||||
return output_device_read();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(address > MAX_RAM)
|
||||
exit_error("Attempted to read byte from RAM address %08x", address);
|
||||
return READ_BYTE(g_ram, address);
|
||||
}
|
||||
|
||||
unsigned int cpu_read_word(unsigned int address)
|
||||
{
|
||||
if(g_fc & 2) /* Program */
|
||||
{
|
||||
if(address > MAX_ROM)
|
||||
exit_error("Attempted to read word from ROM address %08x", address);
|
||||
return READ_WORD(g_rom, address);
|
||||
}
|
||||
|
||||
/* Otherwise it's data space */
|
||||
switch(address)
|
||||
{
|
||||
case INPUT_ADDRESS:
|
||||
return input_device_read();
|
||||
case OUTPUT_ADDRESS:
|
||||
return output_device_read();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(address > MAX_RAM)
|
||||
exit_error("Attempted to read word from RAM address %08x", address);
|
||||
return READ_WORD(g_ram, address);
|
||||
}
|
||||
|
||||
unsigned int cpu_read_long(unsigned int address)
|
||||
{
|
||||
if(g_fc & 2) /* Program */
|
||||
{
|
||||
if(address > MAX_ROM)
|
||||
exit_error("Attempted to read long from ROM address %08x", address);
|
||||
return READ_LONG(g_rom, address);
|
||||
}
|
||||
|
||||
/* Otherwise it's data space */
|
||||
switch(address)
|
||||
{
|
||||
case INPUT_ADDRESS:
|
||||
return input_device_read();
|
||||
case OUTPUT_ADDRESS:
|
||||
return output_device_read();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(address > MAX_RAM)
|
||||
exit_error("Attempted to read long from RAM address %08x", address);
|
||||
return READ_LONG(g_ram, address);
|
||||
}
|
||||
|
||||
|
||||
unsigned int cpu_read_word_dasm(unsigned int address)
|
||||
{
|
||||
if(address > MAX_ROM)
|
||||
exit_error("Disassembler attempted to read word from ROM address %08x", address);
|
||||
return READ_WORD(g_rom, address);
|
||||
}
|
||||
|
||||
unsigned int cpu_read_long_dasm(unsigned int address)
|
||||
{
|
||||
if(address > MAX_ROM)
|
||||
exit_error("Dasm attempted to read long from ROM address %08x", address);
|
||||
return READ_LONG(g_rom, address);
|
||||
}
|
||||
|
||||
|
||||
/* Write data to RAM or a device */
|
||||
void cpu_write_byte(unsigned int address, unsigned int value)
|
||||
{
|
||||
if(g_fc & 2) /* Program */
|
||||
exit_error("Attempted to write %02x to ROM address %08x", value&0xff, address);
|
||||
|
||||
/* Otherwise it's data space */
|
||||
switch(address)
|
||||
{
|
||||
case INPUT_ADDRESS:
|
||||
input_device_write(value&0xff);
|
||||
return;
|
||||
case OUTPUT_ADDRESS:
|
||||
output_device_write(value&0xff);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(address > MAX_RAM)
|
||||
exit_error("Attempted to write %02x to RAM address %08x", value&0xff, address);
|
||||
WRITE_BYTE(g_ram, address, value);
|
||||
}
|
||||
|
||||
void cpu_write_word(unsigned int address, unsigned int value)
|
||||
{
|
||||
if(g_fc & 2) /* Program */
|
||||
exit_error("Attempted to write %04x to ROM address %08x", value&0xffff, address);
|
||||
|
||||
/* Otherwise it's data space */
|
||||
switch(address)
|
||||
{
|
||||
case INPUT_ADDRESS:
|
||||
input_device_write(value&0xffff);
|
||||
return;
|
||||
case OUTPUT_ADDRESS:
|
||||
output_device_write(value&0xffff);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(address > MAX_RAM)
|
||||
exit_error("Attempted to write %04x to RAM address %08x", value&0xffff, address);
|
||||
WRITE_WORD(g_ram, address, value);
|
||||
}
|
||||
|
||||
void cpu_write_long(unsigned int address, unsigned int value)
|
||||
{
|
||||
if(g_fc & 2) /* Program */
|
||||
exit_error("Attempted to write %08x to ROM address %08x", value, address);
|
||||
|
||||
/* Otherwise it's data space */
|
||||
switch(address)
|
||||
{
|
||||
case INPUT_ADDRESS:
|
||||
input_device_write(value);
|
||||
return;
|
||||
case OUTPUT_ADDRESS:
|
||||
output_device_write(value);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(address > MAX_RAM)
|
||||
exit_error("Attempted to write %08x to RAM address %08x", value, address);
|
||||
WRITE_LONG(g_ram, address, value);
|
||||
}
|
||||
|
||||
/* Called when the CPU pulses the RESET line */
|
||||
void cpu_pulse_reset(void)
|
||||
{
|
||||
nmi_device_reset();
|
||||
output_device_reset();
|
||||
input_device_reset();
|
||||
}
|
||||
|
||||
/* Called when the CPU changes the function code pins */
|
||||
void cpu_set_fc(unsigned int fc)
|
||||
{
|
||||
g_fc = fc;
|
||||
}
|
||||
|
||||
/* Called when the CPU acknowledges an interrupt */
|
||||
int cpu_irq_ack(int level)
|
||||
{
|
||||
switch(level)
|
||||
{
|
||||
case IRQ_NMI_DEVICE:
|
||||
return nmi_device_ack();
|
||||
case IRQ_INPUT_DEVICE:
|
||||
return input_device_ack();
|
||||
case IRQ_OUTPUT_DEVICE:
|
||||
return output_device_ack();
|
||||
}
|
||||
return M68K_INT_ACK_SPURIOUS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Implementation for the NMI device */
|
||||
void nmi_device_reset(void)
|
||||
{
|
||||
g_nmi = 0;
|
||||
}
|
||||
|
||||
void nmi_device_update(void)
|
||||
{
|
||||
if(g_nmi)
|
||||
{
|
||||
g_nmi = 0;
|
||||
int_controller_set(IRQ_NMI_DEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
int nmi_device_ack(void)
|
||||
{
|
||||
printf("\nNMI\n");fflush(stdout);
|
||||
int_controller_clear(IRQ_NMI_DEVICE);
|
||||
return M68K_INT_ACK_AUTOVECTOR;
|
||||
}
|
||||
|
||||
|
||||
/* Implementation for the input device */
|
||||
void input_device_reset(void)
|
||||
{
|
||||
g_input_device_value = -1;
|
||||
int_controller_clear(IRQ_INPUT_DEVICE);
|
||||
}
|
||||
|
||||
void input_device_update(void)
|
||||
{
|
||||
if(g_input_device_value >= 0)
|
||||
int_controller_set(IRQ_INPUT_DEVICE);
|
||||
}
|
||||
|
||||
int input_device_ack(void)
|
||||
{
|
||||
return M68K_INT_ACK_AUTOVECTOR;
|
||||
}
|
||||
|
||||
unsigned int input_device_read(void)
|
||||
{
|
||||
int value = g_input_device_value > 0 ? g_input_device_value : 0;
|
||||
int_controller_clear(IRQ_INPUT_DEVICE);
|
||||
g_input_device_value = -1;
|
||||
return value;
|
||||
}
|
||||
|
||||
void input_device_write(unsigned int value)
|
||||
{
|
||||
(void)value;
|
||||
}
|
||||
|
||||
|
||||
/* Implementation for the output device */
|
||||
void output_device_reset(void)
|
||||
{
|
||||
g_output_device_last_output = time(NULL);
|
||||
g_output_device_ready = 0;
|
||||
int_controller_clear(IRQ_OUTPUT_DEVICE);
|
||||
}
|
||||
|
||||
void output_device_update(void)
|
||||
{
|
||||
if(!g_output_device_ready)
|
||||
{
|
||||
if((time(NULL) - g_output_device_last_output) >= OUTPUT_DEVICE_PERIOD)
|
||||
{
|
||||
g_output_device_ready = 1;
|
||||
int_controller_set(IRQ_OUTPUT_DEVICE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int output_device_ack(void)
|
||||
{
|
||||
return M68K_INT_ACK_AUTOVECTOR;
|
||||
}
|
||||
|
||||
unsigned int output_device_read(void)
|
||||
{
|
||||
int_controller_clear(IRQ_OUTPUT_DEVICE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void output_device_write(unsigned int value)
|
||||
{
|
||||
char ch;
|
||||
if(g_output_device_ready)
|
||||
{
|
||||
ch = value & 0xff;
|
||||
printf("%c", ch);
|
||||
g_output_device_last_output = time(NULL);
|
||||
g_output_device_ready = 0;
|
||||
int_controller_clear(IRQ_OUTPUT_DEVICE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Implementation for the interrupt controller */
|
||||
void int_controller_set(unsigned int value)
|
||||
{
|
||||
unsigned int old_pending = g_int_controller_pending;
|
||||
|
||||
g_int_controller_pending |= (1<<value);
|
||||
|
||||
if(old_pending != g_int_controller_pending && value > g_int_controller_highest_int)
|
||||
{
|
||||
g_int_controller_highest_int = value;
|
||||
m68k_set_irq(g_int_controller_highest_int);
|
||||
}
|
||||
}
|
||||
|
||||
void int_controller_clear(unsigned int value)
|
||||
{
|
||||
g_int_controller_pending &= ~(1<<value);
|
||||
|
||||
for(g_int_controller_highest_int = 7;g_int_controller_highest_int > 0;g_int_controller_highest_int--)
|
||||
if(g_int_controller_pending & (1<<g_int_controller_highest_int))
|
||||
break;
|
||||
|
||||
m68k_set_irq(g_int_controller_highest_int);
|
||||
}
|
||||
|
||||
|
||||
/* Parse user input and update any devices that need user input */
|
||||
void get_user_input(void)
|
||||
{
|
||||
static int last_ch = -1;
|
||||
int ch = osd_get_char();
|
||||
|
||||
if(ch >= 0)
|
||||
{
|
||||
switch(ch)
|
||||
{
|
||||
case 0x1b:
|
||||
g_quit = 1;
|
||||
break;
|
||||
case '~':
|
||||
if(last_ch != ch)
|
||||
g_nmi = 1;
|
||||
break;
|
||||
default:
|
||||
g_input_device_value = ch;
|
||||
}
|
||||
}
|
||||
last_ch = ch;
|
||||
}
|
||||
|
||||
/* Disassembler */
|
||||
void make_hex(char* buff, unsigned int pc, unsigned int length)
|
||||
{
|
||||
char* ptr = buff;
|
||||
|
||||
for(;length>0;length -= 2)
|
||||
{
|
||||
sprintf(ptr, "%04x", cpu_read_word_dasm(pc));
|
||||
pc += 2;
|
||||
ptr += 4;
|
||||
if(length > 2)
|
||||
*ptr++ = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
void disassemble_program()
|
||||
{
|
||||
unsigned int pc;
|
||||
unsigned int instr_size;
|
||||
char buff[100];
|
||||
char buff2[100];
|
||||
|
||||
pc = cpu_read_long_dasm(4);
|
||||
|
||||
while(pc <= 0x16e)
|
||||
{
|
||||
instr_size = m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);
|
||||
make_hex(buff2, pc, instr_size);
|
||||
printf("%03x: %-20s: %s\n", pc, buff2, buff);
|
||||
pc += instr_size;
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void cpu_instr_callback(int pc)
|
||||
{
|
||||
(void)pc;
|
||||
/* The following code would print out instructions as they are executed */
|
||||
/*
|
||||
static char buff[100];
|
||||
static char buff2[100];
|
||||
static unsigned int pc;
|
||||
static unsigned int instr_size;
|
||||
|
||||
pc = m68k_get_reg(NULL, M68K_REG_PC);
|
||||
instr_size = m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);
|
||||
make_hex(buff2, pc, instr_size);
|
||||
printf("E %03x: %-20s: %s\n", pc, buff2, buff);
|
||||
fflush(stdout);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The main loop */
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
FILE* fhandle;
|
||||
|
||||
if(argc != 2)
|
||||
{
|
||||
printf("Usage: sim <program file>\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if((fhandle = fopen(argv[1], "rb")) == NULL)
|
||||
exit_error("Unable to open %s", argv[1]);
|
||||
|
||||
if(fread(g_rom, 1, MAX_ROM+1, fhandle) <= 0)
|
||||
exit_error("Error reading %s", argv[1]);
|
||||
|
||||
// disassemble_program();
|
||||
|
||||
m68k_init();
|
||||
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
|
||||
m68k_pulse_reset();
|
||||
input_device_reset();
|
||||
output_device_reset();
|
||||
nmi_device_reset();
|
||||
|
||||
g_quit = 0;
|
||||
while(!g_quit)
|
||||
{
|
||||
// Our loop requires some interleaving to allow us to update the
|
||||
// input, output, and nmi devices.
|
||||
|
||||
get_user_input();
|
||||
|
||||
// Values to execute determine the interleave rate.
|
||||
// Smaller values allow for more accurate interleaving with multiple
|
||||
// devices/CPUs but is more processor intensive.
|
||||
// 100000 is usually a good value to start at, then work from there.
|
||||
|
||||
// Note that I am not emulating the correct clock speed!
|
||||
m68k_execute(100000);
|
||||
output_device_update();
|
||||
input_device_update();
|
||||
nmi_device_update();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
#ifndef SIM__HEADER
|
||||
#define SIM__HEADER
|
||||
|
||||
unsigned int cpu_read_byte(unsigned int address);
|
||||
unsigned int cpu_read_word(unsigned int address);
|
||||
unsigned int cpu_read_long(unsigned int address);
|
||||
void cpu_write_byte(unsigned int address, unsigned int value);
|
||||
void cpu_write_word(unsigned int address, unsigned int value);
|
||||
void cpu_write_long(unsigned int address, unsigned int value);
|
||||
void cpu_pulse_reset(void);
|
||||
void cpu_set_fc(unsigned int fc);
|
||||
int cpu_irq_ack(int level);
|
||||
void cpu_instr_callback(int pc);
|
||||
|
||||
#endif /* SIM__HEADER */
|
@ -167,7 +167,7 @@ EMU_SRC = [
|
||||
'src/GLOBGLUE.c',
|
||||
'src/CFGMAN.c',
|
||||
'src/LANG/INTLCHAR.c',
|
||||
'src/tomlc99/toml.c'
|
||||
'lib/tomlc99/toml.c'
|
||||
]
|
||||
|
||||
EMU_INC = include_directories([
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tomlc99/toml.h"
|
||||
#include "lib/tomlc99/toml.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit c9f3f0091948af39e187559100d0c6c5f2f68ebc
|
Loading…
x
Reference in New Issue
Block a user