Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 | | | |
96de0e25 | 7 | |M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved. |
1da177e4 LT |
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,#alloc,#execinstr | |
383 | .even | |
384 | 1: moveq #-1,%d1 | |
385 | rts | |
386 | .section __ex_table,#alloc | |
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 |