src/musashi/example/example.txt

Sat, 27 Nov 2010 01:13:12 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sat, 27 Nov 2010 01:13:12 +0000
changeset 0
8bf1bf91a36d
permissions
-rw-r--r--

initial commit

     1 EXAMPLE:
     2 -------
     3 As an example, I'll build an imaginary hardware platform.
     6 The system is fairly simple, comprising of a 000, an input device, an output
     7 device, a non-maskable-interrupt device, and an interrupt controller.
    10 The input device receives input from the user and asserts its interrupt
    11 request line until its value is read.  Reading from the input device's
    12 memory-mapped port will both clear its interrupt request and read an ASCII
    13 representation (8 bits) of what the user entered.
    15 The output device reads value when it is selected through its memory-mapped
    16 port and outputs it to a display.  The value it reads will be interpreted as
    17 an ASCII value and output to the display. The output device is fairly slow
    18 (it can only process 1 byte per second), and so it asserts its interrupt
    19 request line when it is ready to receive a byte.  Writing to the output device
    20 sends a byte to it.  If the output device is not ready, the write is ignored.
    21 Reading from the output device returns 0 and clears its interrupt request line
    22 until another byte is written to it and 1 second elapses.
    24 The non-maskable-interrupt (NMI) device, as can be surmised from the name,
    25 generates a non-maskable-interrupt.  This is connected to some kind of external
    26 switch that the user can push to generate a NMI.
    28 Since there are 3 devices interrupting the CPU, an interrupt controller is
    29 needed.  The interrupt controller takes 7 inputs and encodes the highest
    30 priority asserted line on the 3 output pins.  the input device is wired to IN2
    31 and the output device is wired to IN1 on the controller.  The NMI device is
    32 wired to IN7 and all the other inputs are wired low.
    34 The bus is also connected to a 1K ROM and a 256 byte RAM.
    35 Beware: This platform places ROM and RAM in the same address range and uses
    36         the FC pins to select the correct address space!
    37         (You didn't expect me to make it easy, did you? =)
    39 There are two ways to handle address spaces with Musashi:
    41 1. Enable M68K_SEPARATE_READS and make handler functions for immediate and
    42    pc-relative reads.
    44 2. Enable M68K_EMULATE_FC and make a callback function for function code
    45    changes.
    47 Both methods will work in this case, but I've opted for the "more correct"
    48 function code pin emulation for this example.
    52 Here is the schematic in all its ASCII splendour:
    53 -------------------------------------------------
    55      NMI     TIED
    56     SWITCH   LOW
    57       |       |
    58       | +-+-+-+
    59       | | | | | +------------------------------------------------+
    60       | | | | | | +------------------------------------+         |
    61       | | | | | | |                                    |         |
    62      +-------------+                                   |         |
    63      |7 6 5 4 3 2 1|                                   |         |
    64      |             |                                   |         |
    65      | INT CONTRLR |                                   |         |
    66      |             |                                   |         |
    67      |i i i        |                                   |         |
    68      |2 1 0        |                                   |         |
    69      +-------------+                                   |         |
    70       | | |                                            |         |
    71       | | |     +--------------------------------+--+  |         |
    72       o o o     |                                |  |  |         |
    73     +--------------+  +-------+  +----------+  +---------+  +----------+
    74     | I I I     a  |  |       |  |          |  | r  a  i |  |    i     |
    75     | 2 1 0    23  |  |       |  |          |  | e  c    |  |          |
    76     |              |  |       |  |          |  | a  k    |  |          |
    77     |              |  |       |  |          |  | d       |  |          |
    78     |              |  |       |  |          |  |         |  |          |
    79     |    M68000    |  |  ROM  |  |   RAM    |  |   IN    |  |   OUT    |
    80     |              |  |       |  |          |  |         |  |          |
    81     |            a9|--|a9     |--|          |--|         |--|          |
    82     |            a8|--|a8     |--|          |--|         |--|          |
    83     |            a7|--|a7     |--|a7        |--|         |--|          |
    84     |            a6|--|a6     |--|a6        |--|         |--|          |
    85     |            a5|--|a5     |--|a5        |--|         |--|          |
    86     |            a4|--|a4     |--|a4        |--|         |--|          |
    87     |            a3|--|a3     |--|a3        |--|         |--|          |
    88     |            a2|--|a2     |--|a2        |--|         |--|          |
    89     |            a1|--|a1     |--|a1        |--|         |--|          |
    90     |            a0|--|a0     |--|a0        |--|         |--|          |
    91     |              |  |       |  |          |  |         |  |          |
    92     |           d15|--|d15    |--|d15       |--|         |--|          |
    93     |           d14|--|d14    |--|d14       |--|         |--|          |
    94     |           d13|--|d13    |--|d13       |--|         |--|          |
    95     |           d12|--|d12    |--|d12       |--|         |--|          |
    96     |           d11|--|d11    |--|d11       |--|         |--|          |
    97     |           d10|--|d10    |--|d10       |--|         |--|          |
    98     |            d9|--|d9     |--|d9        |--|         |--|          |
    99     |            d8|--|d8     |--|d8        |--|         |--|          |
   100     |            d7|--|d7     |--|d7        |--|d7       |--|d7        |
   101     |            d6|--|d6     |--|d6        |--|d6       |--|d6        |
   102     |            d5|--|d5     |--|d5        |--|d5       |--|d5        |
   103     |            d4|--|d4     |--|d4        |--|d4       |--|d4        |
   104     |            d3|--|d3     |--|d3        |--|d3       |--|d3        |
   105     |            d2|--|d2     |--|d2        |--|d2       |--|d2        |
   106     |            d1|--|d1     |--|d1        |--|d1       |--|d1  w     |
   107     |            d0|--|d0     |--|d0        |--|d0       |--|d0  r     |
   108     |              |  |       |  |          |  |         |  |    i   a |
   109     | a      F F F |  |       |  |          |  |         |  |    t   c |
   110     |22  rW  2 1 0 |  |  cs   |  | cs   rW  |  |         |  |    e   k |
   111     +--------------+  +-------+  +----------+  +---------+  +----------+
   112       |   |  | | |        |         |    |                       |   |
   113       |   |  | | |        |         |    |                       |   |
   114       |   |  | | |    +-------+  +-----+ |                     +---+ |
   115       |   |  | | |    |  IC1  |  | IC2 | |                     |AND| |
   116       |   |  | | |    |a b c d|  |a b c| |                     +---+ |
   117       |   |  | | |    +-------+  +-----+ |                      | |  |
   118       |   |  | | |     | | | |    | | |  |                      | +--+
   119       |   |  | | |     | | | |    | | |  |                      | |
   120       |   |  | | |     | | | |    | | |  |                      | |
   121       |   |  | | |     | | | |    | | |  |                      | |
   122       |   |  | | +-----)-)-+-)----)-)-+  |                      | |
   123       |   |  | +-------)-+---)----)-+    |                      | |
   124       |   |  +---------+-----)----+      |                      | |
   125       |   |                  |           |                      | |
   126       |   +------------------+-----------+----------------------+ |
   127       |                                                           |
   128       +-----------------------------------------------------------+
   130 IC1: output=1 if a=0 and b=1 and c=0 and d=0
   131 IC2: output=1 if a=0 and b=0 and c=1
   135 Here is the listing for program.bin:
   136 -----------------------------------
   138                         INPUT_ADDRESS   equ $800000
   139                         OUTPUT_ADDRESS  equ $400000
   140                         CIRCULAR_BUFFER equ $c0
   141                         CAN_OUTPUT      equ $d0
   142                         STACK_AREA      equ $100
   144                         vector_table:
   145 00000000 0000 0100      	dc.l STACK_AREA				*  0: SP
   146 00000004 0000 00c0      	dc.l init					*  1: PC
   147 00000008 0000 0148      	dc.l unhandled_exception	*  2: bus error
   148 0000000c 0000 0148      	dc.l unhandled_exception	*  3: address error
   149 00000010 0000 0148      	dc.l unhandled_exception	*  4: illegal instruction
   150 00000014 0000 0148      	dc.l unhandled_exception	*  5: zero divide
   151 00000018 0000 0148      	dc.l unhandled_exception	*  6: chk
   152 0000001c 0000 0148      	dc.l unhandled_exception	*  7: trapv
   153 00000020 0000 0148      	dc.l unhandled_exception	*  8: privilege violation
   154 00000024 0000 0148      	dc.l unhandled_exception	*  9: trace
   155 00000028 0000 0148      	dc.l unhandled_exception	* 10: 1010
   156 0000002c 0000 0148      	dc.l unhandled_exception	* 11: 1111
   157 00000030 0000 0148      	dc.l unhandled_exception	* 12: -
   158 00000034 0000 0148      	dc.l unhandled_exception	* 13: -
   159 00000038 0000 0148      	dc.l unhandled_exception	* 14: -
   160 0000003c 0000 0148      	dc.l unhandled_exception	* 15: uninitialized interrupt
   161 00000040 0000 0148      	dc.l unhandled_exception	* 16: -
   162 00000044 0000 0148      	dc.l unhandled_exception	* 17: -
   163 00000048 0000 0148      	dc.l unhandled_exception	* 18: -
   164 0000004c 0000 0148      	dc.l unhandled_exception	* 19: -
   165 00000050 0000 0148      	dc.l unhandled_exception	* 20: -
   166 00000054 0000 0148      	dc.l unhandled_exception	* 21: -
   167 00000058 0000 0148      	dc.l unhandled_exception	* 22: -
   168 0000005c 0000 0148      	dc.l unhandled_exception	* 23: -
   169 00000060 0000 0148      	dc.l unhandled_exception	* 24: spurious interrupt
   170 00000064 0000 0136      	dc.l output_ready			* 25: l1 irq
   171 00000068 0000 010e      	dc.l input_ready			* 26: l2 irq
   172 0000006c 0000 0148      	dc.l unhandled_exception	* 27: l3 irq
   173 00000070 0000 0148      	dc.l unhandled_exception	* 28: l4 irq
   174 00000074 0000 0148      	dc.l unhandled_exception	* 29: l5 irq
   175 00000078 0000 0148      	dc.l unhandled_exception	* 30: l6 irq
   176 0000007c 0000 014e      	dc.l nmi					* 31: l7 irq
   177 00000080 0000 0148      	dc.l unhandled_exception	* 32: trap 0
   178 00000084 0000 0148      	dc.l unhandled_exception	* 33: trap 1
   179 00000088 0000 0148      	dc.l unhandled_exception	* 34: trap 2
   180 0000008c 0000 0148      	dc.l unhandled_exception	* 35: trap 3
   181 00000090 0000 0148      	dc.l unhandled_exception	* 36: trap 4
   182 00000094 0000 0148      	dc.l unhandled_exception	* 37: trap 5
   183 00000098 0000 0148      	dc.l unhandled_exception	* 38: trap 6
   184 0000009c 0000 0148      	dc.l unhandled_exception	* 39: trap 7
   185 000000a0 0000 0148      	dc.l unhandled_exception	* 40: trap 8
   186 000000a4 0000 0148      	dc.l unhandled_exception	* 41: trap 9
   187 000000a8 0000 0148      	dc.l unhandled_exception	* 42: trap 10
   188 000000ac 0000 0148      	dc.l unhandled_exception	* 43: trap 11
   189 000000b0 0000 0148      	dc.l unhandled_exception	* 44: trap 12
   190 000000b4 0000 0148      	dc.l unhandled_exception	* 45: trap 13
   191 000000b8 0000 0148      	dc.l unhandled_exception	* 46: trap 14
   192 000000bc 0000 0148      	dc.l unhandled_exception	* 47: trap 15
   193                         * This is the end of the useful part of the table.
   194                         * We will now do the Capcom thing and put code starting at $c0.
   196                         init:
   197                         * Copy the exception vector table to RAM.
   198 000000c0 227c 0000 0000 	move.l  #0, a1						* a1 is RAM index
   199 000000c6 303c 002f      	move.w  #47, d0						* d0 is counter (48 vectors)
   200 000000ca 41fa 0006      	lea.l   (copy_table,PC), a0			* a0 is scratch
   201 000000ce 2208           	move.l  a0, d1						* d1 is ROM index
   202 000000d0 4481           	neg.l   d1
   203                         copy_table:
   204 000000d2 22fb 18fe      	dc.l    $22fb18fe					* #%#$ as68k generates 020 code here
   205                         *	move.l  (copy_table,PC,d1.l), (a1)+
   206 000000d6 5841           	addq    #4, d1
   207 000000d8 51c8 fff8      	dbf     d0, copy_table
   209                         main_init:
   210                         * Initialize main program
   211 000000dc 11fc 0000 00d0 	move.b  #0, CAN_OUTPUT
   212 000000e2 4df8 00c0      	lea.l   CIRCULAR_BUFFER, a6
   213 000000e6 7c00           	moveq   #0, d6						* output buffer ptr
   214 000000e8 7e00           	moveq   #0, d7						* input buffer ptr
   215 000000ea 027c f8ff      	andi    #$f8ff, SR					* clear interrupt mask
   216                         main:
   217                         * Main program
   218 000000ee 4a38 00d0      	tst.b   CAN_OUTPUT					* can we output?
   219 000000f2 67fa           	beq     main
   220 000000f4 be06           	cmp.b   d6, d7						* is there data?
   221 000000f6 67f6           	beq     main
   222 000000f8 11fc 0000 00d0 	move.b  #0, CAN_OUTPUT
   223 000000fe 13f6 6000 0040 	move.b  (0,a6,d6.w), OUTPUT_ADDRESS	* write data
   224          0000
   225 00000106 5246           	addq    #1, d6
   226 00000108 0206 000f      	andi.b  #15, d6						* update circular buffer
   227 0000010c 60e0           	bra     main
   230                         input_ready:
   231 0000010e 2f00           	move.l  d0, -(a7)
   232 00000110 2f01           	move.l  d1, -(a7)
   233 00000112 1239 0080 0000 	move.b  INPUT_ADDRESS, d1			* read data
   234 00000118 1007           	move.b  d7, d0						* check if buffer full
   235 0000011a 5240           	addq    #1, d0
   236 0000011c 0200 000f      	andi.b  #15, d0
   237 00000120 bc00           	cmp.b   d0, d6
   238 00000122 6700 000c      	beq     input_ready_quit			* throw away if full
   239 00000126 1d81 7000      	move.b  d1, (0,a6,d7.w)				* store the data
   240 0000012a 5247           	addq    #1, d7
   241 0000012c 0207 000f      	andi.b  #15, d7						* update circular buffer
   242                         input_ready_quit:
   243 00000130 221f           	move.l  (a7)+, d1
   244 00000132 201f           	move.l  (a7)+, d0
   245 00000134 4e73           	rte
   247                         output_ready:
   248 00000136 2f00           	move.l  d0, -(a7)
   249 00000138 11fc 0001 00d0 	move.b  #1, CAN_OUTPUT
   250 0000013e 1039 0040 0000 	move.b  OUTPUT_ADDRESS, d0			* acknowledge the interrupt
   251 00000144 201f           	move.l  (a7)+, d0
   252 00000146 4e73           	rte
   254                         unhandled_exception:
   255 00000148 4e72 2700      	stop	#$2700						* wait for NMI
   256 0000014c 60fa           	bra     unhandled_exception			* shouldn't get here
   258                         nmi:
   259                         * perform a soft reset
   260 0000014e 46fc 2700      	move    #$2700, SR					* set status register
   261 00000152 2e7a feac      	move.l  (vector_table,PC), a7		* reset stack pointer
   262 00000156 4e70           	reset								* reset peripherals
   263 00000158 4efa feaa      	jmp     (vector_table+4,PC)			* reset program counter
   265                         END
   269 Compiling the example host environment:
   270 --------------------------------------
   272 The following assumes that you are using a GNU-based compiler such as gcc or
   273 djgpp for DOS (available free from www.delorie.com).
   274 If you are using a commercial compiler, you may have to modify the makefile
   275 or generate your own project file.
   276 Also note that part of the compilation process involves the compilation and
   277 invokation of the m68kmake program.
   279 - Copy the m68k files to a directory.  Then copy the host environment files to
   280   the same directory, overwriting m68kconf.h.  program.bin is the actual 68000
   281   program you will be running.
   282 - Modify osd_get_key() in sim.c to suit your environment (currently set for
   283   the free djgpp compiler, available from www.delorie.com, under DOS).
   284 - Type make
   285 - Perform the necessary animal sacrifices.
   286 - Type sim program.bin
   289 Keys:
   290 	ESC           - quits the simulator
   291 	~             - generates an NMI interrupt
   292 	Any other key - Genearate input for the input device
   295 Note: I've cheated a bit in the emulation.  There is no speed control
   296       to set the speed the CPU runs at; it simply runs as fast as your
   297       processor can run it.
   298       To add speed control, you will need a high-precision timestamp
   299       function (like the RDTSC instruction for newer Pentium CPUs)
   300       and a bit of arithmetic to make the cycles argument for m68k_execute().
   301       I'll leave that as an excercise to the reader.