hexed: add simple io commands
[megadrive.git] / hexed / transfer.S
1 ###############################################################################
2 #
3 # Copyright (c) 2011, GraÅžvydas Ignotas
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #     * Redistributions of source code must retain the above copyright
9 #       notice, this list of conditions and the following disclaimer.
10 #     * Redistributions in binary form must reproduce the above copyright
11 #       notice, this list of conditions and the following disclaimer in the
12 #       documentation and/or other materials provided with the distribution.
13 #     * Neither the name of the organization nor the
14 #       names of its contributors may be used to endorse or promote products
15 #       derived from this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND ANY
18 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 # DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY
21 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #
28 # Assemble with gas
29 #   --register-prefix-optional --bitwise-or
30 #
31
32 #include "transfer.h"
33
34 .text
35 .globl do_transfer
36
37
38 # receive 1 byte to d0
39 #  in: a1 - data port
40 #  trash: d1
41 .macro recv_one_byte is_last=0
42         move.b          #0,(a1)         /* clear TH */
43
44 0: /*L_wait_tl_low*/
45         move.b          (a1),d1
46         btst.b          #4,d1
47         bne             0b /*L_wait_tl_low*/
48
49         move.b          #0x40,(a1)      /* set TH */
50         and.b           #0x0f,d1
51
52 0: /*L_wait_tl_hi*/
53         move.b          (a1),d0
54         btst.b          #4,d0
55         beq             0b /*L_wait_tl_hi*/
56
57 .if !\is_last
58         move.b          #0,(a1)         /* clear TH - ready for next */
59 .endif
60         lsl.b           #4,d0
61         or.b            d1,d0
62 .endm
63
64 # send 1 byte in d0
65 #  in: a1 - data port
66 #  trash: d1,d2
67 .macro send_one_byte
68         move.b          d0,d2
69         and.b           #0x0f,d2
70
71 0: /*Lwait_tl_low:*/
72         move.b          (a1),d1
73         btst.b          #4,d1
74         bne             0b /*Lwait_tl_low*/
75
76         move.b          d2,(a1)         /* clears TH and writes data */
77
78         move.b          d0,d2
79         lsr.b           #4,d2
80         bset.b          #6,d2           /* prepare TH */
81
82 0: /*wait_tl_hi*/
83         move.b          (a1),d1
84         btst.b          #4,d1
85         beq             0b /*wait_tl_hi1*/
86
87         move.b          d2,(a1)
88 .endm
89
90 recv_byte:
91         moveq.l         #0,d0
92         recv_one_byte 1
93         rts
94
95 # receive address/size to d0 (3 bytes BE)
96 #  in: a1 - data port
97 #  trash: d1,d2
98 recv_ad:
99         moveq.l         #0,d2
100         bsr             recv_byte
101         move.b          d0,d2
102         bsr             recv_byte
103         lsl.l           #8,d2
104         move.b          d0,d2
105         bsr             recv_byte
106         lsl.l           #8,d2
107         move.b          d0,d2
108         move.l          d2,d0
109         rts
110
111 send_byte:
112         send_one_byte
113         rts
114
115
116 do_transfer:
117         lea             0xa10005,a1
118         move.b          #0x40,(0xa1000b).l      /* ctrl - all inputs except TH */
119         move.b          #0x00,(a1)
120
121         bsr             recv_byte
122         cmp.b           #CMD_PREFIX,d0
123         bne             return
124
125         bsr             recv_byte
126         cmp.b           #CMD_FIRST,d0
127         bcs             return
128         cmp.b           #CMD_LAST+1,d0
129         bcc             return
130         sub.b           #CMD_FIRST,d0
131
132         lsl.w           #2,d0
133         lea             (jumptab,pc,d0),a0
134         jmp             (a0)
135 jumptab:
136         bra             pcc_transfer_recv       /* sent to us */
137         bra             pcc_transfer_send       /* recv from us */
138         bra             pcc_jump
139         bra             pcc_io
140         bra             pcc_test_code
141
142
143 /* receive data from PC */
144 pcc_transfer_recv:
145         bsr             recv_ad
146         move.l          d0,a0
147         bsr             recv_ad
148         move.l          d0,d3
149
150 tr_recv_loop:
151         recv_one_byte
152         move.b          d0,(a0)+
153         subq.l          #1,d3
154         bgt             tr_recv_loop
155         bra             return
156
157
158 /* send data to PC */
159 pcc_transfer_send:
160         bsr             recv_ad
161         move.l          d0,a0
162         bsr             recv_ad
163         move.l          d0,d3
164
165 0: /*Lwait_tl_low: it should switch to rx mode before lowering tl */
166         move.b          (a1),d0
167         btst.b          #4,d0
168         bne             0b /*Lwait_tl_low*/
169
170         move.b          #0x4f,(0xa1000b).l
171         move.b          #0x40,(a1)
172
173 tr_send_loop:
174         move.b          (a0)+,d0
175         send_one_byte
176         subq.l          #1,d3
177         bgt             tr_send_loop
178         bra             return
179
180
181 /* call specified location */
182 pcc_jump:
183         bsr             recv_ad
184         move.l          d0,a0
185         jsr             (a0)
186         bra             return
187
188
189 /* do simple i/o commands */
190 pcc_io:
191         moveq.l         #0,d4
192         bsr             recv_byte
193         move.b          d0,d4
194         bsr             recv_byte
195         lsl.l           #8,d4
196         move.b          d0,d4
197
198 pcc_io_loop:
199         move.b          #0x40,(0xa1000b).l      /* input mode */
200
201         sub.w           #1,d4
202         bmi             return
203
204         bsr             recv_byte
205         move.b          d0,d3                   /* cmd */
206
207         bsr             recv_ad
208         move.l          d0,a2                   /* addr */
209
210         cmp.b           #IOSEQ_W32, d3
211         beq             pcc_io_w32
212         cmp.b           #IOSEQ_W16, d3
213         beq             pcc_io_w16
214         cmp.b           #IOSEQ_W8, d3
215         bne             pcc_io_rx
216
217 pcc_io_w8:
218         bsr             recv_byte
219         move.b          d0,(a2)
220         bra             pcc_io_loop
221
222 pcc_io_w16:
223         bsr             recv_byte
224         move.b          d0,d3
225         bsr             recv_byte
226         lsl.w           #8,d3
227         move.b          d0,d3
228         move.w          d3,(a2)
229         bra             pcc_io_loop
230
231 pcc_io_w32:
232         bsr             recv_byte
233         move.b          d0,d3
234         bsr             recv_byte
235         lsl.w           #8,d3
236         move.b          d0,d3
237         bsr             recv_byte
238         lsl.l           #8,d3
239         move.b          d0,d3
240         bsr             recv_byte
241         lsl.l           #8,d3
242         move.b          d0,d3
243         move.l          d3,(a2)
244         bra             pcc_io_loop
245
246 pcc_io_rx:
247 0: /*Lwait_tl_low:*/
248         move.b          (a1),d0
249         btst.b          #4,d0
250         bne             0b /*Lwait_tl_low*/
251
252         move.b          #0x4f,(0xa1000b).l
253         move.b          #0x40,(a1)
254
255         cmp.b           #IOSEQ_R32, d3
256         beq             pcc_io_r32
257         cmp.b           #IOSEQ_R16, d3
258         beq             pcc_io_r16
259         cmp.b           #IOSEQ_R8, d3
260         bne             return
261
262 pcc_io_r8:
263         move.b          (a2),d0
264         bsr             send_byte
265         bra             pcc_io_loop
266
267 pcc_io_r16:
268         move.w          (a2),d3
269         move.w          d3,d0
270         lsr.w           #8,d0
271         bsr             send_byte
272         move.b          d3,d0
273         bsr             send_byte
274         bra             pcc_io_loop
275
276 pcc_io_r32:
277         move.l          (a2),d3
278         move.l          d3,d0
279         swap            d0
280         lsr.l           #8,d0
281         bsr             send_byte
282         move.l          d3,d0
283         swap            d0
284         bsr             send_byte
285         move.w          d3,d0
286         lsr.w           #8,d0
287         bsr             send_byte
288         move.b          d3,d0
289         bsr             send_byte
290         bra             pcc_io_loop
291
292
293 /* some random code */
294 pcc_test_code:
295         bra             return
296
297
298
299 return:
300         move.b          #0,(0xa1000b).l /* all inputs */
301         move.l          #0xffe000,a1
302         move.l          d0,(a1)+        /* last state for debug */
303         move.l          d1,(a1)+
304         move.l          d2,(a1)+
305         move.l          d3,(a1)+
306         move.l          a0,(a1)+
307         bra             return_to_main
308
309
310 # vim:filetype=asmM68k