1 | |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
2 | |MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP |
3 | |M68000 Hi-Performance Microprocessor Division |
4 | |M68060 Software Package |
5 | |Production Release P1.00 -- October 10, 1994 |
6 | | |
7 | |M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved. |
8 | | |
9 | |THE SOFTWARE is provided on an "AS IS" basis and without warranty. |
10 | |To the maximum extent permitted by applicable law, |
11 | |MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, |
12 | |INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE |
13 | |and any warranty against infringement with regard to the SOFTWARE |
14 | |(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials. |
15 | | |
16 | |To the maximum extent permitted by applicable law, |
17 | |IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER |
18 | |(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, |
19 | |BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) |
20 | |ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE. |
21 | |Motorola assumes no responsibility for the maintenance and support of the SOFTWARE. |
22 | | |
23 | |You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE |
24 | |so long as this entire notice is retained without alteration in any modified and/or |
25 | |redistributed versions, and that such modified versions are clearly identified as such. |
26 | |No licenses are granted by implication, estoppel or otherwise under any patents |
27 | |or trademarks of Motorola, Inc. |
28 | |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
29 | | os.s |
30 | | |
31 | | This file contains: |
32 | | - example "Call-Out" s required by both the ISP and FPSP. |
33 | | |
34 | |
35 | #include <linux/linkage.h> |
36 | |
37 | |################################ |
38 | | EXAMPLE CALL-OUTS # |
39 | | # |
40 | | _060_dmem_write() # |
41 | | _060_dmem_read() # |
42 | | _060_imem_read() # |
43 | | _060_dmem_read_byte() # |
44 | | _060_dmem_read_word() # |
45 | | _060_dmem_read_long() # |
46 | | _060_imem_read_word() # |
47 | | _060_imem_read_long() # |
48 | | _060_dmem_write_byte() # |
49 | | _060_dmem_write_word() # |
50 | | _060_dmem_write_long() # |
51 | | # |
52 | | _060_real_trace() # |
53 | | _060_real_access() # |
54 | |################################ |
55 | |
56 | | |
57 | | Each IO routine checks to see if the memory write/read is to/from user |
58 | | or supervisor application space. The examples below use simple "move" |
59 | | instructions for supervisor mode applications and call _copyin()/_copyout() |
60 | | for user mode applications. |
61 | | When installing the 060SP, the _copyin()/_copyout() equivalents for a |
62 | | given operating system should be substituted. |
63 | | |
64 | | The addresses within the 060SP are guaranteed to be on the stack. |
65 | | The result is that Unix processes are allowed to sleep as a consequence |
66 | | of a page fault during a _copyout. |
67 | | |
68 | | Linux/68k: The _060_[id]mem_{read,write}_{byte,word,long} functions |
69 | | (i.e. all the known length <= 4) are implemented by single moves |
70 | | statements instead of (more expensive) copy{in,out} calls, if |
71 | | working in user space |
72 | |
73 | | |
74 | | _060_dmem_write(): |
75 | | |
76 | | Writes to data memory while in supervisor mode. |
77 | | |
78 | | INPUTS: |
79 | | a0 - supervisor source address |
80 | | a1 - user destination address |
81 | | d0 - number of bytes to write |
82 | | 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode |
83 | | OUTPUTS: |
84 | | d1 - 0 = success, !0 = failure |
85 | | |
86 | .global _060_dmem_write |
87 | _060_dmem_write: |
88 | subq.l #1,%d0 |
89 | btst #0x5,0x4(%a6) | check for supervisor state |
90 | beqs user_write |
91 | super_write: |
92 | move.b (%a0)+,(%a1)+ | copy 1 byte |
93 | dbra %d0,super_write | quit if --ctr < 0 |
94 | clr.l %d1 | return success |
95 | rts |
96 | user_write: |
97 | move.b (%a0)+,%d1 | copy 1 byte |
98 | copyoutae: |
99 | movs.b %d1,(%a1)+ |
100 | dbra %d0,user_write | quit if --ctr < 0 |
101 | clr.l %d1 | return success |
102 | rts |
103 | |
104 | | |
105 | | _060_imem_read(), _060_dmem_read(): |
106 | | |
107 | | Reads from data/instruction memory while in supervisor mode. |
108 | | |
109 | | INPUTS: |
110 | | a0 - user source address |
111 | | a1 - supervisor destination address |
112 | | d0 - number of bytes to read |
113 | | 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode |
114 | | OUTPUTS: |
115 | | d1 - 0 = success, !0 = failure |
116 | | |
117 | .global _060_imem_read |
118 | .global _060_dmem_read |
119 | _060_imem_read: |
120 | _060_dmem_read: |
121 | subq.l #1,%d0 |
122 | btst #0x5,0x4(%a6) | check for supervisor state |
123 | beqs user_read |
124 | super_read: |
125 | move.b (%a0)+,(%a1)+ | copy 1 byte |
126 | dbra %d0,super_read | quit if --ctr < 0 |
127 | clr.l %d1 | return success |
128 | rts |
129 | user_read: |
130 | copyinae: |
131 | movs.b (%a0)+,%d1 |
132 | move.b %d1,(%a1)+ | copy 1 byte |
133 | dbra %d0,user_read | quit if --ctr < 0 |
134 | clr.l %d1 | return success |
135 | rts |
136 | |
137 | | |
138 | | _060_dmem_read_byte(): |
139 | | |
140 | | Read a data byte from user memory. |
141 | | |
142 | | INPUTS: |
143 | | a0 - user source address |
144 | | 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode |
145 | | OUTPUTS: |
146 | | d0 - data byte in d0 |
147 | | d1 - 0 = success, !0 = failure |
148 | | |
149 | .global _060_dmem_read_byte |
150 | _060_dmem_read_byte: |
151 | clr.l %d0 | clear whole longword |
152 | clr.l %d1 | assume success |
153 | btst #0x5,0x4(%a6) | check for supervisor state |
154 | bnes dmrbs | supervisor |
155 | dmrbuae:movs.b (%a0),%d0 | fetch user byte |
156 | rts |
157 | dmrbs: move.b (%a0),%d0 | fetch super byte |
158 | rts |
159 | |
160 | | |
161 | | _060_dmem_read_word(): |
162 | | |
163 | | Read a data word from user memory. |
164 | | |
165 | | INPUTS: |
166 | | a0 - user source address |
167 | | 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode |
168 | | OUTPUTS: |
169 | | d0 - data word in d0 |
170 | | d1 - 0 = success, !0 = failure |
171 | | |
172 | | _060_imem_read_word(): |
173 | | |
174 | | Read an instruction word from user memory. |
175 | | |
176 | | INPUTS: |
177 | | a0 - user source address |
178 | | 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode |
179 | | OUTPUTS: |
180 | | d0 - instruction word in d0 |
181 | | d1 - 0 = success, !0 = failure |
182 | | |
183 | .global _060_dmem_read_word |
184 | .global _060_imem_read_word |
185 | _060_dmem_read_word: |
186 | _060_imem_read_word: |
187 | clr.l %d1 | assume success |
188 | clr.l %d0 | clear whole longword |
189 | btst #0x5,0x4(%a6) | check for supervisor state |
190 | bnes dmrws | supervisor |
191 | dmrwuae:movs.w (%a0), %d0 | fetch user word |
192 | rts |
193 | dmrws: move.w (%a0), %d0 | fetch super word |
194 | rts |
195 | |
196 | | |
197 | | _060_dmem_read_long(): |
198 | | |
199 | |
200 | | |
201 | | INPUTS: |
202 | | a0 - user source address |
203 | | 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode |
204 | | OUTPUTS: |
205 | | d0 - data longword in d0 |
206 | | d1 - 0 = success, !0 = failure |
207 | | |
208 | | _060_imem_read_long(): |
209 | | |
210 | | Read an instruction longword from user memory. |
211 | | |
212 | | INPUTS: |
213 | | a0 - user source address |
214 | | 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode |
215 | | OUTPUTS: |
216 | | d0 - instruction longword in d0 |
217 | | d1 - 0 = success, !0 = failure |
218 | | |
219 | .global _060_dmem_read_long |
220 | .global _060_imem_read_long |
221 | _060_dmem_read_long: |
222 | _060_imem_read_long: |
223 | clr.l %d1 | assume success |
224 | btst #0x5,0x4(%a6) | check for supervisor state |
225 | bnes dmrls | supervisor |
226 | dmrluae:movs.l (%a0),%d0 | fetch user longword |
227 | rts |
228 | dmrls: move.l (%a0),%d0 | fetch super longword |
229 | rts |
230 | |
231 | | |
232 | | _060_dmem_write_byte(): |
233 | | |
234 | | Write a data byte to user memory. |
235 | | |
236 | | INPUTS: |
237 | | a0 - user destination address |
238 | | d0 - data byte in d0 |
239 | | 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode |
240 | | OUTPUTS: |
241 | | d1 - 0 = success, !0 = failure |
242 | | |
243 | .global _060_dmem_write_byte |
244 | _060_dmem_write_byte: |
245 | clr.l %d1 | assume success |
246 | btst #0x5,0x4(%a6) | check for supervisor state |
247 | bnes dmwbs | supervisor |
248 | dmwbuae:movs.b %d0,(%a0) | store user byte |
249 | rts |
250 | dmwbs: move.b %d0,(%a0) | store super byte |
251 | rts |
252 | |
253 | | |
254 | | _060_dmem_write_word(): |
255 | | |
256 | | Write a data word to user memory. |
257 | | |
258 | | INPUTS: |
259 | | a0 - user destination address |
260 | | d0 - data word in d0 |
261 | | 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode |
262 | | OUTPUTS: |
263 | | d1 - 0 = success, !0 = failure |
264 | | |
265 | .global _060_dmem_write_word |
266 | _060_dmem_write_word: |
267 | clr.l %d1 | assume success |
268 | btst #0x5,0x4(%a6) | check for supervisor state |
269 | bnes dmwws | supervisor |
270 | dmwwu: |
271 | dmwwuae:movs.w %d0,(%a0) | store user word |
272 | bras dmwwr |
273 | dmwws: move.w %d0,(%a0) | store super word |
274 | dmwwr: clr.l %d1 | return success |
275 | rts |
276 | |
277 | | |
278 | | _060_dmem_write_long(): |
279 | | |
280 | | Write a data longword to user memory. |
281 | | |
282 | | INPUTS: |
283 | | a0 - user destination address |
284 | | d0 - data longword in d0 |
285 | | 0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode |
286 | | OUTPUTS: |
287 | | d1 - 0 = success, !0 = failure |
288 | | |
289 | .global _060_dmem_write_long |
290 | _060_dmem_write_long: |
291 | clr.l %d1 | assume success |
292 | btst #0x5,0x4(%a6) | check for supervisor state |
293 | bnes dmwls | supervisor |
294 | dmwluae:movs.l %d0,(%a0) | store user longword |
295 | rts |
296 | dmwls: move.l %d0,(%a0) | store super longword |
297 | rts |
298 | |
299 | |
300 | #if 0 |
301 | |############################################### |
302 | |
303 | | |
304 | | Use these routines if your kernel doesn't have _copyout/_copyin equivalents. |
305 | | Assumes that D0/D1/A0/A1 are scratch registers. The _copyin/_copyout |
306 | | below assume that the SFC/DFC have been set previously. |
307 | | |
308 | | Linux/68k: These are basically non-inlined versions of |
309 | | memcpy_{to,from}fs, but without long-transfer optimization |
310 | | Note: Assumed that SFC/DFC are pointing correctly to user data |
311 | | space... Should be right, or are there any exceptions? |
312 | |
313 | | |
314 | | int _copyout(supervisor_addr, user_addr, nbytes) |
315 | | |
316 | .global _copyout |
317 | _copyout: |
318 | move.l 4(%sp),%a0 | source |
319 | move.l 8(%sp),%a1 | destination |
320 | move.l 12(%sp),%d0 | count |
321 | subq.l #1,%d0 |
322 | moreout: |
323 | move.b (%a0)+,%d1 | fetch supervisor byte |
324 | copyoutae: |
325 | movs.b %d1,(%a1)+ | store user byte |
326 | dbra %d0,moreout | are we through yet? |
327 | moveq #0,%d0 | return success |
328 | rts |
329 | |
330 | | |
331 | | int _copyin(user_addr, supervisor_addr, nbytes) |
332 | | |
333 | .global _copyin |
334 | _copyin: |
335 | move.l 4(%sp),%a0 | source |
336 | move.l 8(%sp),%a1 | destination |
337 | move.l 12(%sp),%d0 | count |
338 | subq.l #1,%d0 |
339 | morein: |
340 | copyinae: |
341 | movs.b (%a0)+,%d1 | fetch user byte |
342 | move.b %d1,(%a1)+ | write supervisor byte |
343 | dbra %d0,morein | are we through yet? |
344 | moveq #0,%d0 | return success |
345 | rts |
346 | #endif |
347 | |
348 | |########################################################################### |
349 | |
350 | | |
351 | | _060_real_trace(): |
352 | | |
353 | | This is the exit point for the 060FPSP when an instruction is being traced |
354 | | and there are no other higher priority exceptions pending for this instruction |
355 | | or they have already been processed. |
356 | | |
357 | | The sample code below simply executes an "rte" . |
358 | | |
359 | .global _060_real_trace |
360 | _060_real_trace: |
361 | bral trap |
362 | |
363 | | |
364 | | _060_real_access(): |
365 | | |
366 | | This is the exit point for the 060FPSP when an access error exception |
367 | | is encountered. The routine below should point to the operating system |
368 | | handler for access error exceptions. The exception stack frame is an |
369 | | 8-word access error frame. |
370 | | |
371 | | The sample routine below simply executes an "rte" instruction which |
372 | | is most likely the incorrect thing to do and could put the system |
373 | | into an infinite loop. |
374 | | |
375 | .global _060_real_access |
376 | _060_real_access: |
377 | bral buserr |
378 | |
379 | |
380 | |
381 | | Execption handling for movs access to illegal memory |
382 | .section .fixup,"ax" |
383 | .even |
384 | 1: moveq #-1,%d1 |
385 | rts |
386 | .section __ex_table,"a" |
387 | .align 4 |
388 | .long dmrbuae,1b |
389 | .long dmrwuae,1b |
390 | .long dmrluae,1b |
391 | .long dmwbuae,1b |
392 | .long dmwwuae,1b |
393 | .long dmwluae,1b |
394 | .long copyoutae,1b |
395 | .long copyinae,1b |
396 | .text |
397 | |