src/musashi/example/example.txt

changeset 0
8bf1bf91a36d
     1.1 diff -r 000000000000 -r 8bf1bf91a36d src/musashi/example/example.txt
     1.2 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 +++ b/src/musashi/example/example.txt	Sat Nov 27 01:13:12 2010 +0000
     1.4 @@ -0,0 +1,301 @@
     1.5 +EXAMPLE:
     1.6 +-------
     1.7 +As an example, I'll build an imaginary hardware platform.
     1.8 +
     1.9 +
    1.10 +The system is fairly simple, comprising of a 000, an input device, an output
    1.11 +device, a non-maskable-interrupt device, and an interrupt controller.
    1.12 +
    1.13 +
    1.14 +The input device receives input from the user and asserts its interrupt
    1.15 +request line until its value is read.  Reading from the input device's
    1.16 +memory-mapped port will both clear its interrupt request and read an ASCII
    1.17 +representation (8 bits) of what the user entered.
    1.18 +
    1.19 +The output device reads value when it is selected through its memory-mapped
    1.20 +port and outputs it to a display.  The value it reads will be interpreted as
    1.21 +an ASCII value and output to the display. The output device is fairly slow
    1.22 +(it can only process 1 byte per second), and so it asserts its interrupt
    1.23 +request line when it is ready to receive a byte.  Writing to the output device
    1.24 +sends a byte to it.  If the output device is not ready, the write is ignored.
    1.25 +Reading from the output device returns 0 and clears its interrupt request line
    1.26 +until another byte is written to it and 1 second elapses.
    1.27 +
    1.28 +The non-maskable-interrupt (NMI) device, as can be surmised from the name,
    1.29 +generates a non-maskable-interrupt.  This is connected to some kind of external
    1.30 +switch that the user can push to generate a NMI.
    1.31 +
    1.32 +Since there are 3 devices interrupting the CPU, an interrupt controller is
    1.33 +needed.  The interrupt controller takes 7 inputs and encodes the highest
    1.34 +priority asserted line on the 3 output pins.  the input device is wired to IN2
    1.35 +and the output device is wired to IN1 on the controller.  The NMI device is
    1.36 +wired to IN7 and all the other inputs are wired low.
    1.37 +
    1.38 +The bus is also connected to a 1K ROM and a 256 byte RAM.
    1.39 +Beware: This platform places ROM and RAM in the same address range and uses
    1.40 +        the FC pins to select the correct address space!
    1.41 +        (You didn't expect me to make it easy, did you? =)
    1.42 +
    1.43 +There are two ways to handle address spaces with Musashi:
    1.44 +
    1.45 +1. Enable M68K_SEPARATE_READS and make handler functions for immediate and
    1.46 +   pc-relative reads.
    1.47 +
    1.48 +2. Enable M68K_EMULATE_FC and make a callback function for function code
    1.49 +   changes.
    1.50 +
    1.51 +Both methods will work in this case, but I've opted for the "more correct"
    1.52 +function code pin emulation for this example.
    1.53 +
    1.54 +
    1.55 +
    1.56 +Here is the schematic in all its ASCII splendour:
    1.57 +-------------------------------------------------
    1.58 +
    1.59 +     NMI     TIED
    1.60 +    SWITCH   LOW
    1.61 +      |       |
    1.62 +      | +-+-+-+
    1.63 +      | | | | | +------------------------------------------------+
    1.64 +      | | | | | | +------------------------------------+         |
    1.65 +      | | | | | | |                                    |         |
    1.66 +     +-------------+                                   |         |
    1.67 +     |7 6 5 4 3 2 1|                                   |         |
    1.68 +     |             |                                   |         |
    1.69 +     | INT CONTRLR |                                   |         |
    1.70 +     |             |                                   |         |
    1.71 +     |i i i        |                                   |         |
    1.72 +     |2 1 0        |                                   |         |
    1.73 +     +-------------+                                   |         |
    1.74 +      | | |                                            |         |
    1.75 +      | | |     +--------------------------------+--+  |         |
    1.76 +      o o o     |                                |  |  |         |
    1.77 +    +--------------+  +-------+  +----------+  +---------+  +----------+
    1.78 +    | I I I     a  |  |       |  |          |  | r  a  i |  |    i     |
    1.79 +    | 2 1 0    23  |  |       |  |          |  | e  c    |  |          |
    1.80 +    |              |  |       |  |          |  | a  k    |  |          |
    1.81 +    |              |  |       |  |          |  | d       |  |          |
    1.82 +    |              |  |       |  |          |  |         |  |          |
    1.83 +    |    M68000    |  |  ROM  |  |   RAM    |  |   IN    |  |   OUT    |
    1.84 +    |              |  |       |  |          |  |         |  |          |
    1.85 +    |            a9|--|a9     |--|          |--|         |--|          |
    1.86 +    |            a8|--|a8     |--|          |--|         |--|          |
    1.87 +    |            a7|--|a7     |--|a7        |--|         |--|          |
    1.88 +    |            a6|--|a6     |--|a6        |--|         |--|          |
    1.89 +    |            a5|--|a5     |--|a5        |--|         |--|          |
    1.90 +    |            a4|--|a4     |--|a4        |--|         |--|          |
    1.91 +    |            a3|--|a3     |--|a3        |--|         |--|          |
    1.92 +    |            a2|--|a2     |--|a2        |--|         |--|          |
    1.93 +    |            a1|--|a1     |--|a1        |--|         |--|          |
    1.94 +    |            a0|--|a0     |--|a0        |--|         |--|          |
    1.95 +    |              |  |       |  |          |  |         |  |          |
    1.96 +    |           d15|--|d15    |--|d15       |--|         |--|          |
    1.97 +    |           d14|--|d14    |--|d14       |--|         |--|          |
    1.98 +    |           d13|--|d13    |--|d13       |--|         |--|          |
    1.99 +    |           d12|--|d12    |--|d12       |--|         |--|          |
   1.100 +    |           d11|--|d11    |--|d11       |--|         |--|          |
   1.101 +    |           d10|--|d10    |--|d10       |--|         |--|          |
   1.102 +    |            d9|--|d9     |--|d9        |--|         |--|          |
   1.103 +    |            d8|--|d8     |--|d8        |--|         |--|          |
   1.104 +    |            d7|--|d7     |--|d7        |--|d7       |--|d7        |
   1.105 +    |            d6|--|d6     |--|d6        |--|d6       |--|d6        |
   1.106 +    |            d5|--|d5     |--|d5        |--|d5       |--|d5        |
   1.107 +    |            d4|--|d4     |--|d4        |--|d4       |--|d4        |
   1.108 +    |            d3|--|d3     |--|d3        |--|d3       |--|d3        |
   1.109 +    |            d2|--|d2     |--|d2        |--|d2       |--|d2        |
   1.110 +    |            d1|--|d1     |--|d1        |--|d1       |--|d1  w     |
   1.111 +    |            d0|--|d0     |--|d0        |--|d0       |--|d0  r     |
   1.112 +    |              |  |       |  |          |  |         |  |    i   a |
   1.113 +    | a      F F F |  |       |  |          |  |         |  |    t   c |
   1.114 +    |22  rW  2 1 0 |  |  cs   |  | cs   rW  |  |         |  |    e   k |
   1.115 +    +--------------+  +-------+  +----------+  +---------+  +----------+
   1.116 +      |   |  | | |        |         |    |                       |   |
   1.117 +      |   |  | | |        |         |    |                       |   |
   1.118 +      |   |  | | |    +-------+  +-----+ |                     +---+ |
   1.119 +      |   |  | | |    |  IC1  |  | IC2 | |                     |AND| |
   1.120 +      |   |  | | |    |a b c d|  |a b c| |                     +---+ |
   1.121 +      |   |  | | |    +-------+  +-----+ |                      | |  |
   1.122 +      |   |  | | |     | | | |    | | |  |                      | +--+
   1.123 +      |   |  | | |     | | | |    | | |  |                      | |
   1.124 +      |   |  | | |     | | | |    | | |  |                      | |
   1.125 +      |   |  | | |     | | | |    | | |  |                      | |
   1.126 +      |   |  | | +-----)-)-+-)----)-)-+  |                      | |
   1.127 +      |   |  | +-------)-+---)----)-+    |                      | |
   1.128 +      |   |  +---------+-----)----+      |                      | |
   1.129 +      |   |                  |           |                      | |
   1.130 +      |   +------------------+-----------+----------------------+ |
   1.131 +      |                                                           |
   1.132 +      +-----------------------------------------------------------+
   1.133 +
   1.134 +IC1: output=1 if a=0 and b=1 and c=0 and d=0
   1.135 +IC2: output=1 if a=0 and b=0 and c=1
   1.136 +
   1.137 +
   1.138 +
   1.139 +Here is the listing for program.bin:
   1.140 +-----------------------------------
   1.141 +
   1.142 +                        INPUT_ADDRESS   equ $800000
   1.143 +                        OUTPUT_ADDRESS  equ $400000
   1.144 +                        CIRCULAR_BUFFER equ $c0
   1.145 +                        CAN_OUTPUT      equ $d0
   1.146 +                        STACK_AREA      equ $100
   1.147 +                        
   1.148 +                        vector_table:
   1.149 +00000000 0000 0100      	dc.l STACK_AREA				*  0: SP
   1.150 +00000004 0000 00c0      	dc.l init					*  1: PC
   1.151 +00000008 0000 0148      	dc.l unhandled_exception	*  2: bus error
   1.152 +0000000c 0000 0148      	dc.l unhandled_exception	*  3: address error
   1.153 +00000010 0000 0148      	dc.l unhandled_exception	*  4: illegal instruction
   1.154 +00000014 0000 0148      	dc.l unhandled_exception	*  5: zero divide
   1.155 +00000018 0000 0148      	dc.l unhandled_exception	*  6: chk
   1.156 +0000001c 0000 0148      	dc.l unhandled_exception	*  7: trapv
   1.157 +00000020 0000 0148      	dc.l unhandled_exception	*  8: privilege violation
   1.158 +00000024 0000 0148      	dc.l unhandled_exception	*  9: trace
   1.159 +00000028 0000 0148      	dc.l unhandled_exception	* 10: 1010
   1.160 +0000002c 0000 0148      	dc.l unhandled_exception	* 11: 1111
   1.161 +00000030 0000 0148      	dc.l unhandled_exception	* 12: -
   1.162 +00000034 0000 0148      	dc.l unhandled_exception	* 13: -
   1.163 +00000038 0000 0148      	dc.l unhandled_exception	* 14: -
   1.164 +0000003c 0000 0148      	dc.l unhandled_exception	* 15: uninitialized interrupt
   1.165 +00000040 0000 0148      	dc.l unhandled_exception	* 16: -
   1.166 +00000044 0000 0148      	dc.l unhandled_exception	* 17: -
   1.167 +00000048 0000 0148      	dc.l unhandled_exception	* 18: -
   1.168 +0000004c 0000 0148      	dc.l unhandled_exception	* 19: -
   1.169 +00000050 0000 0148      	dc.l unhandled_exception	* 20: -
   1.170 +00000054 0000 0148      	dc.l unhandled_exception	* 21: -
   1.171 +00000058 0000 0148      	dc.l unhandled_exception	* 22: -
   1.172 +0000005c 0000 0148      	dc.l unhandled_exception	* 23: -
   1.173 +00000060 0000 0148      	dc.l unhandled_exception	* 24: spurious interrupt
   1.174 +00000064 0000 0136      	dc.l output_ready			* 25: l1 irq
   1.175 +00000068 0000 010e      	dc.l input_ready			* 26: l2 irq
   1.176 +0000006c 0000 0148      	dc.l unhandled_exception	* 27: l3 irq
   1.177 +00000070 0000 0148      	dc.l unhandled_exception	* 28: l4 irq
   1.178 +00000074 0000 0148      	dc.l unhandled_exception	* 29: l5 irq
   1.179 +00000078 0000 0148      	dc.l unhandled_exception	* 30: l6 irq
   1.180 +0000007c 0000 014e      	dc.l nmi					* 31: l7 irq
   1.181 +00000080 0000 0148      	dc.l unhandled_exception	* 32: trap 0
   1.182 +00000084 0000 0148      	dc.l unhandled_exception	* 33: trap 1
   1.183 +00000088 0000 0148      	dc.l unhandled_exception	* 34: trap 2
   1.184 +0000008c 0000 0148      	dc.l unhandled_exception	* 35: trap 3
   1.185 +00000090 0000 0148      	dc.l unhandled_exception	* 36: trap 4
   1.186 +00000094 0000 0148      	dc.l unhandled_exception	* 37: trap 5
   1.187 +00000098 0000 0148      	dc.l unhandled_exception	* 38: trap 6
   1.188 +0000009c 0000 0148      	dc.l unhandled_exception	* 39: trap 7
   1.189 +000000a0 0000 0148      	dc.l unhandled_exception	* 40: trap 8
   1.190 +000000a4 0000 0148      	dc.l unhandled_exception	* 41: trap 9
   1.191 +000000a8 0000 0148      	dc.l unhandled_exception	* 42: trap 10
   1.192 +000000ac 0000 0148      	dc.l unhandled_exception	* 43: trap 11
   1.193 +000000b0 0000 0148      	dc.l unhandled_exception	* 44: trap 12
   1.194 +000000b4 0000 0148      	dc.l unhandled_exception	* 45: trap 13
   1.195 +000000b8 0000 0148      	dc.l unhandled_exception	* 46: trap 14
   1.196 +000000bc 0000 0148      	dc.l unhandled_exception	* 47: trap 15
   1.197 +                        * This is the end of the useful part of the table.
   1.198 +                        * We will now do the Capcom thing and put code starting at $c0.
   1.199 +                        
   1.200 +                        init:
   1.201 +                        * Copy the exception vector table to RAM.
   1.202 +000000c0 227c 0000 0000 	move.l  #0, a1						* a1 is RAM index
   1.203 +000000c6 303c 002f      	move.w  #47, d0						* d0 is counter (48 vectors)
   1.204 +000000ca 41fa 0006      	lea.l   (copy_table,PC), a0			* a0 is scratch
   1.205 +000000ce 2208           	move.l  a0, d1						* d1 is ROM index
   1.206 +000000d0 4481           	neg.l   d1
   1.207 +                        copy_table:
   1.208 +000000d2 22fb 18fe      	dc.l    $22fb18fe					* #%#$ as68k generates 020 code here
   1.209 +                        *	move.l  (copy_table,PC,d1.l), (a1)+
   1.210 +000000d6 5841           	addq    #4, d1
   1.211 +000000d8 51c8 fff8      	dbf     d0, copy_table
   1.212 +                        
   1.213 +                        main_init:
   1.214 +                        * Initialize main program
   1.215 +000000dc 11fc 0000 00d0 	move.b  #0, CAN_OUTPUT
   1.216 +000000e2 4df8 00c0      	lea.l   CIRCULAR_BUFFER, a6
   1.217 +000000e6 7c00           	moveq   #0, d6						* output buffer ptr
   1.218 +000000e8 7e00           	moveq   #0, d7						* input buffer ptr
   1.219 +000000ea 027c f8ff      	andi    #$f8ff, SR					* clear interrupt mask
   1.220 +                        main:
   1.221 +                        * Main program
   1.222 +000000ee 4a38 00d0      	tst.b   CAN_OUTPUT					* can we output?
   1.223 +000000f2 67fa           	beq     main
   1.224 +000000f4 be06           	cmp.b   d6, d7						* is there data?
   1.225 +000000f6 67f6           	beq     main
   1.226 +000000f8 11fc 0000 00d0 	move.b  #0, CAN_OUTPUT
   1.227 +000000fe 13f6 6000 0040 	move.b  (0,a6,d6.w), OUTPUT_ADDRESS	* write data
   1.228 +         0000
   1.229 +00000106 5246           	addq    #1, d6
   1.230 +00000108 0206 000f      	andi.b  #15, d6						* update circular buffer
   1.231 +0000010c 60e0           	bra     main
   1.232 +                        
   1.233 +                        
   1.234 +                        input_ready:
   1.235 +0000010e 2f00           	move.l  d0, -(a7)
   1.236 +00000110 2f01           	move.l  d1, -(a7)
   1.237 +00000112 1239 0080 0000 	move.b  INPUT_ADDRESS, d1			* read data
   1.238 +00000118 1007           	move.b  d7, d0						* check if buffer full
   1.239 +0000011a 5240           	addq    #1, d0
   1.240 +0000011c 0200 000f      	andi.b  #15, d0
   1.241 +00000120 bc00           	cmp.b   d0, d6
   1.242 +00000122 6700 000c      	beq     input_ready_quit			* throw away if full
   1.243 +00000126 1d81 7000      	move.b  d1, (0,a6,d7.w)				* store the data
   1.244 +0000012a 5247           	addq    #1, d7
   1.245 +0000012c 0207 000f      	andi.b  #15, d7						* update circular buffer
   1.246 +                        input_ready_quit:
   1.247 +00000130 221f           	move.l  (a7)+, d1
   1.248 +00000132 201f           	move.l  (a7)+, d0
   1.249 +00000134 4e73           	rte
   1.250 +                        
   1.251 +                        output_ready:
   1.252 +00000136 2f00           	move.l  d0, -(a7)
   1.253 +00000138 11fc 0001 00d0 	move.b  #1, CAN_OUTPUT
   1.254 +0000013e 1039 0040 0000 	move.b  OUTPUT_ADDRESS, d0			* acknowledge the interrupt
   1.255 +00000144 201f           	move.l  (a7)+, d0
   1.256 +00000146 4e73           	rte
   1.257 +                        
   1.258 +                        unhandled_exception:
   1.259 +00000148 4e72 2700      	stop	#$2700						* wait for NMI
   1.260 +0000014c 60fa           	bra     unhandled_exception			* shouldn't get here
   1.261 +                        
   1.262 +                        nmi:
   1.263 +                        * perform a soft reset
   1.264 +0000014e 46fc 2700      	move    #$2700, SR					* set status register
   1.265 +00000152 2e7a feac      	move.l  (vector_table,PC), a7		* reset stack pointer
   1.266 +00000156 4e70           	reset								* reset peripherals
   1.267 +00000158 4efa feaa      	jmp     (vector_table+4,PC)			* reset program counter
   1.268 +                        
   1.269 +                        END
   1.270 +
   1.271 +
   1.272 +
   1.273 +Compiling the example host environment:
   1.274 +--------------------------------------
   1.275 +
   1.276 +The following assumes that you are using a GNU-based compiler such as gcc or
   1.277 +djgpp for DOS (available free from www.delorie.com).
   1.278 +If you are using a commercial compiler, you may have to modify the makefile
   1.279 +or generate your own project file.
   1.280 +Also note that part of the compilation process involves the compilation and
   1.281 +invokation of the m68kmake program.
   1.282 +
   1.283 +- Copy the m68k files to a directory.  Then copy the host environment files to
   1.284 +  the same directory, overwriting m68kconf.h.  program.bin is the actual 68000
   1.285 +  program you will be running.
   1.286 +- Modify osd_get_key() in sim.c to suit your environment (currently set for
   1.287 +  the free djgpp compiler, available from www.delorie.com, under DOS).
   1.288 +- Type make
   1.289 +- Perform the necessary animal sacrifices.
   1.290 +- Type sim program.bin
   1.291 +
   1.292 +
   1.293 +Keys:
   1.294 +	ESC           - quits the simulator
   1.295 +	~             - generates an NMI interrupt
   1.296 +	Any other key - Genearate input for the input device
   1.297 +
   1.298 +
   1.299 +Note: I've cheated a bit in the emulation.  There is no speed control
   1.300 +      to set the speed the CPU runs at; it simply runs as fast as your
   1.301 +      processor can run it.
   1.302 +      To add speed control, you will need a high-precision timestamp
   1.303 +      function (like the RDTSC instruction for newer Pentium CPUs)
   1.304 +      and a bit of arithmetic to make the cycles argument for m68k_execute().
   1.305 +      I'll leave that as an excercise to the reader.