isp.s revision 1.3 1 1.1 is #
2 1.3 kamil # $NetBSD: isp.s,v 1.3 2015/07/11 10:32:46 kamil Exp $
3 1.1 is #
4 1.1 is
5 1.1 is #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 1.1 is # MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
7 1.1 is # M68000 Hi-Performance Microprocessor Division
8 1.1 is # M68060 Software Package Production Release
9 1.1 is #
10 1.1 is # M68060 Software Package Copyright (C) 1993, 1994, 1995, 1996 Motorola Inc.
11 1.1 is # All rights reserved.
12 1.1 is #
13 1.1 is # THE SOFTWARE is provided on an "AS IS" basis and without warranty.
14 1.1 is # To the maximum extent permitted by applicable law,
15 1.1 is # MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
16 1.1 is # INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS
17 1.1 is # FOR A PARTICULAR PURPOSE and any warranty against infringement with
18 1.1 is # regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
19 1.1 is # and any accompanying written materials.
20 1.1 is #
21 1.1 is # To the maximum extent permitted by applicable law,
22 1.1 is # IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
23 1.1 is # (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
24 1.1 is # BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
25 1.1 is # ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
26 1.1 is #
27 1.1 is # Motorola assumes no responsibility for the maintenance and support
28 1.1 is # of the SOFTWARE.
29 1.1 is #
30 1.1 is # You are hereby granted a copyright license to use, modify, and distribute the
31 1.1 is # SOFTWARE so long as this entire notice is retained without alteration
32 1.1 is # in any modified and/or redistributed versions, and that such modified
33 1.1 is # versions are clearly identified as such.
34 1.1 is # No licenses are granted by implication, estoppel or otherwise under any
35 1.1 is # patents or trademarks of Motorola, Inc.
36 1.1 is #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
37 1.1 is
38 1.1 is #
39 1.1 is # ireal.s:
40 1.1 is # This file is appended to the top of the 060ISP package
41 1.1 is # and contains the entry points into the package. The user, in
42 1.1 is # effect, branches to one of the branch table entries located
43 1.1 is # after _060ISP_TABLE.
44 1.1 is # Also, subroutine stubs exist in this file (_isp_done for
45 1.1 is # example) that are referenced by the ISP package itself in order
46 1.1 is # to call a given routine. The stub routine actually performs the
47 1.1 is # callout. The ISP code does a "bsr" to the stub routine. This
48 1.1 is # extra layer of hierarchy adds a slight performance penalty but
49 1.1 is # it makes the ISP code easier to read and more mainatinable.
50 1.1 is #
51 1.1 is
52 1.1 is set _off_chk, 0x00
53 1.1 is set _off_divbyzero, 0x04
54 1.1 is set _off_trace, 0x08
55 1.1 is set _off_access, 0x0c
56 1.1 is set _off_done, 0x10
57 1.1 is
58 1.1 is set _off_cas, 0x14
59 1.1 is set _off_cas2, 0x18
60 1.1 is set _off_lock, 0x1c
61 1.1 is set _off_unlock, 0x20
62 1.1 is
63 1.1 is set _off_imr, 0x40
64 1.1 is set _off_dmr, 0x44
65 1.1 is set _off_dmw, 0x48
66 1.1 is set _off_irw, 0x4c
67 1.1 is set _off_irl, 0x50
68 1.1 is set _off_drb, 0x54
69 1.1 is set _off_drw, 0x58
70 1.1 is set _off_drl, 0x5c
71 1.1 is set _off_dwb, 0x60
72 1.1 is set _off_dww, 0x64
73 1.1 is set _off_dwl, 0x68
74 1.1 is
75 1.1 is _060ISP_TABLE:
76 1.1 is
77 1.1 is # Here's the table of ENTRY POINTS for those linking the package.
78 1.1 is bra.l _isp_unimp
79 1.1 is short 0x0000
80 1.1 is
81 1.1 is bra.l _isp_cas
82 1.1 is short 0x0000
83 1.1 is
84 1.1 is bra.l _isp_cas2
85 1.1 is short 0x0000
86 1.1 is
87 1.1 is bra.l _isp_cas_finish
88 1.1 is short 0x0000
89 1.1 is
90 1.1 is bra.l _isp_cas2_finish
91 1.1 is short 0x0000
92 1.1 is
93 1.1 is bra.l _isp_cas_inrange
94 1.1 is short 0x0000
95 1.1 is
96 1.1 is bra.l _isp_cas_terminate
97 1.1 is short 0x0000
98 1.1 is
99 1.1 is bra.l _isp_cas_restart
100 1.1 is short 0x0000
101 1.1 is
102 1.1 is space 64
103 1.1 is
104 1.1 is #############################################################
105 1.1 is
106 1.1 is global _real_chk
107 1.1 is _real_chk:
108 1.1 is mov.l %d0,-(%sp)
109 1.1 is mov.l (_060ISP_TABLE-0x80+_off_chk,%pc),%d0
110 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
111 1.1 is mov.l 0x4(%sp),%d0
112 1.1 is rtd &0x4
113 1.1 is
114 1.1 is global _real_divbyzero
115 1.1 is _real_divbyzero:
116 1.1 is mov.l %d0,-(%sp)
117 1.1 is mov.l (_060ISP_TABLE-0x80+_off_divbyzero,%pc),%d0
118 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
119 1.1 is mov.l 0x4(%sp),%d0
120 1.1 is rtd &0x4
121 1.1 is
122 1.1 is global _real_trace
123 1.1 is _real_trace:
124 1.1 is mov.l %d0,-(%sp)
125 1.1 is mov.l (_060ISP_TABLE-0x80+_off_trace,%pc),%d0
126 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
127 1.1 is mov.l 0x4(%sp),%d0
128 1.1 is rtd &0x4
129 1.1 is
130 1.1 is global _real_access
131 1.1 is _real_access:
132 1.1 is mov.l %d0,-(%sp)
133 1.1 is mov.l (_060ISP_TABLE-0x80+_off_access,%pc),%d0
134 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
135 1.1 is mov.l 0x4(%sp),%d0
136 1.1 is rtd &0x4
137 1.1 is
138 1.1 is global _isp_done
139 1.1 is _isp_done:
140 1.1 is mov.l %d0,-(%sp)
141 1.1 is mov.l (_060ISP_TABLE-0x80+_off_done,%pc),%d0
142 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
143 1.1 is mov.l 0x4(%sp),%d0
144 1.1 is rtd &0x4
145 1.1 is
146 1.1 is #######################################
147 1.1 is
148 1.1 is global _real_cas
149 1.1 is _real_cas:
150 1.1 is mov.l %d0,-(%sp)
151 1.1 is mov.l (_060ISP_TABLE-0x80+_off_cas,%pc),%d0
152 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
153 1.1 is mov.l 0x4(%sp),%d0
154 1.1 is rtd &0x4
155 1.1 is
156 1.1 is global _real_cas2
157 1.1 is _real_cas2:
158 1.1 is mov.l %d0,-(%sp)
159 1.1 is mov.l (_060ISP_TABLE-0x80+_off_cas2,%pc),%d0
160 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
161 1.1 is mov.l 0x4(%sp),%d0
162 1.1 is rtd &0x4
163 1.1 is
164 1.1 is global _real_lock_page
165 1.1 is _real_lock_page:
166 1.1 is mov.l %d0,-(%sp)
167 1.1 is mov.l (_060ISP_TABLE-0x80+_off_lock,%pc),%d0
168 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
169 1.1 is mov.l 0x4(%sp),%d0
170 1.1 is rtd &0x4
171 1.1 is
172 1.1 is global _real_unlock_page
173 1.1 is _real_unlock_page:
174 1.1 is mov.l %d0,-(%sp)
175 1.1 is mov.l (_060ISP_TABLE-0x80+_off_unlock,%pc),%d0
176 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
177 1.1 is mov.l 0x4(%sp),%d0
178 1.1 is rtd &0x4
179 1.1 is
180 1.1 is #######################################
181 1.1 is
182 1.1 is global _imem_read
183 1.1 is _imem_read:
184 1.1 is mov.l %d0,-(%sp)
185 1.1 is mov.l (_060ISP_TABLE-0x80+_off_imr,%pc),%d0
186 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
187 1.1 is mov.l 0x4(%sp),%d0
188 1.1 is rtd &0x4
189 1.1 is
190 1.1 is global _dmem_read
191 1.1 is _dmem_read:
192 1.1 is mov.l %d0,-(%sp)
193 1.1 is mov.l (_060ISP_TABLE-0x80+_off_dmr,%pc),%d0
194 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
195 1.1 is mov.l 0x4(%sp),%d0
196 1.1 is rtd &0x4
197 1.1 is
198 1.1 is global _dmem_write
199 1.1 is _dmem_write:
200 1.1 is mov.l %d0,-(%sp)
201 1.1 is mov.l (_060ISP_TABLE-0x80+_off_dmw,%pc),%d0
202 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
203 1.1 is mov.l 0x4(%sp),%d0
204 1.1 is rtd &0x4
205 1.1 is
206 1.1 is global _imem_read_word
207 1.1 is _imem_read_word:
208 1.1 is mov.l %d0,-(%sp)
209 1.1 is mov.l (_060ISP_TABLE-0x80+_off_irw,%pc),%d0
210 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
211 1.1 is mov.l 0x4(%sp),%d0
212 1.1 is rtd &0x4
213 1.1 is
214 1.1 is global _imem_read_long
215 1.1 is _imem_read_long:
216 1.1 is mov.l %d0,-(%sp)
217 1.1 is mov.l (_060ISP_TABLE-0x80+_off_irl,%pc),%d0
218 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
219 1.1 is mov.l 0x4(%sp),%d0
220 1.1 is rtd &0x4
221 1.1 is
222 1.1 is global _dmem_read_byte
223 1.1 is _dmem_read_byte:
224 1.1 is mov.l %d0,-(%sp)
225 1.1 is mov.l (_060ISP_TABLE-0x80+_off_drb,%pc),%d0
226 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
227 1.1 is mov.l 0x4(%sp),%d0
228 1.1 is rtd &0x4
229 1.1 is
230 1.1 is global _dmem_read_word
231 1.1 is _dmem_read_word:
232 1.1 is mov.l %d0,-(%sp)
233 1.1 is mov.l (_060ISP_TABLE-0x80+_off_drw,%pc),%d0
234 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
235 1.1 is mov.l 0x4(%sp),%d0
236 1.1 is rtd &0x4
237 1.1 is
238 1.1 is global _dmem_read_long
239 1.1 is _dmem_read_long:
240 1.1 is mov.l %d0,-(%sp)
241 1.1 is mov.l (_060ISP_TABLE-0x80+_off_drl,%pc),%d0
242 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
243 1.1 is mov.l 0x4(%sp),%d0
244 1.1 is rtd &0x4
245 1.1 is
246 1.1 is global _dmem_write_byte
247 1.1 is _dmem_write_byte:
248 1.1 is mov.l %d0,-(%sp)
249 1.1 is mov.l (_060ISP_TABLE-0x80+_off_dwb,%pc),%d0
250 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
251 1.1 is mov.l 0x4(%sp),%d0
252 1.1 is rtd &0x4
253 1.1 is
254 1.1 is global _dmem_write_word
255 1.1 is _dmem_write_word:
256 1.1 is mov.l %d0,-(%sp)
257 1.1 is mov.l (_060ISP_TABLE-0x80+_off_dww,%pc),%d0
258 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
259 1.1 is mov.l 0x4(%sp),%d0
260 1.1 is rtd &0x4
261 1.1 is
262 1.1 is global _dmem_write_long
263 1.1 is _dmem_write_long:
264 1.1 is mov.l %d0,-(%sp)
265 1.1 is mov.l (_060ISP_TABLE-0x80+_off_dwl,%pc),%d0
266 1.1 is pea.l (_060ISP_TABLE-0x80,%pc,%d0)
267 1.1 is mov.l 0x4(%sp),%d0
268 1.1 is rtd &0x4
269 1.1 is
270 1.1 is #
271 1.1 is # This file contains a set of define statements for constants
272 1.1 is # in oreder to promote readability within the core code itself.
273 1.1 is #
274 1.1 is
275 1.1 is set LOCAL_SIZE, 96 # stack frame size(bytes)
276 1.1 is set LV, -LOCAL_SIZE # stack offset
277 1.1 is
278 1.1 is set EXC_ISR, 0x4 # stack status register
279 1.1 is set EXC_IPC, 0x6 # stack pc
280 1.1 is set EXC_IVOFF, 0xa # stacked vector offset
281 1.1 is
282 1.1 is set EXC_AREGS, LV+64 # offset of all address regs
283 1.1 is set EXC_DREGS, LV+32 # offset of all data regs
284 1.1 is
285 1.1 is set EXC_A7, EXC_AREGS+(7*4) # offset of a7
286 1.1 is set EXC_A6, EXC_AREGS+(6*4) # offset of a6
287 1.1 is set EXC_A5, EXC_AREGS+(5*4) # offset of a5
288 1.1 is set EXC_A4, EXC_AREGS+(4*4) # offset of a4
289 1.1 is set EXC_A3, EXC_AREGS+(3*4) # offset of a3
290 1.1 is set EXC_A2, EXC_AREGS+(2*4) # offset of a2
291 1.1 is set EXC_A1, EXC_AREGS+(1*4) # offset of a1
292 1.1 is set EXC_A0, EXC_AREGS+(0*4) # offset of a0
293 1.1 is set EXC_D7, EXC_DREGS+(7*4) # offset of d7
294 1.1 is set EXC_D6, EXC_DREGS+(6*4) # offset of d6
295 1.1 is set EXC_D5, EXC_DREGS+(5*4) # offset of d5
296 1.1 is set EXC_D4, EXC_DREGS+(4*4) # offset of d4
297 1.1 is set EXC_D3, EXC_DREGS+(3*4) # offset of d3
298 1.1 is set EXC_D2, EXC_DREGS+(2*4) # offset of d2
299 1.1 is set EXC_D1, EXC_DREGS+(1*4) # offset of d1
300 1.1 is set EXC_D0, EXC_DREGS+(0*4) # offset of d0
301 1.1 is
302 1.1 is set EXC_TEMP, LV+16 # offset of temp stack space
303 1.1 is
304 1.1 is set EXC_SAVVAL, LV+12 # offset of old areg value
305 1.1 is set EXC_SAVREG, LV+11 # offset of old areg index
306 1.1 is
307 1.1 is set SPCOND_FLG, LV+10 # offset of spc condition flg
308 1.1 is
309 1.1 is set EXC_CC, LV+8 # offset of cc register
310 1.1 is set EXC_EXTWPTR, LV+4 # offset of current PC
311 1.1 is set EXC_EXTWORD, LV+2 # offset of current ext opword
312 1.1 is set EXC_OPWORD, LV+0 # offset of current opword
313 1.1 is
314 1.1 is ###########################
315 1.1 is # SPecial CONDition FLaGs #
316 1.1 is ###########################
317 1.1 is set mia7_flg, 0x04 # (a7)+ flag
318 1.1 is set mda7_flg, 0x08 # -(a7) flag
319 1.1 is set ichk_flg, 0x10 # chk exception flag
320 1.1 is set idbyz_flg, 0x20 # divbyzero flag
321 1.1 is set restore_flg, 0x40 # restore -(an)+ flag
322 1.1 is set immed_flg, 0x80 # immediate data flag
323 1.1 is
324 1.1 is set mia7_bit, 0x2 # (a7)+ bit
325 1.1 is set mda7_bit, 0x3 # -(a7) bit
326 1.1 is set ichk_bit, 0x4 # chk exception bit
327 1.1 is set idbyz_bit, 0x5 # divbyzero bit
328 1.1 is set restore_bit, 0x6 # restore -(a7)+ bit
329 1.1 is set immed_bit, 0x7 # immediate data bit
330 1.1 is
331 1.1 is #########
332 1.1 is # Misc. #
333 1.1 is #########
334 1.1 is set BYTE, 1 # len(byte) == 1 byte
335 1.1 is set WORD, 2 # len(word) == 2 bytes
336 1.1 is set LONG, 4 # len(longword) == 4 bytes
337 1.1 is
338 1.1 is #########################################################################
339 1.1 is # XDEF **************************************************************** #
340 1.1 is # _isp_unimp(): 060ISP entry point for Unimplemented Instruction #
341 1.1 is # #
342 1.1 is # This handler should be the first code executed upon taking the #
343 1.1 is # "Unimplemented Integer Instruction" exception in an operating #
344 1.1 is # system. #
345 1.1 is # #
346 1.1 is # XREF **************************************************************** #
347 1.1 is # _imem_read_{word,long}() - read instruction word/longword #
348 1.1 is # _mul64() - emulate 64-bit multiply #
349 1.1 is # _div64() - emulate 64-bit divide #
350 1.1 is # _moveperipheral() - emulate "movep" #
351 1.1 is # _compandset() - emulate misaligned "cas" #
352 1.1 is # _compandset2() - emulate "cas2" #
353 1.1 is # _chk2_cmp2() - emulate "cmp2" and "chk2" #
354 1.1 is # _isp_done() - "callout" for normal final exit #
355 1.1 is # _real_trace() - "callout" for Trace exception #
356 1.1 is # _real_chk() - "callout" for Chk exception #
357 1.1 is # _real_divbyzero() - "callout" for DZ exception #
358 1.1 is # _real_access() - "callout" for access error exception #
359 1.1 is # #
360 1.1 is # INPUT *************************************************************** #
361 1.1 is # - The system stack contains the Unimp Int Instr stack frame #
362 1.1 is # #
363 1.1 is # OUTPUT ************************************************************** #
364 1.1 is # If Trace exception: #
365 1.1 is # - The system stack changed to contain Trace exc stack frame #
366 1.1 is # If Chk exception: #
367 1.1 is # - The system stack changed to contain Chk exc stack frame #
368 1.1 is # If DZ exception: #
369 1.1 is # - The system stack changed to contain DZ exc stack frame #
370 1.1 is # If access error exception: #
371 1.1 is # - The system stack changed to contain access err exc stk frame #
372 1.1 is # Else: #
373 1.1 is # - Results saved as appropriate #
374 1.1 is # #
375 1.1 is # ALGORITHM *********************************************************** #
376 1.1 is # This handler fetches the first instruction longword from #
377 1.1 is # memory and decodes it to determine which of the unimplemented #
378 1.1 is # integer instructions caused this exception. This handler then calls #
379 1.1 is # one of _mul64(), _div64(), _moveperipheral(), _compandset(), #
380 1.1 is # _compandset2(), or _chk2_cmp2() as appropriate. #
381 1.1 is # Some of these instructions, by their nature, may produce other #
382 1.1 is # types of exceptions. "div" can produce a divide-by-zero exception, #
383 1.1 is # and "chk2" can cause a "Chk" exception. In both cases, the current #
384 1.1 is # exception stack frame must be converted to an exception stack frame #
385 1.1 is # of the correct exception type and an exit must be made through #
386 1.1 is # _real_divbyzero() or _real_chk() as appropriate. In addition, all #
387 1.1 is # instructions may be executing while Trace is enabled. If so, then #
388 1.1 is # a Trace exception stack frame must be created and an exit made #
389 1.1 is # through _real_trace(). #
390 1.1 is # Meanwhile, if any read or write to memory using the #
391 1.1 is # _mem_{read,write}() "callout"s returns a failing value, then an #
392 1.1 is # access error frame must be created and an exit made through #
393 1.1 is # _real_access(). #
394 1.1 is # If none of these occur, then a normal exit is made through #
395 1.1 is # _isp_done(). #
396 1.1 is # #
397 1.1 is # This handler, upon entry, saves almost all user-visible #
398 1.1 is # address and data registers to the stack. Although this may seem to #
399 1.1 is # cause excess memory traffic, it was found that due to having to #
400 1.1 is # access these register files for things like data retrieval and <ea> #
401 1.1 is # calculations, it was more efficient to have them on the stack where #
402 1.1 is # they could be accessed by indexing rather than to make subroutine #
403 1.1 is # calls to retrieve a register of a particular index. #
404 1.1 is # #
405 1.1 is #########################################################################
406 1.1 is
407 1.1 is global _isp_unimp
408 1.1 is _isp_unimp:
409 1.1 is link.w %a6,&-LOCAL_SIZE # create room for stack frame
410 1.1 is
411 1.1 is movm.l &0x3fff,EXC_DREGS(%a6) # store d0-d7/a0-a5
412 1.1 is mov.l (%a6),EXC_A6(%a6) # store a6
413 1.1 is
414 1.1 is btst &0x5,EXC_ISR(%a6) # from s or u mode?
415 1.1 is bne.b uieh_s # supervisor mode
416 1.1 is uieh_u:
417 1.1 is mov.l %usp,%a0 # fetch user stack pointer
418 1.1 is mov.l %a0,EXC_A7(%a6) # store a7
419 1.1 is bra.b uieh_cont
420 1.1 is uieh_s:
421 1.1 is lea 0xc(%a6),%a0
422 1.1 is mov.l %a0,EXC_A7(%a6) # store corrected sp
423 1.1 is
424 1.1 is ###############################################################################
425 1.1 is
426 1.1 is uieh_cont:
427 1.1 is clr.b SPCOND_FLG(%a6) # clear "special case" flag
428 1.1 is
429 1.1 is mov.w EXC_ISR(%a6),EXC_CC(%a6) # store cc copy on stack
430 1.1 is mov.l EXC_IPC(%a6),EXC_EXTWPTR(%a6) # store extwptr on stack
431 1.1 is
432 1.1 is #
433 1.1 is # fetch the opword and first extension word pointed to by the stacked pc
434 1.1 is # and store them to the stack for now
435 1.1 is #
436 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
437 1.1 is addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
438 1.1 is bsr.l _imem_read_long # fetch opword & extword
439 1.1 is mov.l %d0,EXC_OPWORD(%a6) # store extword on stack
440 1.1 is
441 1.1 is
442 1.1 is #########################################################################
443 1.1 is # muls.l 0100 1100 00 |<ea>| 0*** 1100 0000 0*** #
444 1.1 is # mulu.l 0100 1100 00 |<ea>| 0*** 0100 0000 0*** #
445 1.1 is # #
446 1.1 is # divs.l 0100 1100 01 |<ea>| 0*** 1100 0000 0*** #
447 1.1 is # divu.l 0100 1100 01 |<ea>| 0*** 0100 0000 0*** #
448 1.1 is # #
449 1.1 is # movep.w m2r 0000 ***1 00 001*** | <displacement> | #
450 1.1 is # movep.l m2r 0000 ***1 01 001*** | <displacement> | #
451 1.1 is # movep.w r2m 0000 ***1 10 001*** | <displacement> | #
452 1.1 is # movep.l r2m 0000 ***1 11 001*** | <displacement> | #
453 1.1 is # #
454 1.1 is # cas.w 0000 1100 11 |<ea>| 0000 000* **00 0*** #
455 1.1 is # cas.l 0000 1110 11 |<ea>| 0000 000* **00 0*** #
456 1.1 is # #
457 1.1 is # cas2.w 0000 1100 11 111100 **** 000* **00 0*** #
458 1.1 is # **** 000* **00 0*** #
459 1.1 is # cas2.l 0000 1110 11 111100 **** 000* **00 0*** #
460 1.1 is # **** 000* **00 0*** #
461 1.1 is # #
462 1.1 is # chk2.b 0000 0000 11 |<ea>| **** 1000 0000 0000 #
463 1.1 is # chk2.w 0000 0010 11 |<ea>| **** 1000 0000 0000 #
464 1.1 is # chk2.l 0000 0100 11 |<ea>| **** 1000 0000 0000 #
465 1.1 is # #
466 1.1 is # cmp2.b 0000 0000 11 |<ea>| **** 0000 0000 0000 #
467 1.1 is # cmp2.w 0000 0010 11 |<ea>| **** 0000 0000 0000 #
468 1.1 is # cmp2.l 0000 0100 11 |<ea>| **** 0000 0000 0000 #
469 1.1 is #########################################################################
470 1.1 is
471 1.1 is #
472 1.1 is # using bit 14 of the operation word, separate into 2 groups:
473 1.1 is # (group1) mul64, div64
474 1.1 is # (group2) movep, chk2, cmp2, cas2, cas
475 1.1 is #
476 1.1 is btst &0x1e,%d0 # group1 or group2
477 1.1 is beq.b uieh_group2 # go handle group2
478 1.1 is
479 1.1 is #
480 1.1 is # now, w/ group1, make mul64's decode the fastest since it will
481 1.1 is # most likely be used the most.
482 1.1 is #
483 1.1 is uieh_group1:
484 1.1 is btst &0x16,%d0 # test for div64
485 1.1 is bne.b uieh_div64 # go handle div64
486 1.1 is
487 1.1 is uieh_mul64:
488 1.1 is # mul64() may use ()+ addressing and may, therefore, alter a7
489 1.1 is
490 1.1 is bsr.l _mul64 # _mul64()
491 1.1 is
492 1.1 is btst &0x5,EXC_ISR(%a6) # supervisor mode?
493 1.1 is beq.w uieh_done
494 1.1 is btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
495 1.1 is beq.w uieh_done # no
496 1.1 is btst &0x7,EXC_ISR(%a6) # is trace enabled?
497 1.1 is bne.w uieh_trace_a7 # yes
498 1.1 is bra.w uieh_a7 # no
499 1.1 is
500 1.1 is uieh_div64:
501 1.1 is # div64() may use ()+ addressing and may, therefore, alter a7.
502 1.1 is # div64() may take a divide by zero exception.
503 1.1 is
504 1.1 is bsr.l _div64 # _div64()
505 1.1 is
506 1.1 is # here, we sort out all of the special cases that may have happened.
507 1.1 is btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
508 1.1 is bne.b uieh_div64_a7 # yes
509 1.1 is uieh_div64_dbyz:
510 1.1 is btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
511 1.1 is bne.w uieh_divbyzero # yes
512 1.1 is bra.w uieh_done # no
513 1.1 is uieh_div64_a7:
514 1.1 is btst &0x5,EXC_ISR(%a6) # supervisor mode?
515 1.1 is beq.b uieh_div64_dbyz # no
516 1.1 is # here, a7 has been incremented by 4 bytes in supervisor mode. we still
517 1.1 is # may have the following 3 cases:
518 1.1 is # (i) (a7)+
519 1.1 is # (ii) (a7)+; trace
520 1.1 is # (iii) (a7)+; divide-by-zero
521 1.1 is #
522 1.1 is btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
523 1.1 is bne.w uieh_divbyzero_a7 # yes
524 1.1 is tst.b EXC_ISR(%a6) # no; is trace enabled?
525 1.1 is bmi.w uieh_trace_a7 # yes
526 1.1 is bra.w uieh_a7 # no
527 1.1 is
528 1.1 is #
529 1.1 is # now, w/ group2, make movep's decode the fastest since it will
530 1.1 is # most likely be used the most.
531 1.1 is #
532 1.1 is uieh_group2:
533 1.1 is btst &0x18,%d0 # test for not movep
534 1.1 is beq.b uieh_not_movep
535 1.1 is
536 1.1 is
537 1.1 is bsr.l _moveperipheral # _movep()
538 1.1 is bra.w uieh_done
539 1.1 is
540 1.1 is uieh_not_movep:
541 1.1 is btst &0x1b,%d0 # test for chk2,cmp2
542 1.1 is beq.b uieh_chk2cmp2 # go handle chk2,cmp2
543 1.1 is
544 1.1 is swap %d0 # put opword in lo word
545 1.1 is cmpi.b %d0,&0xfc # test for cas2
546 1.1 is beq.b uieh_cas2 # go handle cas2
547 1.1 is
548 1.1 is uieh_cas:
549 1.1 is
550 1.1 is bsr.l _compandset # _cas()
551 1.1 is
552 1.1 is # the cases of "cas Dc,Du,(a7)+" and "cas Dc,Du,-(a7)" used from supervisor
553 1.1 is # mode are simply not considered valid and therefore are not handled.
554 1.1 is
555 1.1 is bra.w uieh_done
556 1.1 is
557 1.1 is uieh_cas2:
558 1.1 is
559 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
560 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
561 1.1 is bsr.l _imem_read_word # read extension word
562 1.1 is
563 1.1 is tst.l %d1 # ifetch error?
564 1.1 is bne.w isp_iacc # yes
565 1.1 is
566 1.1 is bsr.l _compandset2 # _cas2()
567 1.1 is bra.w uieh_done
568 1.1 is
569 1.1 is uieh_chk2cmp2:
570 1.1 is # chk2 may take a chk exception
571 1.1 is
572 1.1 is bsr.l _chk2_cmp2 # _chk2_cmp2()
573 1.1 is
574 1.1 is # here we check to see if a chk trap should be taken
575 1.1 is cmpi.b SPCOND_FLG(%a6),&ichk_flg
576 1.1 is bne.w uieh_done
577 1.1 is bra.b uieh_chk_trap
578 1.1 is
579 1.1 is ###########################################################################
580 1.1 is
581 1.1 is #
582 1.1 is # the required emulation has been completed. now, clean up the necessary stack
583 1.1 is # info and prepare for rte
584 1.1 is #
585 1.1 is uieh_done:
586 1.1 is mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
587 1.1 is
588 1.1 is # if exception occurred in user mode, then we have to restore a7 in case it
589 1.1 is # changed. we don't have to update a7 for supervisor mose because that case
590 1.1 is # doesn't flow through here
591 1.1 is btst &0x5,EXC_ISR(%a6) # user or supervisor?
592 1.1 is bne.b uieh_finish # supervisor
593 1.1 is
594 1.1 is mov.l EXC_A7(%a6),%a0 # fetch user stack pointer
595 1.1 is mov.l %a0,%usp # restore it
596 1.1 is
597 1.1 is uieh_finish:
598 1.1 is movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
599 1.1 is
600 1.1 is btst &0x7,EXC_ISR(%a6) # is trace mode on?
601 1.1 is bne.b uieh_trace # yes;go handle trace mode
602 1.1 is
603 1.1 is mov.l EXC_EXTWPTR(%a6),EXC_IPC(%a6) # new pc on stack frame
604 1.1 is mov.l EXC_A6(%a6),(%a6) # prepare new a6 for unlink
605 1.1 is unlk %a6 # unlink stack frame
606 1.1 is bra.l _isp_done
607 1.1 is
608 1.1 is #
609 1.1 is # The instruction that was just emulated was also being traced. The trace
610 1.1 is # trap for this instruction will be lost unless we jump to the trace handler.
611 1.1 is # So, here we create a Trace Exception format number two exception stack
612 1.1 is # frame from the Unimplemented Integer Intruction Exception stack frame
613 1.1 is # format number zero and jump to the user supplied hook "_real_trace()".
614 1.1 is #
615 1.1 is # UIEH FRAME TRACE FRAME
616 1.1 is # ***************** *****************
617 1.1 is # * 0x0 * 0x0f4 * * Current *
618 1.1 is # ***************** * PC *
619 1.1 is # * Current * *****************
620 1.1 is # * PC * * 0x2 * 0x024 *
621 1.1 is # ***************** *****************
622 1.1 is # * SR * * Next *
623 1.1 is # ***************** * PC *
624 1.1 is # ->* Old * *****************
625 1.1 is # from link -->* A6 * * SR *
626 1.1 is # ***************** *****************
627 1.1 is # /* A7 * * New * <-- for final unlink
628 1.1 is # / * * * A6 *
629 1.1 is # link frame < ***************** *****************
630 1.1 is # \ ~ ~ ~ ~
631 1.1 is # \***************** *****************
632 1.1 is #
633 1.1 is uieh_trace:
634 1.1 is mov.l EXC_A6(%a6),-0x4(%a6)
635 1.1 is mov.w EXC_ISR(%a6),0x0(%a6)
636 1.1 is mov.l EXC_IPC(%a6),0x8(%a6)
637 1.1 is mov.l EXC_EXTWPTR(%a6),0x2(%a6)
638 1.1 is mov.w &0x2024,0x6(%a6)
639 1.1 is sub.l &0x4,%a6
640 1.1 is unlk %a6
641 1.1 is bra.l _real_trace
642 1.1 is
643 1.1 is #
644 1.1 is # UIEH FRAME CHK FRAME
645 1.1 is # ***************** *****************
646 1.1 is # * 0x0 * 0x0f4 * * Current *
647 1.1 is # ***************** * PC *
648 1.1 is # * Current * *****************
649 1.1 is # * PC * * 0x2 * 0x018 *
650 1.1 is # ***************** *****************
651 1.1 is # * SR * * Next *
652 1.1 is # ***************** * PC *
653 1.1 is # (4 words) *****************
654 1.1 is # * SR *
655 1.1 is # *****************
656 1.1 is # (6 words)
657 1.1 is #
658 1.1 is # the chk2 instruction should take a chk trap. so, here we must create a
659 1.1 is # chk stack frame from an unimplemented integer instruction exception frame
660 1.1 is # and jump to the user supplied entry point "_real_chk()".
661 1.1 is #
662 1.1 is uieh_chk_trap:
663 1.1 is mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
664 1.1 is movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
665 1.1 is
666 1.1 is mov.w EXC_ISR(%a6),(%a6) # put new SR on stack
667 1.1 is mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack
668 1.1 is mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
669 1.1 is mov.w &0x2018,0x6(%a6) # put Vector Offset on stack
670 1.1 is
671 1.1 is mov.l EXC_A6(%a6),%a6 # restore a6
672 1.1 is add.l &LOCAL_SIZE,%sp # clear stack frame
673 1.1 is
674 1.1 is bra.l _real_chk
675 1.1 is
676 1.1 is #
677 1.1 is # UIEH FRAME DIVBYZERO FRAME
678 1.1 is # ***************** *****************
679 1.1 is # * 0x0 * 0x0f4 * * Current *
680 1.1 is # ***************** * PC *
681 1.1 is # * Current * *****************
682 1.1 is # * PC * * 0x2 * 0x014 *
683 1.1 is # ***************** *****************
684 1.1 is # * SR * * Next *
685 1.1 is # ***************** * PC *
686 1.1 is # (4 words) *****************
687 1.1 is # * SR *
688 1.1 is # *****************
689 1.1 is # (6 words)
690 1.1 is #
691 1.1 is # the divide instruction should take an integer divide by zero trap. so, here
692 1.1 is # we must create a divbyzero stack frame from an unimplemented integer
693 1.1 is # instruction exception frame and jump to the user supplied entry point
694 1.1 is # "_real_divbyzero()".
695 1.1 is #
696 1.1 is uieh_divbyzero:
697 1.1 is mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
698 1.1 is movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
699 1.1 is
700 1.1 is mov.w EXC_ISR(%a6),(%a6) # put new SR on stack
701 1.1 is mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack
702 1.1 is mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
703 1.1 is mov.w &0x2014,0x6(%a6) # put Vector Offset on stack
704 1.1 is
705 1.1 is mov.l EXC_A6(%a6),%a6 # restore a6
706 1.1 is add.l &LOCAL_SIZE,%sp # clear stack frame
707 1.1 is
708 1.1 is bra.l _real_divbyzero
709 1.1 is
710 1.1 is #
711 1.1 is # DIVBYZERO FRAME
712 1.1 is # *****************
713 1.1 is # * Current *
714 1.1 is # UIEH FRAME * PC *
715 1.1 is # ***************** *****************
716 1.1 is # * 0x0 * 0x0f4 * * 0x2 * 0x014 *
717 1.1 is # ***************** *****************
718 1.1 is # * Current * * Next *
719 1.1 is # * PC * * PC *
720 1.1 is # ***************** *****************
721 1.1 is # * SR * * SR *
722 1.1 is # ***************** *****************
723 1.1 is # (4 words) (6 words)
724 1.1 is #
725 1.1 is # the divide instruction should take an integer divide by zero trap. so, here
726 1.1 is # we must create a divbyzero stack frame from an unimplemented integer
727 1.1 is # instruction exception frame and jump to the user supplied entry point
728 1.1 is # "_real_divbyzero()".
729 1.1 is #
730 1.1 is # However, we must also deal with the fact that (a7)+ was used from supervisor
731 1.1 is # mode, thereby shifting the stack frame up 4 bytes.
732 1.1 is #
733 1.1 is uieh_divbyzero_a7:
734 1.1 is mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
735 1.1 is movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
736 1.1 is
737 1.1 is mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack
738 1.1 is mov.w &0x2014,0xa(%a6) # put Vector Offset on stack
739 1.1 is mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
740 1.1 is
741 1.1 is mov.l EXC_A6(%a6),%a6 # restore a6
742 1.1 is add.l &4+LOCAL_SIZE,%sp # clear stack frame
743 1.1 is
744 1.1 is bra.l _real_divbyzero
745 1.1 is
746 1.1 is #
747 1.1 is # TRACE FRAME
748 1.1 is # *****************
749 1.1 is # * Current *
750 1.1 is # UIEH FRAME * PC *
751 1.1 is # ***************** *****************
752 1.1 is # * 0x0 * 0x0f4 * * 0x2 * 0x024 *
753 1.1 is # ***************** *****************
754 1.1 is # * Current * * Next *
755 1.1 is # * PC * * PC *
756 1.1 is # ***************** *****************
757 1.1 is # * SR * * SR *
758 1.1 is # ***************** *****************
759 1.1 is # (4 words) (6 words)
760 1.1 is #
761 1.1 is #
762 1.1 is # The instruction that was just emulated was also being traced. The trace
763 1.1 is # trap for this instruction will be lost unless we jump to the trace handler.
764 1.1 is # So, here we create a Trace Exception format number two exception stack
765 1.1 is # frame from the Unimplemented Integer Intruction Exception stack frame
766 1.1 is # format number zero and jump to the user supplied hook "_real_trace()".
767 1.1 is #
768 1.1 is # However, we must also deal with the fact that (a7)+ was used from supervisor
769 1.1 is # mode, thereby shifting the stack frame up 4 bytes.
770 1.1 is #
771 1.1 is uieh_trace_a7:
772 1.1 is mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
773 1.1 is movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
774 1.1 is
775 1.1 is mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack
776 1.1 is mov.w &0x2024,0xa(%a6) # put Vector Offset on stack
777 1.1 is mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
778 1.1 is
779 1.1 is mov.l EXC_A6(%a6),%a6 # restore a6
780 1.1 is add.l &4+LOCAL_SIZE,%sp # clear stack frame
781 1.1 is
782 1.1 is bra.l _real_trace
783 1.1 is
784 1.1 is #
785 1.1 is # UIEH FRAME
786 1.1 is # *****************
787 1.1 is # * 0x0 * 0x0f4 *
788 1.1 is # UIEH FRAME *****************
789 1.1 is # ***************** * Next *
790 1.1 is # * 0x0 * 0x0f4 * * PC *
791 1.1 is # ***************** *****************
792 1.1 is # * Current * * SR *
793 1.1 is # * PC * *****************
794 1.1 is # ***************** (4 words)
795 1.1 is # * SR *
796 1.1 is # *****************
797 1.1 is # (4 words)
798 1.1 is uieh_a7:
799 1.1 is mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
800 1.1 is movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
801 1.1 is
802 1.1 is mov.w &0x00f4,0xe(%a6) # put Vector Offset on stack
803 1.1 is mov.l EXC_EXTWPTR(%a6),0xa(%a6) # put "Next PC" on stack
804 1.1 is mov.w EXC_ISR(%a6),0x8(%a6) # put SR on stack
805 1.1 is
806 1.1 is mov.l EXC_A6(%a6),%a6 # restore a6
807 1.1 is add.l &8+LOCAL_SIZE,%sp # clear stack frame
808 1.1 is bra.l _isp_done
809 1.1 is
810 1.1 is ##########
811 1.1 is
812 1.1 is # this is the exit point if a data read or write fails.
813 1.1 is # a0 = failing address
814 1.1 is # d0 = fslw
815 1.1 is isp_dacc:
816 1.1 is mov.l %a0,(%a6) # save address
817 1.1 is mov.l %d0,-0x4(%a6) # save partial fslw
818 1.1 is
819 1.1 is lea -64(%a6),%sp
820 1.1 is movm.l (%sp)+,&0x7fff # restore d0-d7/a0-a6
821 1.1 is
822 1.1 is mov.l 0xc(%sp),-(%sp) # move voff,hi(pc)
823 1.1 is mov.l 0x4(%sp),0x10(%sp) # store fslw
824 1.1 is mov.l 0xc(%sp),0x4(%sp) # store sr,lo(pc)
825 1.1 is mov.l 0x8(%sp),0xc(%sp) # store address
826 1.1 is mov.l (%sp)+,0x4(%sp) # store voff,hi(pc)
827 1.1 is mov.w &0x4008,0x6(%sp) # store new voff
828 1.1 is
829 1.1 is bra.b isp_acc_exit
830 1.1 is
831 1.1 is # this is the exit point if an instruction word read fails.
832 1.1 is # FSLW:
833 1.1 is # misaligned = true
834 1.1 is # read = true
835 1.1 is # size = word
836 1.1 is # instruction = true
837 1.1 is # software emulation error = true
838 1.1 is isp_iacc:
839 1.1 is movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5
840 1.1 is unlk %a6 # unlink frame
841 1.1 is sub.w &0x8,%sp # make room for acc frame
842 1.1 is mov.l 0x8(%sp),(%sp) # store sr,lo(pc)
843 1.1 is mov.w 0xc(%sp),0x4(%sp) # store hi(pc)
844 1.1 is mov.w &0x4008,0x6(%sp) # store new voff
845 1.1 is mov.l 0x2(%sp),0x8(%sp) # store address (=pc)
846 1.1 is mov.l &0x09428001,0xc(%sp) # store fslw
847 1.1 is
848 1.1 is isp_acc_exit:
849 1.1 is btst &0x5,(%sp) # user or supervisor?
850 1.1 is beq.b isp_acc_exit2 # user
851 1.1 is bset &0x2,0xd(%sp) # set supervisor TM bit
852 1.1 is isp_acc_exit2:
853 1.1 is bra.l _real_access
854 1.1 is
855 1.1 is # if the addressing mode was (an)+ or -(an), the address register must
856 1.1 is # be restored to it's pre-exception value before entering _real_access.
857 1.1 is isp_restore:
858 1.1 is cmpi.b SPCOND_FLG(%a6),&restore_flg # do we need a restore?
859 1.1 is bne.b isp_restore_done # no
860 1.1 is clr.l %d0
861 1.1 is mov.b EXC_SAVREG(%a6),%d0 # regno to restore
862 1.1 is mov.l EXC_SAVVAL(%a6),(EXC_AREGS,%a6,%d0.l*4) # restore value
863 1.1 is isp_restore_done:
864 1.1 is rts
865 1.1 is
866 1.1 is #########################################################################
867 1.1 is # XDEF **************************************************************** #
868 1.1 is # _calc_ea(): routine to calculate effective address #
869 1.1 is # #
870 1.1 is # XREF **************************************************************** #
871 1.1 is # _imem_read_word() - read instruction word #
872 1.1 is # _imem_read_long() - read instruction longword #
873 1.1 is # _dmem_read_long() - read data longword (for memory indirect) #
874 1.1 is # isp_iacc() - handle instruction access error exception #
875 1.1 is # isp_dacc() - handle data access error exception #
876 1.1 is # #
877 1.1 is # INPUT *************************************************************** #
878 1.1 is # d0 = number of bytes related to effective address (w,l) #
879 1.1 is # #
880 1.1 is # OUTPUT ************************************************************** #
881 1.1 is # If exiting through isp_dacc... #
882 1.1 is # a0 = failing address #
883 1.1 is # d0 = FSLW #
884 1.1 is # elsif exiting though isp_iacc... #
885 1.1 is # none #
886 1.1 is # else #
887 1.1 is # a0 = effective address #
888 1.1 is # #
889 1.1 is # ALGORITHM *********************************************************** #
890 1.1 is # The effective address type is decoded from the opword residing #
891 1.1 is # on the stack. A jump table is used to vector to a routine for the #
892 1.1 is # appropriate mode. Since none of the emulated integer instructions #
893 1.1 is # uses byte-sized operands, only handle word and long operations. #
894 1.1 is # #
895 1.1 is # Dn,An - shouldn't enter here #
896 1.1 is # (An) - fetch An value from stack #
897 1.1 is # -(An) - fetch An value from stack; return decr value; #
898 1.1 is # place decr value on stack; store old value in case of #
899 1.1 is # future access error; if -(a7), set mda7_flg in #
900 1.1 is # SPCOND_FLG #
901 1.1 is # (An)+ - fetch An value from stack; return value; #
902 1.1 is # place incr value on stack; store old value in case of #
903 1.1 is # future access error; if (a7)+, set mia7_flg in #
904 1.1 is # SPCOND_FLG #
905 1.1 is # (d16,An) - fetch An value from stack; read d16 using #
906 1.1 is # _imem_read_word(); fetch may fail -> branch to #
907 1.1 is # isp_iacc() #
908 1.1 is # (xxx).w,(xxx).l - use _imem_read_{word,long}() to fetch #
909 1.1 is # address; fetch may fail #
910 1.1 is # #<data> - return address of immediate value; set immed_flg #
911 1.1 is # in SPCOND_FLG #
912 1.1 is # (d16,PC) - fetch stacked PC value; read d16 using #
913 1.1 is # _imem_read_word(); fetch may fail -> branch to #
914 1.1 is # isp_iacc() #
915 1.1 is # everything else - read needed displacements as appropriate w/ #
916 1.1 is # _imem_read_{word,long}(); read may fail; if memory #
917 1.1 is # indirect, read indirect address using #
918 1.1 is # _dmem_read_long() which may also fail #
919 1.1 is # #
920 1.1 is #########################################################################
921 1.1 is
922 1.1 is global _calc_ea
923 1.1 is _calc_ea:
924 1.1 is mov.l %d0,%a0 # move # bytes to a0
925 1.1 is
926 1.1 is # MODE and REG are taken from the EXC_OPWORD.
927 1.1 is mov.w EXC_OPWORD(%a6),%d0 # fetch opcode word
928 1.1 is mov.w %d0,%d1 # make a copy
929 1.1 is
930 1.1 is andi.w &0x3f,%d0 # extract mode field
931 1.1 is andi.l &0x7,%d1 # extract reg field
932 1.1 is
933 1.1 is # jump to the corresponding function for each {MODE,REG} pair.
934 1.1 is mov.w (tbl_ea_mode.b,%pc,%d0.w*2), %d0 # fetch jmp distance
935 1.1 is jmp (tbl_ea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
936 1.1 is
937 1.1 is swbeg &64
938 1.1 is tbl_ea_mode:
939 1.1 is short tbl_ea_mode - tbl_ea_mode
940 1.1 is short tbl_ea_mode - tbl_ea_mode
941 1.1 is short tbl_ea_mode - tbl_ea_mode
942 1.1 is short tbl_ea_mode - tbl_ea_mode
943 1.1 is short tbl_ea_mode - tbl_ea_mode
944 1.1 is short tbl_ea_mode - tbl_ea_mode
945 1.1 is short tbl_ea_mode - tbl_ea_mode
946 1.1 is short tbl_ea_mode - tbl_ea_mode
947 1.1 is
948 1.1 is short tbl_ea_mode - tbl_ea_mode
949 1.1 is short tbl_ea_mode - tbl_ea_mode
950 1.1 is short tbl_ea_mode - tbl_ea_mode
951 1.1 is short tbl_ea_mode - tbl_ea_mode
952 1.1 is short tbl_ea_mode - tbl_ea_mode
953 1.1 is short tbl_ea_mode - tbl_ea_mode
954 1.1 is short tbl_ea_mode - tbl_ea_mode
955 1.1 is short tbl_ea_mode - tbl_ea_mode
956 1.1 is
957 1.1 is short addr_ind_a0 - tbl_ea_mode
958 1.1 is short addr_ind_a1 - tbl_ea_mode
959 1.1 is short addr_ind_a2 - tbl_ea_mode
960 1.1 is short addr_ind_a3 - tbl_ea_mode
961 1.1 is short addr_ind_a4 - tbl_ea_mode
962 1.1 is short addr_ind_a5 - tbl_ea_mode
963 1.1 is short addr_ind_a6 - tbl_ea_mode
964 1.1 is short addr_ind_a7 - tbl_ea_mode
965 1.1 is
966 1.1 is short addr_ind_p_a0 - tbl_ea_mode
967 1.1 is short addr_ind_p_a1 - tbl_ea_mode
968 1.1 is short addr_ind_p_a2 - tbl_ea_mode
969 1.1 is short addr_ind_p_a3 - tbl_ea_mode
970 1.1 is short addr_ind_p_a4 - tbl_ea_mode
971 1.1 is short addr_ind_p_a5 - tbl_ea_mode
972 1.1 is short addr_ind_p_a6 - tbl_ea_mode
973 1.1 is short addr_ind_p_a7 - tbl_ea_mode
974 1.1 is
975 1.1 is short addr_ind_m_a0 - tbl_ea_mode
976 1.1 is short addr_ind_m_a1 - tbl_ea_mode
977 1.1 is short addr_ind_m_a2 - tbl_ea_mode
978 1.1 is short addr_ind_m_a3 - tbl_ea_mode
979 1.1 is short addr_ind_m_a4 - tbl_ea_mode
980 1.1 is short addr_ind_m_a5 - tbl_ea_mode
981 1.1 is short addr_ind_m_a6 - tbl_ea_mode
982 1.1 is short addr_ind_m_a7 - tbl_ea_mode
983 1.1 is
984 1.1 is short addr_ind_disp_a0 - tbl_ea_mode
985 1.1 is short addr_ind_disp_a1 - tbl_ea_mode
986 1.1 is short addr_ind_disp_a2 - tbl_ea_mode
987 1.1 is short addr_ind_disp_a3 - tbl_ea_mode
988 1.1 is short addr_ind_disp_a4 - tbl_ea_mode
989 1.1 is short addr_ind_disp_a5 - tbl_ea_mode
990 1.1 is short addr_ind_disp_a6 - tbl_ea_mode
991 1.1 is short addr_ind_disp_a7 - tbl_ea_mode
992 1.1 is
993 1.1 is short _addr_ind_ext - tbl_ea_mode
994 1.1 is short _addr_ind_ext - tbl_ea_mode
995 1.1 is short _addr_ind_ext - tbl_ea_mode
996 1.1 is short _addr_ind_ext - tbl_ea_mode
997 1.1 is short _addr_ind_ext - tbl_ea_mode
998 1.1 is short _addr_ind_ext - tbl_ea_mode
999 1.1 is short _addr_ind_ext - tbl_ea_mode
1000 1.1 is short _addr_ind_ext - tbl_ea_mode
1001 1.1 is
1002 1.1 is short abs_short - tbl_ea_mode
1003 1.1 is short abs_long - tbl_ea_mode
1004 1.1 is short pc_ind - tbl_ea_mode
1005 1.1 is short pc_ind_ext - tbl_ea_mode
1006 1.1 is short immediate - tbl_ea_mode
1007 1.1 is short tbl_ea_mode - tbl_ea_mode
1008 1.1 is short tbl_ea_mode - tbl_ea_mode
1009 1.1 is short tbl_ea_mode - tbl_ea_mode
1010 1.1 is
1011 1.1 is ###################################
1012 1.1 is # Address register indirect: (An) #
1013 1.1 is ###################################
1014 1.1 is addr_ind_a0:
1015 1.1 is mov.l EXC_A0(%a6),%a0 # Get current a0
1016 1.1 is rts
1017 1.1 is
1018 1.1 is addr_ind_a1:
1019 1.1 is mov.l EXC_A1(%a6),%a0 # Get current a1
1020 1.1 is rts
1021 1.1 is
1022 1.1 is addr_ind_a2:
1023 1.1 is mov.l EXC_A2(%a6),%a0 # Get current a2
1024 1.1 is rts
1025 1.1 is
1026 1.1 is addr_ind_a3:
1027 1.1 is mov.l EXC_A3(%a6),%a0 # Get current a3
1028 1.1 is rts
1029 1.1 is
1030 1.1 is addr_ind_a4:
1031 1.1 is mov.l EXC_A4(%a6),%a0 # Get current a4
1032 1.1 is rts
1033 1.1 is
1034 1.1 is addr_ind_a5:
1035 1.1 is mov.l EXC_A5(%a6),%a0 # Get current a5
1036 1.1 is rts
1037 1.1 is
1038 1.1 is addr_ind_a6:
1039 1.1 is mov.l EXC_A6(%a6),%a0 # Get current a6
1040 1.1 is rts
1041 1.1 is
1042 1.1 is addr_ind_a7:
1043 1.1 is mov.l EXC_A7(%a6),%a0 # Get current a7
1044 1.1 is rts
1045 1.1 is
1046 1.1 is #####################################################
1047 1.1 is # Address register indirect w/ postincrement: (An)+ #
1048 1.1 is #####################################################
1049 1.1 is addr_ind_p_a0:
1050 1.1 is mov.l %a0,%d0 # copy no. bytes
1051 1.1 is mov.l EXC_A0(%a6),%a0 # load current value
1052 1.1 is add.l %a0,%d0 # increment
1053 1.1 is mov.l %d0,EXC_A0(%a6) # save incremented value
1054 1.1 is
1055 1.1 is mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1056 1.1 is mov.b &0x0,EXC_SAVREG(%a6) # save regno, too
1057 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1058 1.1 is rts
1059 1.1 is
1060 1.1 is addr_ind_p_a1:
1061 1.1 is mov.l %a0,%d0 # copy no. bytes
1062 1.1 is mov.l EXC_A1(%a6),%a0 # load current value
1063 1.1 is add.l %a0,%d0 # increment
1064 1.1 is mov.l %d0,EXC_A1(%a6) # save incremented value
1065 1.1 is
1066 1.1 is mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1067 1.1 is mov.b &0x1,EXC_SAVREG(%a6) # save regno, too
1068 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1069 1.1 is rts
1070 1.1 is
1071 1.1 is addr_ind_p_a2:
1072 1.1 is mov.l %a0,%d0 # copy no. bytes
1073 1.1 is mov.l EXC_A2(%a6),%a0 # load current value
1074 1.1 is add.l %a0,%d0 # increment
1075 1.1 is mov.l %d0,EXC_A2(%a6) # save incremented value
1076 1.1 is
1077 1.1 is mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1078 1.1 is mov.b &0x2,EXC_SAVREG(%a6) # save regno, too
1079 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1080 1.1 is rts
1081 1.1 is
1082 1.1 is addr_ind_p_a3:
1083 1.1 is mov.l %a0,%d0 # copy no. bytes
1084 1.1 is mov.l EXC_A3(%a6),%a0 # load current value
1085 1.1 is add.l %a0,%d0 # increment
1086 1.1 is mov.l %d0,EXC_A3(%a6) # save incremented value
1087 1.1 is
1088 1.1 is mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1089 1.1 is mov.b &0x3,EXC_SAVREG(%a6) # save regno, too
1090 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1091 1.1 is rts
1092 1.1 is
1093 1.1 is addr_ind_p_a4:
1094 1.1 is mov.l %a0,%d0 # copy no. bytes
1095 1.1 is mov.l EXC_A4(%a6),%a0 # load current value
1096 1.1 is add.l %a0,%d0 # increment
1097 1.1 is mov.l %d0,EXC_A4(%a6) # save incremented value
1098 1.1 is
1099 1.1 is mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1100 1.1 is mov.b &0x4,EXC_SAVREG(%a6) # save regno, too
1101 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1102 1.1 is rts
1103 1.1 is
1104 1.1 is addr_ind_p_a5:
1105 1.1 is mov.l %a0,%d0 # copy no. bytes
1106 1.1 is mov.l EXC_A5(%a6),%a0 # load current value
1107 1.1 is add.l %a0,%d0 # increment
1108 1.1 is mov.l %d0,EXC_A5(%a6) # save incremented value
1109 1.1 is
1110 1.1 is mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1111 1.1 is mov.b &0x5,EXC_SAVREG(%a6) # save regno, too
1112 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1113 1.1 is rts
1114 1.1 is
1115 1.1 is addr_ind_p_a6:
1116 1.1 is mov.l %a0,%d0 # copy no. bytes
1117 1.1 is mov.l EXC_A6(%a6),%a0 # load current value
1118 1.1 is add.l %a0,%d0 # increment
1119 1.1 is mov.l %d0,EXC_A6(%a6) # save incremented value
1120 1.1 is
1121 1.1 is mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error
1122 1.1 is mov.b &0x6,EXC_SAVREG(%a6) # save regno, too
1123 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1124 1.1 is rts
1125 1.1 is
1126 1.1 is addr_ind_p_a7:
1127 1.1 is mov.b &mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
1128 1.1 is
1129 1.1 is mov.l %a0,%d0 # copy no. bytes
1130 1.1 is mov.l EXC_A7(%a6),%a0 # load current value
1131 1.1 is add.l %a0,%d0 # increment
1132 1.1 is mov.l %d0,EXC_A7(%a6) # save incremented value
1133 1.1 is rts
1134 1.1 is
1135 1.1 is ####################################################
1136 1.1 is # Address register indirect w/ predecrement: -(An) #
1137 1.1 is ####################################################
1138 1.1 is addr_ind_m_a0:
1139 1.1 is mov.l EXC_A0(%a6),%d0 # Get current a0
1140 1.1 is mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1141 1.1 is sub.l %a0,%d0 # Decrement
1142 1.1 is mov.l %d0,EXC_A0(%a6) # Save decr value
1143 1.1 is mov.l %d0,%a0
1144 1.1 is
1145 1.1 is mov.b &0x0,EXC_SAVREG(%a6) # save regno, too
1146 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1147 1.1 is rts
1148 1.1 is
1149 1.1 is addr_ind_m_a1:
1150 1.1 is mov.l EXC_A1(%a6),%d0 # Get current a1
1151 1.1 is mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1152 1.1 is sub.l %a0,%d0 # Decrement
1153 1.1 is mov.l %d0,EXC_A1(%a6) # Save decr value
1154 1.1 is mov.l %d0,%a0
1155 1.1 is
1156 1.1 is mov.b &0x1,EXC_SAVREG(%a6) # save regno, too
1157 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1158 1.1 is rts
1159 1.1 is
1160 1.1 is addr_ind_m_a2:
1161 1.1 is mov.l EXC_A2(%a6),%d0 # Get current a2
1162 1.1 is mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1163 1.1 is sub.l %a0,%d0 # Decrement
1164 1.1 is mov.l %d0,EXC_A2(%a6) # Save decr value
1165 1.1 is mov.l %d0,%a0
1166 1.1 is
1167 1.1 is mov.b &0x2,EXC_SAVREG(%a6) # save regno, too
1168 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1169 1.1 is rts
1170 1.1 is
1171 1.1 is addr_ind_m_a3:
1172 1.1 is mov.l EXC_A3(%a6),%d0 # Get current a3
1173 1.1 is mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1174 1.1 is sub.l %a0,%d0 # Decrement
1175 1.1 is mov.l %d0,EXC_A3(%a6) # Save decr value
1176 1.1 is mov.l %d0,%a0
1177 1.1 is
1178 1.1 is mov.b &0x3,EXC_SAVREG(%a6) # save regno, too
1179 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1180 1.1 is rts
1181 1.1 is
1182 1.1 is addr_ind_m_a4:
1183 1.1 is mov.l EXC_A4(%a6),%d0 # Get current a4
1184 1.1 is mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1185 1.1 is sub.l %a0,%d0 # Decrement
1186 1.1 is mov.l %d0,EXC_A4(%a6) # Save decr value
1187 1.1 is mov.l %d0,%a0
1188 1.1 is
1189 1.1 is mov.b &0x4,EXC_SAVREG(%a6) # save regno, too
1190 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1191 1.1 is rts
1192 1.1 is
1193 1.1 is addr_ind_m_a5:
1194 1.1 is mov.l EXC_A5(%a6),%d0 # Get current a5
1195 1.1 is mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1196 1.1 is sub.l %a0,%d0 # Decrement
1197 1.1 is mov.l %d0,EXC_A5(%a6) # Save decr value
1198 1.1 is mov.l %d0,%a0
1199 1.1 is
1200 1.1 is mov.b &0x5,EXC_SAVREG(%a6) # save regno, too
1201 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1202 1.1 is rts
1203 1.1 is
1204 1.1 is addr_ind_m_a6:
1205 1.1 is mov.l EXC_A6(%a6),%d0 # Get current a6
1206 1.1 is mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error
1207 1.1 is sub.l %a0,%d0 # Decrement
1208 1.1 is mov.l %d0,EXC_A6(%a6) # Save decr value
1209 1.1 is mov.l %d0,%a0
1210 1.1 is
1211 1.1 is mov.b &0x6,EXC_SAVREG(%a6) # save regno, too
1212 1.1 is mov.b &restore_flg,SPCOND_FLG(%a6) # set flag
1213 1.1 is rts
1214 1.1 is
1215 1.1 is addr_ind_m_a7:
1216 1.1 is mov.b &mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
1217 1.1 is
1218 1.1 is mov.l EXC_A7(%a6),%d0 # Get current a7
1219 1.1 is sub.l %a0,%d0 # Decrement
1220 1.1 is mov.l %d0,EXC_A7(%a6) # Save decr value
1221 1.1 is mov.l %d0,%a0
1222 1.1 is rts
1223 1.1 is
1224 1.1 is ########################################################
1225 1.1 is # Address register indirect w/ displacement: (d16, An) #
1226 1.1 is ########################################################
1227 1.1 is addr_ind_disp_a0:
1228 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1229 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1230 1.1 is bsr.l _imem_read_word
1231 1.1 is
1232 1.1 is tst.l %d1 # ifetch error?
1233 1.1 is bne.l isp_iacc # yes
1234 1.1 is
1235 1.1 is mov.w %d0,%a0 # sign extend displacement
1236 1.1 is add.l EXC_A0(%a6),%a0 # a0 + d16
1237 1.1 is rts
1238 1.1 is
1239 1.1 is addr_ind_disp_a1:
1240 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1241 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1242 1.1 is bsr.l _imem_read_word
1243 1.1 is
1244 1.1 is tst.l %d1 # ifetch error?
1245 1.1 is bne.l isp_iacc # yes
1246 1.1 is
1247 1.1 is mov.w %d0,%a0 # sign extend displacement
1248 1.1 is add.l EXC_A1(%a6),%a0 # a1 + d16
1249 1.1 is rts
1250 1.1 is
1251 1.1 is addr_ind_disp_a2:
1252 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1253 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1254 1.1 is bsr.l _imem_read_word
1255 1.1 is
1256 1.1 is tst.l %d1 # ifetch error?
1257 1.1 is bne.l isp_iacc # yes
1258 1.1 is
1259 1.1 is mov.w %d0,%a0 # sign extend displacement
1260 1.1 is add.l EXC_A2(%a6),%a0 # a2 + d16
1261 1.1 is rts
1262 1.1 is
1263 1.1 is addr_ind_disp_a3:
1264 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1265 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1266 1.1 is bsr.l _imem_read_word
1267 1.1 is
1268 1.1 is tst.l %d1 # ifetch error?
1269 1.1 is bne.l isp_iacc # yes
1270 1.1 is
1271 1.1 is mov.w %d0,%a0 # sign extend displacement
1272 1.1 is add.l EXC_A3(%a6),%a0 # a3 + d16
1273 1.1 is rts
1274 1.1 is
1275 1.1 is addr_ind_disp_a4:
1276 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1277 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1278 1.1 is bsr.l _imem_read_word
1279 1.1 is
1280 1.1 is tst.l %d1 # ifetch error?
1281 1.1 is bne.l isp_iacc # yes
1282 1.1 is
1283 1.1 is mov.w %d0,%a0 # sign extend displacement
1284 1.1 is add.l EXC_A4(%a6),%a0 # a4 + d16
1285 1.1 is rts
1286 1.1 is
1287 1.1 is addr_ind_disp_a5:
1288 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1289 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1290 1.1 is bsr.l _imem_read_word
1291 1.1 is
1292 1.1 is tst.l %d1 # ifetch error?
1293 1.1 is bne.l isp_iacc # yes
1294 1.1 is
1295 1.1 is mov.w %d0,%a0 # sign extend displacement
1296 1.1 is add.l EXC_A5(%a6),%a0 # a5 + d16
1297 1.1 is rts
1298 1.1 is
1299 1.1 is addr_ind_disp_a6:
1300 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1301 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1302 1.1 is bsr.l _imem_read_word
1303 1.1 is
1304 1.1 is tst.l %d1 # ifetch error?
1305 1.1 is bne.l isp_iacc # yes
1306 1.1 is
1307 1.1 is mov.w %d0,%a0 # sign extend displacement
1308 1.1 is add.l EXC_A6(%a6),%a0 # a6 + d16
1309 1.1 is rts
1310 1.1 is
1311 1.1 is addr_ind_disp_a7:
1312 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1313 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1314 1.1 is bsr.l _imem_read_word
1315 1.1 is
1316 1.1 is tst.l %d1 # ifetch error?
1317 1.1 is bne.l isp_iacc # yes
1318 1.1 is
1319 1.1 is mov.w %d0,%a0 # sign extend displacement
1320 1.1 is add.l EXC_A7(%a6),%a0 # a7 + d16
1321 1.1 is rts
1322 1.1 is
1323 1.1 is ########################################################################
1324 1.1 is # Address register indirect w/ index(8-bit displacement): (dn, An, Xn) #
1325 1.1 is # " " " w/ " (base displacement): (bd, An, Xn) #
1326 1.1 is # Memory indirect postindexed: ([bd, An], Xn, od) #
1327 1.1 is # Memory indirect preindexed: ([bd, An, Xn], od) #
1328 1.1 is ########################################################################
1329 1.1 is _addr_ind_ext:
1330 1.1 is mov.l %d1,-(%sp)
1331 1.1 is
1332 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1333 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1334 1.1 is bsr.l _imem_read_word # fetch extword in d0
1335 1.1 is
1336 1.1 is tst.l %d1 # ifetch error?
1337 1.1 is bne.l isp_iacc # yes
1338 1.1 is
1339 1.1 is mov.l (%sp)+,%d1
1340 1.1 is
1341 1.1 is mov.l (EXC_AREGS,%a6,%d1.w*4),%a0 # put base in a0
1342 1.1 is
1343 1.1 is btst &0x8,%d0
1344 1.1 is beq.b addr_ind_index_8bit # for ext word or not?
1345 1.1 is
1346 1.1 is movm.l &0x3c00,-(%sp) # save d2-d5
1347 1.1 is
1348 1.1 is mov.l %d0,%d5 # put extword in d5
1349 1.1 is mov.l %a0,%d3 # put base in d3
1350 1.1 is
1351 1.1 is bra.l calc_mem_ind # calc memory indirect
1352 1.1 is
1353 1.1 is addr_ind_index_8bit:
1354 1.1 is mov.l %d2,-(%sp) # save old d2
1355 1.1 is
1356 1.1 is mov.l %d0,%d1
1357 1.1 is rol.w &0x4,%d1
1358 1.1 is andi.w &0xf,%d1 # extract index regno
1359 1.1 is
1360 1.1 is mov.l (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
1361 1.1 is
1362 1.1 is btst &0xb,%d0 # is it word or long?
1363 1.1 is bne.b aii8_long
1364 1.1 is ext.l %d1 # sign extend word index
1365 1.1 is aii8_long:
1366 1.1 is mov.l %d0,%d2
1367 1.1 is rol.w &0x7,%d2
1368 1.1 is andi.l &0x3,%d2 # extract scale value
1369 1.1 is
1370 1.1 is lsl.l %d2,%d1 # shift index by scale
1371 1.1 is
1372 1.1 is extb.l %d0 # sign extend displacement
1373 1.1 is add.l %d1,%d0 # index + disp
1374 1.1 is add.l %d0,%a0 # An + (index + disp)
1375 1.1 is
1376 1.1 is mov.l (%sp)+,%d2 # restore old d2
1377 1.1 is rts
1378 1.1 is
1379 1.1 is ######################
1380 1.1 is # Immediate: #<data> #
1381 1.1 is #########################################################################
1382 1.1 is # word, long: <ea> of the data is the current extension word #
1383 1.1 is # pointer value. new extension word pointer is simply the old #
1384 1.1 is # plus the number of bytes in the data type(2 or 4). #
1385 1.1 is #########################################################################
1386 1.1 is immediate:
1387 1.1 is mov.b &immed_flg,SPCOND_FLG(%a6) # set immediate flag
1388 1.1 is
1389 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch extension word ptr
1390 1.1 is rts
1391 1.1 is
1392 1.1 is ###########################
1393 1.1 is # Absolute short: (XXX).W #
1394 1.1 is ###########################
1395 1.1 is abs_short:
1396 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1397 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1398 1.1 is bsr.l _imem_read_word # fetch short address
1399 1.1 is
1400 1.1 is tst.l %d1 # ifetch error?
1401 1.1 is bne.l isp_iacc # yes
1402 1.1 is
1403 1.1 is mov.w %d0,%a0 # return <ea> in a0
1404 1.1 is rts
1405 1.1 is
1406 1.1 is ##########################
1407 1.1 is # Absolute long: (XXX).L #
1408 1.1 is ##########################
1409 1.1 is abs_long:
1410 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1411 1.1 is addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
1412 1.1 is bsr.l _imem_read_long # fetch long address
1413 1.1 is
1414 1.1 is tst.l %d1 # ifetch error?
1415 1.1 is bne.l isp_iacc # yes
1416 1.1 is
1417 1.1 is mov.l %d0,%a0 # return <ea> in a0
1418 1.1 is rts
1419 1.1 is
1420 1.1 is #######################################################
1421 1.1 is # Program counter indirect w/ displacement: (d16, PC) #
1422 1.1 is #######################################################
1423 1.1 is pc_ind:
1424 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1425 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1426 1.1 is bsr.l _imem_read_word # fetch word displacement
1427 1.1 is
1428 1.1 is tst.l %d1 # ifetch error?
1429 1.1 is bne.l isp_iacc # yes
1430 1.1 is
1431 1.1 is mov.w %d0,%a0 # sign extend displacement
1432 1.1 is
1433 1.1 is add.l EXC_EXTWPTR(%a6),%a0 # pc + d16
1434 1.1 is
1435 1.1 is # _imem_read_word() increased the extwptr by 2. need to adjust here.
1436 1.1 is subq.l &0x2,%a0 # adjust <ea>
1437 1.1 is
1438 1.1 is rts
1439 1.1 is
1440 1.1 is ##########################################################
1441 1.1 is # PC indirect w/ index(8-bit displacement): (d8, PC, An) #
1442 1.1 is # " " w/ " (base displacement): (bd, PC, An) #
1443 1.1 is # PC memory indirect postindexed: ([bd, PC], Xn, od) #
1444 1.1 is # PC memory indirect preindexed: ([bd, PC, Xn], od) #
1445 1.1 is ##########################################################
1446 1.1 is pc_ind_ext:
1447 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1448 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1449 1.1 is bsr.l _imem_read_word # fetch ext word
1450 1.1 is
1451 1.1 is tst.l %d1 # ifetch error?
1452 1.1 is bne.l isp_iacc # yes
1453 1.1 is
1454 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # put base in a0
1455 1.1 is subq.l &0x2,%a0 # adjust base
1456 1.1 is
1457 1.1 is btst &0x8,%d0 # is disp only 8 bits?
1458 1.1 is beq.b pc_ind_index_8bit # yes
1459 1.1 is
1460 1.1 is # the indexed addressing mode uses a base displacement of size
1461 1.1 is # word or long
1462 1.1 is movm.l &0x3c00,-(%sp) # save d2-d5
1463 1.1 is
1464 1.1 is mov.l %d0,%d5 # put extword in d5
1465 1.1 is mov.l %a0,%d3 # put base in d3
1466 1.1 is
1467 1.1 is bra.l calc_mem_ind # calc memory indirect
1468 1.1 is
1469 1.1 is pc_ind_index_8bit:
1470 1.1 is mov.l %d2,-(%sp) # create a temp register
1471 1.1 is
1472 1.1 is mov.l %d0,%d1 # make extword copy
1473 1.1 is rol.w &0x4,%d1 # rotate reg num into place
1474 1.1 is andi.w &0xf,%d1 # extract register number
1475 1.1 is
1476 1.1 is mov.l (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
1477 1.1 is
1478 1.1 is btst &0xb,%d0 # is index word or long?
1479 1.1 is bne.b pii8_long # long
1480 1.1 is ext.l %d1 # sign extend word index
1481 1.1 is pii8_long:
1482 1.1 is mov.l %d0,%d2 # make extword copy
1483 1.1 is rol.w &0x7,%d2 # rotate scale value into place
1484 1.1 is andi.l &0x3,%d2 # extract scale value
1485 1.1 is
1486 1.1 is lsl.l %d2,%d1 # shift index by scale
1487 1.1 is
1488 1.1 is extb.l %d0 # sign extend displacement
1489 1.1 is add.l %d1,%d0 # index + disp
1490 1.1 is add.l %d0,%a0 # An + (index + disp)
1491 1.1 is
1492 1.1 is mov.l (%sp)+,%d2 # restore temp register
1493 1.1 is
1494 1.1 is rts
1495 1.1 is
1496 1.1 is # a5 = exc_extwptr (global to uaeh)
1497 1.1 is # a4 = exc_opword (global to uaeh)
1498 1.1 is # a3 = exc_dregs (global to uaeh)
1499 1.1 is
1500 1.1 is # d2 = index (internal " " )
1501 1.1 is # d3 = base (internal " " )
1502 1.1 is # d4 = od (internal " " )
1503 1.1 is # d5 = extword (internal " " )
1504 1.1 is calc_mem_ind:
1505 1.1 is btst &0x6,%d5 # is the index suppressed?
1506 1.1 is beq.b calc_index
1507 1.1 is clr.l %d2 # yes, so index = 0
1508 1.1 is bra.b base_supp_ck
1509 1.1 is calc_index:
1510 1.1 is bfextu %d5{&16:&4},%d2
1511 1.1 is mov.l (EXC_DREGS,%a6,%d2.w*4),%d2
1512 1.1 is btst &0xb,%d5 # is index word or long?
1513 1.1 is bne.b no_ext
1514 1.1 is ext.l %d2
1515 1.1 is no_ext:
1516 1.1 is bfextu %d5{&21:&2},%d0
1517 1.1 is lsl.l %d0,%d2
1518 1.1 is base_supp_ck:
1519 1.1 is btst &0x7,%d5 # is the bd suppressed?
1520 1.1 is beq.b no_base_sup
1521 1.1 is clr.l %d3
1522 1.1 is no_base_sup:
1523 1.1 is bfextu %d5{&26:&2},%d0 # get bd size
1524 1.1 is # beq.l _error # if (size == 0) it's reserved
1525 1.1 is cmpi.b %d0,&2
1526 1.1 is blt.b no_bd
1527 1.1 is beq.b get_word_bd
1528 1.1 is
1529 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1530 1.1 is addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
1531 1.1 is bsr.l _imem_read_long
1532 1.1 is
1533 1.1 is tst.l %d1 # ifetch error?
1534 1.1 is bne.l isp_iacc # yes
1535 1.1 is
1536 1.1 is bra.b chk_ind
1537 1.1 is get_word_bd:
1538 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1539 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1540 1.1 is bsr.l _imem_read_word
1541 1.1 is
1542 1.1 is tst.l %d1 # ifetch error?
1543 1.1 is bne.l isp_iacc # yes
1544 1.1 is
1545 1.1 is ext.l %d0 # sign extend bd
1546 1.1 is
1547 1.1 is chk_ind:
1548 1.1 is add.l %d0,%d3 # base += bd
1549 1.1 is no_bd:
1550 1.1 is bfextu %d5{&30:&2},%d0 # is od suppressed?
1551 1.1 is beq.w aii_bd
1552 1.1 is cmpi.b %d0,&0x2
1553 1.1 is blt.b null_od
1554 1.1 is beq.b word_od
1555 1.1 is
1556 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1557 1.1 is addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
1558 1.1 is bsr.l _imem_read_long
1559 1.1 is
1560 1.1 is tst.l %d1 # ifetch error?
1561 1.1 is bne.l isp_iacc # yes
1562 1.1 is
1563 1.1 is bra.b add_them
1564 1.1 is
1565 1.1 is word_od:
1566 1.1 is mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
1567 1.1 is addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
1568 1.1 is bsr.l _imem_read_word
1569 1.1 is
1570 1.1 is tst.l %d1 # ifetch error?
1571 1.1 is bne.l isp_iacc # yes
1572 1.1 is
1573 1.1 is ext.l %d0 # sign extend od
1574 1.1 is bra.b add_them
1575 1.1 is
1576 1.1 is null_od:
1577 1.1 is clr.l %d0
1578 1.1 is add_them:
1579 1.1 is mov.l %d0,%d4
1580 1.1 is btst &0x2,%d5 # pre or post indexing?
1581 1.1 is beq.b pre_indexed
1582 1.1 is
1583 1.1 is mov.l %d3,%a0
1584 1.1 is bsr.l _dmem_read_long
1585 1.1 is
1586 1.1 is tst.l %d1 # dfetch error?
1587 1.1 is bne.b calc_ea_err # yes
1588 1.1 is
1589 1.1 is add.l %d2,%d0 # <ea> += index
1590 1.1 is add.l %d4,%d0 # <ea> += od
1591 1.1 is bra.b done_ea
1592 1.1 is
1593 1.1 is pre_indexed:
1594 1.1 is add.l %d2,%d3 # preindexing
1595 1.1 is mov.l %d3,%a0
1596 1.1 is bsr.l _dmem_read_long
1597 1.1 is
1598 1.1 is tst.l %d1 # ifetch error?
1599 1.1 is bne.b calc_ea_err # yes
1600 1.1 is
1601 1.1 is add.l %d4,%d0 # ea += od
1602 1.1 is bra.b done_ea
1603 1.1 is
1604 1.1 is aii_bd:
1605 1.1 is add.l %d2,%d3 # ea = (base + bd) + index
1606 1.1 is mov.l %d3,%d0
1607 1.1 is done_ea:
1608 1.1 is mov.l %d0,%a0
1609 1.1 is
1610 1.1 is movm.l (%sp)+,&0x003c # restore d2-d5
1611 1.1 is rts
1612 1.1 is
1613 1.1 is # if dmem_read_long() returns a fail message in d1, the package
1614 1.1 is # must create an access error frame. here, we pass a skeleton fslw
1615 1.1 is # and the failing address to the routine that creates the new frame.
1616 1.1 is # FSLW:
1617 1.1 is # read = true
1618 1.1 is # size = longword
1619 1.1 is # TM = data
1620 1.1 is # software emulation error = true
1621 1.1 is calc_ea_err:
1622 1.1 is mov.l %d3,%a0 # pass failing address
1623 1.1 is mov.l &0x01010001,%d0 # pass fslw
1624 1.1 is bra.l isp_dacc
1625 1.1 is
1626 1.1 is #########################################################################
1627 1.1 is # XDEF **************************************************************** #
1628 1.1 is # _moveperipheral(): routine to emulate movep instruction #
1629 1.1 is # #
1630 1.1 is # XREF **************************************************************** #
1631 1.1 is # _dmem_read_byte() - read byte from memory #
1632 1.1 is # _dmem_write_byte() - write byte to memory #
1633 1.1 is # isp_dacc() - handle data access error exception #
1634 1.1 is # #
1635 1.1 is # INPUT *************************************************************** #
1636 1.1 is # none #
1637 1.1 is # #
1638 1.1 is # OUTPUT ************************************************************** #
1639 1.1 is # If exiting through isp_dacc... #
1640 1.1 is # a0 = failing address #
1641 1.1 is # d0 = FSLW #
1642 1.1 is # else #
1643 1.1 is # none #
1644 1.1 is # #
1645 1.1 is # ALGORITHM *********************************************************** #
1646 1.1 is # Decode the movep instruction words stored at EXC_OPWORD and #
1647 1.1 is # either read or write the required bytes from/to memory. Use the #
1648 1.1 is # _dmem_{read,write}_byte() routines. If one of the memory routines #
1649 1.1 is # returns a failing value, we must pass the failing address and a FSLW #
1650 1.1 is # to the _isp_dacc() routine. #
1651 1.1 is # Since this instruction is used to access peripherals, make sure #
1652 1.1 is # to only access the required bytes. #
1653 1.1 is # #
1654 1.1 is #########################################################################
1655 1.1 is
1656 1.1 is ###########################
1657 1.1 is # movep.(w,l) Dx,(d,Ay) #
1658 1.1 is # movep.(w,l) (d,Ay),Dx #
1659 1.1 is ###########################
1660 1.1 is global _moveperipheral
1661 1.1 is _moveperipheral:
1662 1.1 is mov.w EXC_OPWORD(%a6),%d1 # fetch the opcode word
1663 1.1 is
1664 1.1 is mov.b %d1,%d0
1665 1.1 is and.w &0x7,%d0 # extract Ay from opcode word
1666 1.1 is
1667 1.1 is mov.l (EXC_AREGS,%a6,%d0.w*4),%a0 # fetch ay
1668 1.1 is
1669 1.1 is add.w EXC_EXTWORD(%a6),%a0 # add: an + sgn_ext(disp)
1670 1.1 is
1671 1.1 is btst &0x7,%d1 # (reg 2 mem) or (mem 2 reg)
1672 1.1 is beq.w mem2reg
1673 1.1 is
1674 1.1 is # reg2mem: fetch dx, then write it to memory
1675 1.1 is reg2mem:
1676 1.1 is mov.w %d1,%d0
1677 1.1 is rol.w &0x7,%d0
1678 1.1 is and.w &0x7,%d0 # extract Dx from opcode word
1679 1.1 is
1680 1.1 is mov.l (EXC_DREGS,%a6,%d0.w*4), %d0 # fetch dx
1681 1.1 is
1682 1.1 is btst &0x6,%d1 # word or long operation?
1683 1.1 is beq.b r2mwtrans
1684 1.1 is
1685 1.1 is # a0 = dst addr
1686 1.1 is # d0 = Dx
1687 1.1 is r2mltrans:
1688 1.1 is mov.l %d0,%d2 # store data
1689 1.1 is mov.l %a0,%a2 # store addr
1690 1.1 is rol.l &0x8,%d2
1691 1.1 is mov.l %d2,%d0
1692 1.1 is
1693 1.1 is bsr.l _dmem_write_byte # os : write hi
1694 1.1 is
1695 1.1 is tst.l %d1 # dfetch error?
1696 1.1 is bne.w movp_write_err # yes
1697 1.1 is
1698 1.1 is add.w &0x2,%a2 # incr addr
1699 1.1 is mov.l %a2,%a0
1700 1.1 is rol.l &0x8,%d2
1701 1.1 is mov.l %d2,%d0
1702 1.1 is
1703 1.1 is bsr.l _dmem_write_byte # os : write lo
1704 1.1 is
1705 1.1 is tst.l %d1 # dfetch error?
1706 1.1 is bne.w movp_write_err # yes
1707 1.1 is
1708 1.1 is add.w &0x2,%a2 # incr addr
1709 1.1 is mov.l %a2,%a0
1710 1.1 is rol.l &0x8,%d2
1711 1.1 is mov.l %d2,%d0
1712 1.1 is
1713 1.1 is bsr.l _dmem_write_byte # os : write lo
1714 1.1 is
1715 1.1 is tst.l %d1 # dfetch error?
1716 1.1 is bne.w movp_write_err # yes
1717 1.1 is
1718 1.1 is add.w &0x2,%a2 # incr addr
1719 1.1 is mov.l %a2,%a0
1720 1.1 is rol.l &0x8,%d2
1721 1.1 is mov.l %d2,%d0
1722 1.1 is
1723 1.1 is bsr.l _dmem_write_byte # os : write lo
1724 1.1 is
1725 1.1 is tst.l %d1 # dfetch error?
1726 1.1 is bne.w movp_write_err # yes
1727 1.1 is
1728 1.1 is rts
1729 1.1 is
1730 1.1 is # a0 = dst addr
1731 1.1 is # d0 = Dx
1732 1.1 is r2mwtrans:
1733 1.1 is mov.l %d0,%d2 # store data
1734 1.1 is mov.l %a0,%a2 # store addr
1735 1.1 is lsr.w &0x8,%d0
1736 1.1 is
1737 1.1 is bsr.l _dmem_write_byte # os : write hi
1738 1.1 is
1739 1.1 is tst.l %d1 # dfetch error?
1740 1.1 is bne.w movp_write_err # yes
1741 1.1 is
1742 1.1 is add.w &0x2,%a2
1743 1.1 is mov.l %a2,%a0
1744 1.1 is mov.l %d2,%d0
1745 1.1 is
1746 1.1 is bsr.l _dmem_write_byte # os : write lo
1747 1.1 is
1748 1.1 is tst.l %d1 # dfetch error?
1749 1.1 is bne.w movp_write_err # yes
1750 1.1 is
1751 1.1 is rts
1752 1.1 is
1753 1.1 is # mem2reg: read bytes from memory.
1754 1.1 is # determines the dest register, and then writes the bytes into it.
1755 1.1 is mem2reg:
1756 1.1 is btst &0x6,%d1 # word or long operation?
1757 1.1 is beq.b m2rwtrans
1758 1.1 is
1759 1.1 is # a0 = dst addr
1760 1.1 is m2rltrans:
1761 1.1 is mov.l %a0,%a2 # store addr
1762 1.1 is
1763 1.1 is bsr.l _dmem_read_byte # read first byte
1764 1.1 is
1765 1.1 is tst.l %d1 # dfetch error?
1766 1.1 is bne.w movp_read_err # yes
1767 1.1 is
1768 1.1 is mov.l %d0,%d2
1769 1.1 is
1770 1.1 is add.w &0x2,%a2 # incr addr by 2 bytes
1771 1.1 is mov.l %a2,%a0
1772 1.1 is
1773 1.1 is bsr.l _dmem_read_byte # read second byte
1774 1.1 is
1775 1.1 is tst.l %d1 # dfetch error?
1776 1.1 is bne.w movp_read_err # yes
1777 1.1 is
1778 1.1 is lsl.w &0x8,%d2
1779 1.1 is mov.b %d0,%d2 # append bytes
1780 1.1 is
1781 1.1 is add.w &0x2,%a2 # incr addr by 2 bytes
1782 1.1 is mov.l %a2,%a0
1783 1.1 is
1784 1.1 is bsr.l _dmem_read_byte # read second byte
1785 1.1 is
1786 1.1 is tst.l %d1 # dfetch error?
1787 1.1 is bne.w movp_read_err # yes
1788 1.1 is
1789 1.1 is lsl.l &0x8,%d2
1790 1.1 is mov.b %d0,%d2 # append bytes
1791 1.1 is
1792 1.1 is add.w &0x2,%a2 # incr addr by 2 bytes
1793 1.1 is mov.l %a2,%a0
1794 1.1 is
1795 1.1 is bsr.l _dmem_read_byte # read second byte
1796 1.1 is
1797 1.1 is tst.l %d1 # dfetch error?
1798 1.1 is bne.w movp_read_err # yes
1799 1.1 is
1800 1.1 is lsl.l &0x8,%d2
1801 1.1 is mov.b %d0,%d2 # append bytes
1802 1.1 is
1803 1.1 is mov.b EXC_OPWORD(%a6),%d1
1804 1.1 is lsr.b &0x1,%d1
1805 1.1 is and.w &0x7,%d1 # extract Dx from opcode word
1806 1.1 is
1807 1.1 is mov.l %d2,(EXC_DREGS,%a6,%d1.w*4) # store dx
1808 1.1 is
1809 1.1 is rts
1810 1.1 is
1811 1.1 is # a0 = dst addr
1812 1.1 is m2rwtrans:
1813 1.1 is mov.l %a0,%a2 # store addr
1814 1.1 is
1815 1.1 is bsr.l _dmem_read_byte # read first byte
1816 1.1 is
1817 1.1 is tst.l %d1 # dfetch error?
1818 1.1 is bne.w movp_read_err # yes
1819 1.1 is
1820 1.1 is mov.l %d0,%d2
1821 1.1 is
1822 1.1 is add.w &0x2,%a2 # incr addr by 2 bytes
1823 1.1 is mov.l %a2,%a0
1824 1.1 is
1825 1.1 is bsr.l _dmem_read_byte # read second byte
1826 1.1 is
1827 1.1 is tst.l %d1 # dfetch error?
1828 1.1 is bne.w movp_read_err # yes
1829 1.1 is
1830 1.1 is lsl.w &0x8,%d2
1831 1.1 is mov.b %d0,%d2 # append bytes
1832 1.1 is
1833 1.1 is mov.b EXC_OPWORD(%a6),%d1
1834 1.1 is lsr.b &0x1,%d1
1835 1.1 is and.w &0x7,%d1 # extract Dx from opcode word
1836 1.1 is
1837 1.1 is mov.w %d2,(EXC_DREGS+2,%a6,%d1.w*4) # store dx
1838 1.1 is
1839 1.1 is rts
1840 1.1 is
1841 1.1 is # if dmem_{read,write}_byte() returns a fail message in d1, the package
1842 1.1 is # must create an access error frame. here, we pass a skeleton fslw
1843 1.1 is # and the failing address to the routine that creates the new frame.
1844 1.1 is # FSLW:
1845 1.1 is # write = true
1846 1.1 is # size = byte
1847 1.1 is # TM = data
1848 1.1 is # software emulation error = true
1849 1.1 is movp_write_err:
1850 1.1 is mov.l %a2,%a0 # pass failing address
1851 1.1 is mov.l &0x00a10001,%d0 # pass fslw
1852 1.1 is bra.l isp_dacc
1853 1.1 is
1854 1.1 is # FSLW:
1855 1.1 is # read = true
1856 1.1 is # size = byte
1857 1.1 is # TM = data
1858 1.1 is # software emulation error = true
1859 1.1 is movp_read_err:
1860 1.1 is mov.l %a2,%a0 # pass failing address
1861 1.1 is mov.l &0x01210001,%d0 # pass fslw
1862 1.1 is bra.l isp_dacc
1863 1.1 is
1864 1.1 is #########################################################################
1865 1.1 is # XDEF **************************************************************** #
1866 1.1 is # _chk2_cmp2(): routine to emulate chk2/cmp2 instructions #
1867 1.1 is # #
1868 1.1 is # XREF **************************************************************** #
1869 1.1 is # _calc_ea(): calculate effective address #
1870 1.1 is # _dmem_read_long(): read operands #
1871 1.1 is # _dmem_read_word(): read operands #
1872 1.1 is # isp_dacc(): handle data access error exception #
1873 1.1 is # #
1874 1.1 is # INPUT *************************************************************** #
1875 1.1 is # none #
1876 1.1 is # #
1877 1.1 is # OUTPUT ************************************************************** #
1878 1.1 is # If exiting through isp_dacc... #
1879 1.1 is # a0 = failing address #
1880 1.1 is # d0 = FSLW #
1881 1.1 is # else #
1882 1.1 is # none #
1883 1.1 is # #
1884 1.1 is # ALGORITHM *********************************************************** #
1885 1.1 is # First, calculate the effective address, then fetch the byte, #
1886 1.1 is # word, or longword sized operands. Then, in the interest of #
1887 1.1 is # simplicity, all operands are converted to longword size whether the #
1888 1.1 is # operation is byte, word, or long. The bounds are sign extended #
1889 1.3 kamil # accordingly. If Rn is a data register, Rn is also sign extended. If #
1890 1.1 is # Rn is an address register, it need not be sign extended since the #
1891 1.1 is # full register is always used. #
1892 1.1 is # The comparisons are made and the condition codes calculated. #
1893 1.1 is # If the instruction is chk2 and the Rn value is out-of-bounds, set #
1894 1.1 is # the ichk_flg in SPCOND_FLG. #
1895 1.1 is # If the memory fetch returns a failing value, pass the failing #
1896 1.1 is # address and FSLW to the isp_dacc() routine. #
1897 1.1 is # #
1898 1.1 is #########################################################################
1899 1.1 is
1900 1.1 is global _chk2_cmp2
1901 1.1 is _chk2_cmp2:
1902 1.1 is
1903 1.1 is # passing size parameter doesn't matter since chk2 & cmp2 can't do
1904 1.1 is # either predecrement, postincrement, or immediate.
1905 1.1 is bsr.l _calc_ea # calculate <ea>
1906 1.1 is
1907 1.1 is mov.b EXC_EXTWORD(%a6), %d0 # fetch hi extension word
1908 1.1 is rol.b &0x4, %d0 # rotate reg bits into lo
1909 1.1 is and.w &0xf, %d0 # extract reg bits
1910 1.1 is
1911 1.1 is mov.l (EXC_DREGS,%a6,%d0.w*4), %d2 # get regval
1912 1.1 is
1913 1.1 is cmpi.b EXC_OPWORD(%a6), &0x2 # what size is operation?
1914 1.1 is blt.b chk2_cmp2_byte # size == byte
1915 1.1 is beq.b chk2_cmp2_word # size == word
1916 1.1 is
1917 1.1 is # the bounds are longword size. call routine to read the lower
1918 1.1 is # bound into d0 and the higher bound into d1.
1919 1.1 is chk2_cmp2_long:
1920 1.1 is mov.l %a0,%a2 # save copy of <ea>
1921 1.1 is bsr.l _dmem_read_long # fetch long lower bound
1922 1.1 is
1923 1.1 is tst.l %d1 # dfetch error?
1924 1.1 is bne.w chk2_cmp2_err_l # yes
1925 1.1 is
1926 1.1 is mov.l %d0,%d3 # save long lower bound
1927 1.1 is addq.l &0x4,%a2
1928 1.1 is mov.l %a2,%a0 # pass <ea> of long upper bound
1929 1.1 is bsr.l _dmem_read_long # fetch long upper bound
1930 1.1 is
1931 1.1 is tst.l %d1 # dfetch error?
1932 1.1 is bne.w chk2_cmp2_err_l # yes
1933 1.1 is
1934 1.1 is mov.l %d0,%d1 # long upper bound in d1
1935 1.1 is mov.l %d3,%d0 # long lower bound in d0
1936 1.1 is bra.w chk2_cmp2_compare # go do the compare emulation
1937 1.1 is
1938 1.1 is # the bounds are word size. fetch them in one subroutine call by
1939 1.1 is # reading a longword. sign extend both. if it's a data operation,
1940 1.1 is # sign extend Rn to long, also.
1941 1.1 is chk2_cmp2_word:
1942 1.1 is mov.l %a0,%a2
1943 1.1 is bsr.l _dmem_read_long # fetch 2 word bounds
1944 1.1 is
1945 1.1 is tst.l %d1 # dfetch error?
1946 1.1 is bne.w chk2_cmp2_err_l # yes
1947 1.1 is
1948 1.1 is mov.w %d0, %d1 # place hi in %d1
1949 1.1 is swap %d0 # place lo in %d0
1950 1.1 is
1951 1.1 is ext.l %d0 # sign extend lo bnd
1952 1.1 is ext.l %d1 # sign extend hi bnd
1953 1.1 is
1954 1.1 is btst &0x7, EXC_EXTWORD(%a6) # address compare?
1955 1.1 is bne.w chk2_cmp2_compare # yes; don't sign extend
1956 1.1 is
1957 1.1 is # operation is a data register compare.
1958 1.1 is # sign extend word to long so we can do simple longword compares.
1959 1.1 is ext.l %d2 # sign extend data word
1960 1.1 is bra.w chk2_cmp2_compare # go emulate compare
1961 1.1 is
1962 1.1 is # the bounds are byte size. fetch them in one subroutine call by
1963 1.1 is # reading a word. sign extend both. if it's a data operation,
1964 1.1 is # sign extend Rn to long, also.
1965 1.1 is chk2_cmp2_byte:
1966 1.1 is mov.l %a0,%a2
1967 1.1 is bsr.l _dmem_read_word # fetch 2 byte bounds
1968 1.1 is
1969 1.1 is tst.l %d1 # dfetch error?
1970 1.1 is bne.w chk2_cmp2_err_w # yes
1971 1.1 is
1972 1.1 is mov.b %d0, %d1 # place hi in %d1
1973 1.1 is lsr.w &0x8, %d0 # place lo in %d0
1974 1.1 is
1975 1.1 is extb.l %d0 # sign extend lo bnd
1976 1.1 is extb.l %d1 # sign extend hi bnd
1977 1.1 is
1978 1.1 is btst &0x7, EXC_EXTWORD(%a6) # address compare?
1979 1.1 is bne.b chk2_cmp2_compare # yes; don't sign extend
1980 1.1 is
1981 1.1 is # operation is a data register compare.
1982 1.1 is # sign extend byte to long so we can do simple longword compares.
1983 1.1 is extb.l %d2 # sign extend data byte
1984 1.1 is
1985 1.1 is #
1986 1.1 is # To set the ccodes correctly:
1987 1.1 is # (1) save 'Z' bit from (Rn - lo)
1988 1.1 is # (2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi))
1989 1.1 is # (3) keep 'X', 'N', and 'V' from before instruction
1990 1.1 is # (4) combine ccodes
1991 1.1 is #
1992 1.1 is chk2_cmp2_compare:
1993 1.1 is sub.l %d0, %d2 # (Rn - lo)
1994 1.1 is mov.w %cc, %d3 # fetch resulting ccodes
1995 1.1 is andi.b &0x4, %d3 # keep 'Z' bit
1996 1.1 is sub.l %d0, %d1 # (hi - lo)
1997 1.1 is cmp.l %d1,%d2 # ((hi - lo) - (Rn - hi))
1998 1.1 is
1999 1.1 is mov.w %cc, %d4 # fetch resulting ccodes
2000 1.1 is or.b %d4, %d3 # combine w/ earlier ccodes
2001 1.1 is andi.b &0x5, %d3 # keep 'Z' and 'N'
2002 1.1 is
2003 1.1 is mov.w EXC_CC(%a6), %d4 # fetch old ccodes
2004 1.1 is andi.b &0x1a, %d4 # keep 'X','N','V' bits
2005 1.1 is or.b %d3, %d4 # insert new ccodes
2006 1.1 is mov.w %d4, EXC_CC(%a6) # save new ccodes
2007 1.1 is
2008 1.1 is btst &0x3, EXC_EXTWORD(%a6) # separate chk2,cmp2
2009 1.1 is bne.b chk2_finish # it's a chk2
2010 1.1 is
2011 1.1 is rts
2012 1.1 is
2013 1.1 is # this code handles the only difference between chk2 and cmp2. chk2 would
2014 1.1 is # have trapped out if the value was out of bounds. we check this by seeing
2015 1.1 is # if the 'N' bit was set by the operation.
2016 1.1 is chk2_finish:
2017 1.1 is btst &0x0, %d4 # is 'N' bit set?
2018 1.1 is bne.b chk2_trap # yes;chk2 should trap
2019 1.1 is rts
2020 1.1 is chk2_trap:
2021 1.1 is mov.b &ichk_flg,SPCOND_FLG(%a6) # set "special case" flag
2022 1.1 is rts
2023 1.1 is
2024 1.1 is # if dmem_read_{long,word}() returns a fail message in d1, the package
2025 1.1 is # must create an access error frame. here, we pass a skeleton fslw
2026 1.1 is # and the failing address to the routine that creates the new frame.
2027 1.1 is # FSLW:
2028 1.1 is # read = true
2029 1.1 is # size = longword
2030 1.1 is # TM = data
2031 1.1 is # software emulation error = true
2032 1.1 is chk2_cmp2_err_l:
2033 1.1 is mov.l %a2,%a0 # pass failing address
2034 1.1 is mov.l &0x01010001,%d0 # pass fslw
2035 1.1 is bra.l isp_dacc
2036 1.1 is
2037 1.1 is # FSLW:
2038 1.1 is # read = true
2039 1.1 is # size = word
2040 1.1 is # TM = data
2041 1.1 is # software emulation error = true
2042 1.1 is chk2_cmp2_err_w:
2043 1.1 is mov.l %a2,%a0 # pass failing address
2044 1.1 is mov.l &0x01410001,%d0 # pass fslw
2045 1.1 is bra.l isp_dacc
2046 1.1 is
2047 1.1 is #########################################################################
2048 1.1 is # XDEF **************************************************************** #
2049 1.1 is # _div64(): routine to emulate div{u,s}.l <ea>,Dr:Dq #
2050 1.1 is # 64/32->32r:32q #
2051 1.1 is # #
2052 1.1 is # XREF **************************************************************** #
2053 1.1 is # _calc_ea() - calculate effective address #
2054 1.1 is # isp_iacc() - handle instruction access error exception #
2055 1.1 is # isp_dacc() - handle data access error exception #
2056 1.1 is # isp_restore() - restore An on access error w/ -() or ()+ #
2057 1.1 is # #
2058 1.1 is # INPUT *************************************************************** #
2059 1.1 is # none #
2060 1.1 is # #
2061 1.1 is # OUTPUT ************************************************************** #
2062 1.1 is # If exiting through isp_dacc... #
2063 1.1 is # a0 = failing address #
2064 1.1 is # d0 = FSLW #
2065 1.1 is # else #
2066 1.1 is # none #
2067 1.1 is # #
2068 1.1 is # ALGORITHM *********************************************************** #
2069 1.1 is # First, decode the operand location. If it's in Dn, fetch from #
2070 1.1 is # the stack. If it's in memory, use _calc_ea() to calculate the #
2071 1.1 is # effective address. Use _dmem_read_long() to fetch at that address. #
2072 1.1 is # Unless the operand is immediate data. Then use _imem_read_long(). #
2073 1.1 is # Send failures to isp_dacc() or isp_iacc() as appropriate. #
2074 1.1 is # If the operands are signed, make them unsigned and save the #
2075 1.1 is # sign info for later. Separate out special cases like divide-by-zero #
2076 1.1 is # or 32-bit divides if possible. Else, use a special math algorithm #
2077 1.1 is # to calculate the result. #
2078 1.1 is # Restore sign info if signed instruction. Set the condition #
2079 1.1 is # codes. Set idbyz_flg in SPCOND_FLG if divisor was zero. Store the #
2080 1.1 is # quotient and remainder in the appropriate data registers on the stack.#
2081 1.1 is # #
2082 1.1 is #########################################################################
2083 1.1 is
2084 1.1 is set NDIVISOR, EXC_TEMP+0x0
2085 1.1 is set NDIVIDEND, EXC_TEMP+0x1
2086 1.1 is set NDRSAVE, EXC_TEMP+0x2
2087 1.1 is set NDQSAVE, EXC_TEMP+0x4
2088 1.1 is set DDSECOND, EXC_TEMP+0x6
2089 1.1 is set DDQUOTIENT, EXC_TEMP+0x8
2090 1.1 is set DDNORMAL, EXC_TEMP+0xc
2091 1.1 is
2092 1.1 is global _div64
2093 1.1 is #############
2094 1.1 is # div(u,s)l #
2095 1.1 is #############
2096 1.1 is _div64:
2097 1.1 is mov.b EXC_OPWORD+1(%a6), %d0
2098 1.1 is andi.b &0x38, %d0 # extract src mode
2099 1.1 is
2100 1.1 is bne.w dcontrolmodel_s # %dn dest or control mode?
2101 1.1 is
2102 1.1 is mov.b EXC_OPWORD+1(%a6), %d0 # extract Dn from opcode
2103 1.1 is andi.w &0x7, %d0
2104 1.1 is mov.l (EXC_DREGS,%a6,%d0.w*4), %d7 # fetch divisor from register
2105 1.1 is
2106 1.1 is dgotsrcl:
2107 1.1 is beq.w div64eq0 # divisor is = 0!!!
2108 1.1 is
2109 1.1 is mov.b EXC_EXTWORD+1(%a6), %d0 # extract Dr from extword
2110 1.1 is mov.b EXC_EXTWORD(%a6), %d1 # extract Dq from extword
2111 1.1 is and.w &0x7, %d0
2112 1.1 is lsr.b &0x4, %d1
2113 1.1 is and.w &0x7, %d1
2114 1.1 is mov.w %d0, NDRSAVE(%a6) # save Dr for later
2115 1.1 is mov.w %d1, NDQSAVE(%a6) # save Dq for later
2116 1.1 is
2117 1.1 is # fetch %dr and %dq directly off stack since all regs are saved there
2118 1.1 is mov.l (EXC_DREGS,%a6,%d0.w*4), %d5 # get dividend hi
2119 1.1 is mov.l (EXC_DREGS,%a6,%d1.w*4), %d6 # get dividend lo
2120 1.1 is
2121 1.1 is # separate signed and unsigned divide
2122 1.1 is btst &0x3, EXC_EXTWORD(%a6) # signed or unsigned?
2123 1.1 is beq.b dspecialcases # use positive divide
2124 1.1 is
2125 1.1 is # save the sign of the divisor
2126 1.1 is # make divisor unsigned if it's negative
2127 1.1 is tst.l %d7 # chk sign of divisor
2128 1.1 is slt NDIVISOR(%a6) # save sign of divisor
2129 1.1 is bpl.b dsgndividend
2130 1.1 is neg.l %d7 # complement negative divisor
2131 1.1 is
2132 1.1 is # save the sign of the dividend
2133 1.1 is # make dividend unsigned if it's negative
2134 1.1 is dsgndividend:
2135 1.1 is tst.l %d5 # chk sign of hi(dividend)
2136 1.1 is slt NDIVIDEND(%a6) # save sign of dividend
2137 1.1 is bpl.b dspecialcases
2138 1.1 is
2139 1.1 is mov.w &0x0, %cc # clear 'X' cc bit
2140 1.1 is negx.l %d6 # complement signed dividend
2141 1.1 is negx.l %d5
2142 1.1 is
2143 1.1 is # extract some special cases:
2144 1.1 is # - is (dividend == 0) ?
2145 1.1 is # - is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div)
2146 1.1 is dspecialcases:
2147 1.1 is tst.l %d5 # is (hi(dividend) == 0)
2148 1.1 is bne.b dnormaldivide # no, so try it the long way
2149 1.1 is
2150 1.1 is tst.l %d6 # is (lo(dividend) == 0), too
2151 1.1 is beq.w ddone # yes, so (dividend == 0)
2152 1.1 is
2153 1.1 is cmp.l %d7,%d6 # is (divisor <= lo(dividend))
2154 1.1 is bls.b d32bitdivide # yes, so use 32 bit divide
2155 1.1 is
2156 1.1 is exg %d5,%d6 # q = 0, r = dividend
2157 1.1 is bra.w divfinish # can't divide, we're done.
2158 1.1 is
2159 1.1 is d32bitdivide:
2160 1.1 is tdivu.l %d7, %d5:%d6 # it's only a 32/32 bit div!
2161 1.1 is
2162 1.1 is bra.b divfinish
2163 1.1 is
2164 1.1 is dnormaldivide:
2165 1.1 is # last special case:
2166 1.1 is # - is hi(dividend) >= divisor ? if yes, then overflow
2167 1.1 is cmp.l %d7,%d5
2168 1.1 is bls.b ddovf # answer won't fit in 32 bits
2169 1.1 is
2170 1.1 is # perform the divide algorithm:
2171 1.1 is bsr.l dclassical # do int divide
2172 1.1 is
2173 1.1 is # separate into signed and unsigned finishes.
2174 1.1 is divfinish:
2175 1.1 is btst &0x3, EXC_EXTWORD(%a6) # do divs, divu separately
2176 1.1 is beq.b ddone # divu has no processing!!!
2177 1.1 is
2178 1.1 is # it was a divs.l, so ccode setting is a little more complicated...
2179 1.1 is tst.b NDIVIDEND(%a6) # remainder has same sign
2180 1.1 is beq.b dcc # as dividend.
2181 1.1 is neg.l %d5 # sgn(rem) = sgn(dividend)
2182 1.1 is dcc:
2183 1.1 is mov.b NDIVISOR(%a6), %d0
2184 1.1 is eor.b %d0, NDIVIDEND(%a6) # chk if quotient is negative
2185 1.1 is beq.b dqpos # branch to quot positive
2186 1.1 is
2187 1.1 is # 0x80000000 is the largest number representable as a 32-bit negative
2188 1.1 is # number. the negative of 0x80000000 is 0x80000000.
2189 1.1 is cmpi.l %d6, &0x80000000 # will (-quot) fit in 32 bits?
2190 1.1 is bhi.b ddovf
2191 1.1 is
2192 1.1 is neg.l %d6 # make (-quot) 2's comp
2193 1.1 is
2194 1.1 is bra.b ddone
2195 1.1 is
2196 1.1 is dqpos:
2197 1.1 is btst &0x1f, %d6 # will (+quot) fit in 32 bits?
2198 1.1 is bne.b ddovf
2199 1.1 is
2200 1.1 is ddone:
2201 1.1 is # at this point, result is normal so ccodes are set based on result.
2202 1.1 is mov.w EXC_CC(%a6), %cc
2203 1.1 is tst.l %d6 # set %ccode bits
2204 1.1 is mov.w %cc, EXC_CC(%a6)
2205 1.1 is
2206 1.1 is mov.w NDRSAVE(%a6), %d0 # get Dr off stack
2207 1.1 is mov.w NDQSAVE(%a6), %d1 # get Dq off stack
2208 1.1 is
2209 1.1 is # if the register numbers are the same, only the quotient gets saved.
2210 1.1 is # so, if we always save the quotient second, we save ourselves a cmp&beq
2211 1.1 is mov.l %d5, (EXC_DREGS,%a6,%d0.w*4) # save remainder
2212 1.1 is mov.l %d6, (EXC_DREGS,%a6,%d1.w*4) # save quotient
2213 1.1 is
2214 1.1 is rts
2215 1.1 is
2216 1.1 is ddovf:
2217 1.1 is bset &0x1, EXC_CC+1(%a6) # 'V' set on overflow
2218 1.1 is bclr &0x0, EXC_CC+1(%a6) # 'C' cleared on overflow
2219 1.1 is
2220 1.1 is rts
2221 1.1 is
2222 1.1 is div64eq0:
2223 1.1 is andi.b &0x1e, EXC_CC+1(%a6) # clear 'C' bit on divbyzero
2224 1.1 is ori.b &idbyz_flg,SPCOND_FLG(%a6) # set "special case" flag
2225 1.1 is rts
2226 1.1 is
2227 1.1 is ###########################################################################
2228 1.1 is #########################################################################
2229 1.1 is # This routine uses the 'classical' Algorithm D from Donald Knuth's #
2230 1.1 is # Art of Computer Programming, vol II, Seminumerical Algorithms. #
2231 1.1 is # For this implementation b=2**16, and the target is U1U2U3U4/V1V2, #
2232 1.1 is # where U,V are words of the quadword dividend and longword divisor, #
2233 1.1 is # and U1, V1 are the most significant words. #
2234 1.1 is # #
2235 1.1 is # The most sig. longword of the 64 bit dividend must be in %d5, least #
2236 1.1 is # in %d6. The divisor must be in the variable ddivisor, and the #
2237 1.1 is # signed/unsigned flag ddusign must be set (0=unsigned,1=signed). #
2238 1.1 is # The quotient is returned in %d6, remainder in %d5, unless the #
2239 1.1 is # v (overflow) bit is set in the saved %ccr. If overflow, the dividend #
2240 1.1 is # is unchanged. #
2241 1.1 is #########################################################################
2242 1.1 is dclassical:
2243 1.1 is # if the divisor msw is 0, use simpler algorithm then the full blown
2244 1.1 is # one at ddknuth:
2245 1.1 is
2246 1.1 is cmpi.l %d7, &0xffff
2247 1.1 is bhi.b ddknuth # go use D. Knuth algorithm
2248 1.1 is
2249 1.1 is # Since the divisor is only a word (and larger than the mslw of the dividend),
2250 1.1 is # a simpler algorithm may be used :
2251 1.1 is # In the general case, four quotient words would be created by
2252 1.1 is # dividing the divisor word into each dividend word. In this case,
2253 1.1 is # the first two quotient words must be zero, or overflow would occur.
2254 1.1 is # Since we already checked this case above, we can treat the most significant
2255 1.1 is # longword of the dividend as (0) remainder (see Knuth) and merely complete
2256 1.1 is # the last two divisions to get a quotient longword and word remainder:
2257 1.1 is
2258 1.1 is clr.l %d1
2259 1.1 is swap %d5 # same as r*b if previous step rqd
2260 1.1 is swap %d6 # get u3 to lsw position
2261 1.1 is mov.w %d6, %d5 # rb + u3
2262 1.1 is
2263 1.1 is divu.w %d7, %d5
2264 1.1 is
2265 1.1 is mov.w %d5, %d1 # first quotient word
2266 1.1 is swap %d6 # get u4
2267 1.1 is mov.w %d6, %d5 # rb + u4
2268 1.1 is
2269 1.1 is divu.w %d7, %d5
2270 1.1 is
2271 1.1 is swap %d1
2272 1.1 is mov.w %d5, %d1 # 2nd quotient 'digit'
2273 1.1 is clr.w %d5
2274 1.1 is swap %d5 # now remainder
2275 1.1 is mov.l %d1, %d6 # and quotient
2276 1.1 is
2277 1.1 is rts
2278 1.1 is
2279 1.1 is ddknuth:
2280 1.1 is # In this algorithm, the divisor is treated as a 2 digit (word) number
2281 1.1 is # which is divided into a 3 digit (word) dividend to get one quotient
2282 1.1 is # digit (word). After subtraction, the dividend is shifted and the
2283 1.1 is # process repeated. Before beginning, the divisor and quotient are
2284 1.1 is # 'normalized' so that the process of estimating the quotient digit
2285 1.1 is # will yield verifiably correct results..
2286 1.1 is
2287 1.1 is clr.l DDNORMAL(%a6) # count of shifts for normalization
2288 1.1 is clr.b DDSECOND(%a6) # clear flag for quotient digits
2289 1.1 is clr.l %d1 # %d1 will hold trial quotient
2290 1.1 is ddnchk:
2291 1.1 is btst &31, %d7 # must we normalize? first word of
2292 1.1 is bne.b ddnormalized # divisor (V1) must be >= 65536/2
2293 1.1 is addq.l &0x1, DDNORMAL(%a6) # count normalization shifts
2294 1.1 is lsl.l &0x1, %d7 # shift the divisor
2295 1.1 is lsl.l &0x1, %d6 # shift u4,u3 with overflow to u2
2296 1.1 is roxl.l &0x1, %d5 # shift u1,u2
2297 1.1 is bra.w ddnchk
2298 1.1 is ddnormalized:
2299 1.1 is
2300 1.1 is # Now calculate an estimate of the quotient words (msw first, then lsw).
2301 1.1 is # The comments use subscripts for the first quotient digit determination.
2302 1.1 is mov.l %d7, %d3 # divisor
2303 1.1 is mov.l %d5, %d2 # dividend mslw
2304 1.1 is swap %d2
2305 1.1 is swap %d3
2306 1.1 is cmp.w %d2, %d3 # V1 = U1 ?
2307 1.1 is bne.b ddqcalc1
2308 1.1 is mov.w &0xffff, %d1 # use max trial quotient word
2309 1.1 is bra.b ddadj0
2310 1.1 is ddqcalc1:
2311 1.1 is mov.l %d5, %d1
2312 1.1 is
2313 1.1 is divu.w %d3, %d1 # use quotient of mslw/msw
2314 1.1 is
2315 1.1 is andi.l &0x0000ffff, %d1 # zero any remainder
2316 1.1 is ddadj0:
2317 1.1 is
2318 1.1 is # now test the trial quotient and adjust. This step plus the
2319 1.1 is # normalization assures (according to Knuth) that the trial
2320 1.1 is # quotient will be at worst 1 too large.
2321 1.1 is mov.l %d6, -(%sp)
2322 1.1 is clr.w %d6 # word u3 left
2323 1.1 is swap %d6 # in lsw position
2324 1.1 is ddadj1: mov.l %d7, %d3
2325 1.1 is mov.l %d1, %d2
2326 1.1 is mulu.w %d7, %d2 # V2q
2327 1.1 is swap %d3
2328 1.1 is mulu.w %d1, %d3 # V1q
2329 1.1 is mov.l %d5, %d4 # U1U2
2330 1.1 is sub.l %d3, %d4 # U1U2 - V1q
2331 1.1 is
2332 1.1 is swap %d4
2333 1.1 is
2334 1.1 is mov.w %d4,%d0
2335 1.1 is mov.w %d6,%d4 # insert lower word (U3)
2336 1.1 is
2337 1.1 is tst.w %d0 # is upper word set?
2338 1.1 is bne.w ddadjd1
2339 1.1 is
2340 1.1 is # add.l %d6, %d4 # (U1U2 - V1q) + U3
2341 1.1 is
2342 1.1 is cmp.l %d2, %d4
2343 1.1 is bls.b ddadjd1 # is V2q > (U1U2-V1q) + U3 ?
2344 1.1 is subq.l &0x1, %d1 # yes, decrement and recheck
2345 1.1 is bra.b ddadj1
2346 1.1 is ddadjd1:
2347 1.1 is # now test the word by multiplying it by the divisor (V1V2) and comparing
2348 1.1 is # the 3 digit (word) result with the current dividend words
2349 1.1 is mov.l %d5, -(%sp) # save %d5 (%d6 already saved)
2350 1.1 is mov.l %d1, %d6
2351 1.1 is swap %d6 # shift answer to ms 3 words
2352 1.1 is mov.l %d7, %d5
2353 1.1 is bsr.l dmm2
2354 1.1 is mov.l %d5, %d2 # now %d2,%d3 are trial*divisor
2355 1.1 is mov.l %d6, %d3
2356 1.1 is mov.l (%sp)+, %d5 # restore dividend
2357 1.1 is mov.l (%sp)+, %d6
2358 1.1 is sub.l %d3, %d6
2359 1.1 is subx.l %d2, %d5 # subtract double precision
2360 1.1 is bcc dd2nd # no carry, do next quotient digit
2361 1.1 is subq.l &0x1, %d1 # q is one too large
2362 1.1 is # need to add back divisor longword to current ms 3 digits of dividend
2363 1.1 is # - according to Knuth, this is done only 2 out of 65536 times for random
2364 1.1 is # divisor, dividend selection.
2365 1.1 is clr.l %d2
2366 1.1 is mov.l %d7, %d3
2367 1.1 is swap %d3
2368 1.1 is clr.w %d3 # %d3 now ls word of divisor
2369 1.1 is add.l %d3, %d6 # aligned with 3rd word of dividend
2370 1.1 is addx.l %d2, %d5
2371 1.1 is mov.l %d7, %d3
2372 1.1 is clr.w %d3 # %d3 now ms word of divisor
2373 1.1 is swap %d3 # aligned with 2nd word of dividend
2374 1.1 is add.l %d3, %d5
2375 1.1 is dd2nd:
2376 1.1 is tst.b DDSECOND(%a6) # both q words done?
2377 1.1 is bne.b ddremain
2378 1.1 is # first quotient digit now correct. store digit and shift the
2379 1.1 is # (subtracted) dividend
2380 1.1 is mov.w %d1, DDQUOTIENT(%a6)
2381 1.1 is clr.l %d1
2382 1.1 is swap %d5
2383 1.1 is swap %d6
2384 1.1 is mov.w %d6, %d5
2385 1.1 is clr.w %d6
2386 1.1 is st DDSECOND(%a6) # second digit
2387 1.1 is bra.w ddnormalized
2388 1.1 is ddremain:
2389 1.1 is # add 2nd word to quotient, get the remainder.
2390 1.1 is mov.w %d1, DDQUOTIENT+2(%a6)
2391 1.1 is # shift down one word/digit to renormalize remainder.
2392 1.1 is mov.w %d5, %d6
2393 1.1 is swap %d6
2394 1.1 is swap %d5
2395 1.1 is mov.l DDNORMAL(%a6), %d7 # get norm shift count
2396 1.1 is beq.b ddrn
2397 1.1 is subq.l &0x1, %d7 # set for loop count
2398 1.1 is ddnlp:
2399 1.1 is lsr.l &0x1, %d5 # shift into %d6
2400 1.1 is roxr.l &0x1, %d6
2401 1.1 is dbf %d7, ddnlp
2402 1.1 is ddrn:
2403 1.1 is mov.l %d6, %d5 # remainder
2404 1.1 is mov.l DDQUOTIENT(%a6), %d6 # quotient
2405 1.1 is
2406 1.1 is rts
2407 1.1 is dmm2:
2408 1.1 is # factors for the 32X32->64 multiplication are in %d5 and %d6.
2409 1.1 is # returns 64 bit result in %d5 (hi) %d6(lo).
2410 1.1 is # destroys %d2,%d3,%d4.
2411 1.1 is
2412 1.1 is # multiply hi,lo words of each factor to get 4 intermediate products
2413 1.1 is mov.l %d6, %d2
2414 1.1 is mov.l %d6, %d3
2415 1.1 is mov.l %d5, %d4
2416 1.1 is swap %d3
2417 1.1 is swap %d4
2418 1.1 is mulu.w %d5, %d6 # %d6 <- lsw*lsw
2419 1.1 is mulu.w %d3, %d5 # %d5 <- msw-dest*lsw-source
2420 1.1 is mulu.w %d4, %d2 # %d2 <- msw-source*lsw-dest
2421 1.1 is mulu.w %d4, %d3 # %d3 <- msw*msw
2422 1.1 is # now use swap and addx to consolidate to two longwords
2423 1.1 is clr.l %d4
2424 1.1 is swap %d6
2425 1.1 is add.w %d5, %d6 # add msw of l*l to lsw of m*l product
2426 1.1 is addx.w %d4, %d3 # add any carry to m*m product
2427 1.1 is add.w %d2, %d6 # add in lsw of other m*l product
2428 1.1 is addx.w %d4, %d3 # add any carry to m*m product
2429 1.1 is swap %d6 # %d6 is low 32 bits of final product
2430 1.1 is clr.w %d5
2431 1.1 is clr.w %d2 # lsw of two mixed products used,
2432 1.1 is swap %d5 # now use msws of longwords
2433 1.1 is swap %d2
2434 1.1 is add.l %d2, %d5
2435 1.1 is add.l %d3, %d5 # %d5 now ms 32 bits of final product
2436 1.1 is rts
2437 1.1 is
2438 1.1 is ##########
2439 1.1 is dcontrolmodel_s:
2440 1.1 is movq.l &LONG,%d0
2441 1.1 is bsr.l _calc_ea # calc <ea>
2442 1.1 is
2443 1.1 is cmpi.b SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
2444 1.1 is beq.b dimmed # yes
2445 1.1 is
2446 1.1 is mov.l %a0,%a2
2447 1.1 is bsr.l _dmem_read_long # fetch divisor from <ea>
2448 1.1 is
2449 1.1 is tst.l %d1 # dfetch error?
2450 1.1 is bne.b div64_err # yes
2451 1.1 is
2452 1.1 is mov.l %d0, %d7
2453 1.1 is bra.w dgotsrcl
2454 1.1 is
2455 1.1 is # we have to split out immediate data here because it must be read using
2456 1.1 is # imem_read() instead of dmem_read(). this becomes especially important
2457 1.1 is # if the fetch runs into some deadly fault.
2458 1.1 is dimmed:
2459 1.1 is addq.l &0x4,EXC_EXTWPTR(%a6)
2460 1.1 is bsr.l _imem_read_long # read immediate value
2461 1.1 is
2462 1.1 is tst.l %d1 # ifetch error?
2463 1.1 is bne.l isp_iacc # yes
2464 1.1 is
2465 1.1 is mov.l %d0,%d7
2466 1.1 is bra.w dgotsrcl
2467 1.1 is
2468 1.1 is ##########
2469 1.1 is
2470 1.1 is # if dmem_read_long() returns a fail message in d1, the package
2471 1.1 is # must create an access error frame. here, we pass a skeleton fslw
2472 1.1 is # and the failing address to the routine that creates the new frame.
2473 1.1 is # also, we call isp_restore in case the effective addressing mode was
2474 1.1 is # (an)+ or -(an) in which case the previous "an" value must be restored.
2475 1.1 is # FSLW:
2476 1.1 is # read = true
2477 1.1 is # size = longword
2478 1.1 is # TM = data
2479 1.1 is # software emulation error = true
2480 1.1 is div64_err:
2481 1.1 is bsr.l isp_restore # restore addr reg
2482 1.1 is mov.l %a2,%a0 # pass failing address
2483 1.1 is mov.l &0x01010001,%d0 # pass fslw
2484 1.1 is bra.l isp_dacc
2485 1.1 is
2486 1.1 is #########################################################################
2487 1.1 is # XDEF **************************************************************** #
2488 1.1 is # _mul64(): routine to emulate mul{u,s}.l <ea>,Dh:Dl 32x32->64 #
2489 1.1 is # #
2490 1.1 is # XREF **************************************************************** #
2491 1.1 is # _calc_ea() - calculate effective address #
2492 1.1 is # isp_iacc() - handle instruction access error exception #
2493 1.1 is # isp_dacc() - handle data access error exception #
2494 1.1 is # isp_restore() - restore An on access error w/ -() or ()+ #
2495 1.1 is # #
2496 1.1 is # INPUT *************************************************************** #
2497 1.1 is # none #
2498 1.1 is # #
2499 1.1 is # OUTPUT ************************************************************** #
2500 1.1 is # If exiting through isp_dacc... #
2501 1.1 is # a0 = failing address #
2502 1.1 is # d0 = FSLW #
2503 1.1 is # else #
2504 1.1 is # none #
2505 1.1 is # #
2506 1.1 is # ALGORITHM *********************************************************** #
2507 1.1 is # First, decode the operand location. If it's in Dn, fetch from #
2508 1.1 is # the stack. If it's in memory, use _calc_ea() to calculate the #
2509 1.1 is # effective address. Use _dmem_read_long() to fetch at that address. #
2510 1.1 is # Unless the operand is immediate data. Then use _imem_read_long(). #
2511 1.1 is # Send failures to isp_dacc() or isp_iacc() as appropriate. #
2512 1.1 is # If the operands are signed, make them unsigned and save the #
2513 1.1 is # sign info for later. Perform the multiplication using 16x16->32 #
2514 1.1 is # unsigned multiplies and "add" instructions. Store the high and low #
2515 1.1 is # portions of the result in the appropriate data registers on the #
2516 1.1 is # stack. Calculate the condition codes, also. #
2517 1.1 is # #
2518 1.1 is #########################################################################
2519 1.1 is
2520 1.1 is #############
2521 1.1 is # mul(u,s)l #
2522 1.1 is #############
2523 1.1 is global _mul64
2524 1.1 is _mul64:
2525 1.1 is mov.b EXC_OPWORD+1(%a6), %d0 # extract src {mode,reg}
2526 1.1 is cmpi.b %d0, &0x7 # is src mode Dn or other?
2527 1.1 is bgt.w mul64_memop # src is in memory
2528 1.1 is
2529 1.1 is # multiplier operand in the data register file.
2530 1.1 is # must extract the register number and fetch the operand from the stack.
2531 1.1 is mul64_regop:
2532 1.1 is andi.w &0x7, %d0 # extract Dn
2533 1.1 is mov.l (EXC_DREGS,%a6,%d0.w*4), %d3 # fetch multiplier
2534 1.1 is
2535 1.1 is # multiplier is in %d3. now, extract Dl and Dh fields and fetch the
2536 1.1 is # multiplicand from the data register specified by Dl.
2537 1.1 is mul64_multiplicand:
2538 1.1 is mov.w EXC_EXTWORD(%a6), %d2 # fetch ext word
2539 1.1 is clr.w %d1 # clear Dh reg
2540 1.1 is mov.b %d2, %d1 # grab Dh
2541 1.1 is rol.w &0x4, %d2 # align Dl byte
2542 1.1 is andi.w &0x7, %d2 # extract Dl
2543 1.1 is
2544 1.1 is mov.l (EXC_DREGS,%a6,%d2.w*4), %d4 # get multiplicand
2545 1.1 is
2546 1.1 is # check for the case of "zero" result early
2547 1.1 is tst.l %d4 # test multiplicand
2548 1.1 is beq.w mul64_zero # handle zero separately
2549 1.1 is tst.l %d3 # test multiplier
2550 1.1 is beq.w mul64_zero # handle zero separately
2551 1.1 is
2552 1.1 is # multiplier is in %d3 and multiplicand is in %d4.
2553 1.1 is # if the operation is to be signed, then the operands are converted
2554 1.1 is # to unsigned and the result sign is saved for the end.
2555 1.1 is clr.b EXC_TEMP(%a6) # clear temp space
2556 1.1 is btst &0x3, EXC_EXTWORD(%a6) # signed or unsigned?
2557 1.1 is beq.b mul64_alg # unsigned; skip sgn calc
2558 1.1 is
2559 1.1 is tst.l %d3 # is multiplier negative?
2560 1.1 is bge.b mul64_chk_md_sgn # no
2561 1.1 is neg.l %d3 # make multiplier positive
2562 1.1 is ori.b &0x1, EXC_TEMP(%a6) # save multiplier sgn
2563 1.1 is
2564 1.1 is # the result sign is the exclusive or of the operand sign bits.
2565 1.1 is mul64_chk_md_sgn:
2566 1.1 is tst.l %d4 # is multiplicand negative?
2567 1.1 is bge.b mul64_alg # no
2568 1.1 is neg.l %d4 # make multiplicand positive
2569 1.1 is eori.b &0x1, EXC_TEMP(%a6) # calculate correct sign
2570 1.1 is
2571 1.1 is #########################################################################
2572 1.1 is # 63 32 0 #
2573 1.1 is # ---------------------------- #
2574 1.1 is # | hi(mplier) * hi(mplicand)| #
2575 1.1 is # ---------------------------- #
2576 1.1 is # ----------------------------- #
2577 1.1 is # | hi(mplier) * lo(mplicand) | #
2578 1.1 is # ----------------------------- #
2579 1.1 is # ----------------------------- #
2580 1.1 is # | lo(mplier) * hi(mplicand) | #
2581 1.1 is # ----------------------------- #
2582 1.1 is # | ----------------------------- #
2583 1.1 is # --|-- | lo(mplier) * lo(mplicand) | #
2584 1.1 is # | ----------------------------- #
2585 1.1 is # ======================================================== #
2586 1.1 is # -------------------------------------------------------- #
2587 1.1 is # | hi(result) | lo(result) | #
2588 1.1 is # -------------------------------------------------------- #
2589 1.1 is #########################################################################
2590 1.1 is mul64_alg:
2591 1.1 is # load temp registers with operands
2592 1.1 is mov.l %d3, %d5 # mr in %d5
2593 1.1 is mov.l %d3, %d6 # mr in %d6
2594 1.1 is mov.l %d4, %d7 # md in %d7
2595 1.1 is swap %d6 # hi(mr) in lo %d6
2596 1.1 is swap %d7 # hi(md) in lo %d7
2597 1.1 is
2598 1.1 is # complete necessary multiplies:
2599 1.1 is mulu.w %d4, %d3 # [1] lo(mr) * lo(md)
2600 1.1 is mulu.w %d6, %d4 # [2] hi(mr) * lo(md)
2601 1.1 is mulu.w %d7, %d5 # [3] lo(mr) * hi(md)
2602 1.1 is mulu.w %d7, %d6 # [4] hi(mr) * hi(md)
2603 1.1 is
2604 1.1 is # add lo portions of [2],[3] to hi portion of [1].
2605 1.1 is # add carries produced from these adds to [4].
2606 1.1 is # lo([1]) is the final lo 16 bits of the result.
2607 1.1 is clr.l %d7 # load %d7 w/ zero value
2608 1.1 is swap %d3 # hi([1]) <==> lo([1])
2609 1.1 is add.w %d4, %d3 # hi([1]) + lo([2])
2610 1.1 is addx.l %d7, %d6 # [4] + carry
2611 1.1 is add.w %d5, %d3 # hi([1]) + lo([3])
2612 1.1 is addx.l %d7, %d6 # [4] + carry
2613 1.1 is swap %d3 # lo([1]) <==> hi([1])
2614 1.1 is
2615 1.1 is # lo portions of [2],[3] have been added in to final result.
2616 1.1 is # now, clear lo, put hi in lo reg, and add to [4]
2617 1.1 is clr.w %d4 # clear lo([2])
2618 1.1 is clr.w %d5 # clear hi([3])
2619 1.1 is swap %d4 # hi([2]) in lo %d4
2620 1.1 is swap %d5 # hi([3]) in lo %d5
2621 1.1 is add.l %d5, %d4 # [4] + hi([2])
2622 1.1 is add.l %d6, %d4 # [4] + hi([3])
2623 1.1 is
2624 1.1 is # unsigned result is now in {%d4,%d3}
2625 1.1 is tst.b EXC_TEMP(%a6) # should result be signed?
2626 1.1 is beq.b mul64_done # no
2627 1.1 is
2628 1.1 is # result should be a signed negative number.
2629 1.1 is # compute 2's complement of the unsigned number:
2630 1.1 is # -negate all bits and add 1
2631 1.1 is mul64_neg:
2632 1.1 is not.l %d3 # negate lo(result) bits
2633 1.1 is not.l %d4 # negate hi(result) bits
2634 1.1 is addq.l &1, %d3 # add 1 to lo(result)
2635 1.1 is addx.l %d7, %d4 # add carry to hi(result)
2636 1.1 is
2637 1.1 is # the result is saved to the register file.
2638 1.2 wiz # for '040 compatibility, if Dl == Dh then only the hi(result) is
2639 1.1 is # saved. so, saving hi after lo accomplishes this without need to
2640 1.1 is # check Dl,Dh equality.
2641 1.1 is mul64_done:
2642 1.1 is mov.l %d3, (EXC_DREGS,%a6,%d2.w*4) # save lo(result)
2643 1.1 is mov.w &0x0, %cc
2644 1.1 is mov.l %d4, (EXC_DREGS,%a6,%d1.w*4) # save hi(result)
2645 1.1 is
2646 1.1 is # now, grab the condition codes. only one that can be set is 'N'.
2647 1.1 is # 'N' CAN be set if the operation is unsigned if bit 63 is set.
2648 1.1 is mov.w %cc, %d7 # fetch %ccr to see if 'N' set
2649 1.1 is andi.b &0x8, %d7 # extract 'N' bit
2650 1.1 is
2651 1.1 is mul64_ccode_set:
2652 1.1 is mov.b EXC_CC+1(%a6), %d6 # fetch previous %ccr
2653 1.1 is andi.b &0x10, %d6 # all but 'X' bit changes
2654 1.1 is
2655 1.1 is or.b %d7, %d6 # group 'X' and 'N'
2656 1.1 is mov.b %d6, EXC_CC+1(%a6) # save new %ccr
2657 1.1 is
2658 1.1 is rts
2659 1.1 is
2660 1.1 is # one or both of the operands is zero so the result is also zero.
2661 1.1 is # save the zero result to the register file and set the 'Z' ccode bit.
2662 1.1 is mul64_zero:
2663 1.1 is clr.l (EXC_DREGS,%a6,%d2.w*4) # save lo(result)
2664 1.1 is clr.l (EXC_DREGS,%a6,%d1.w*4) # save hi(result)
2665 1.1 is
2666 1.1 is movq.l &0x4, %d7 # set 'Z' ccode bit
2667 1.1 is bra.b mul64_ccode_set # finish ccode set
2668 1.1 is
2669 1.1 is ##########
2670 1.1 is
2671 1.1 is # multiplier operand is in memory at the effective address.
2672 1.1 is # must calculate the <ea> and go fetch the 32-bit operand.
2673 1.1 is mul64_memop:
2674 1.1 is movq.l &LONG, %d0 # pass # of bytes
2675 1.1 is bsr.l _calc_ea # calculate <ea>
2676 1.1 is
2677 1.1 is cmpi.b SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
2678 1.1 is beq.b mul64_immed # yes
2679 1.1 is
2680 1.1 is mov.l %a0,%a2
2681 1.1 is bsr.l _dmem_read_long # fetch src from addr (%a0)
2682 1.1 is
2683 1.1 is tst.l %d1 # dfetch error?
2684 1.1 is bne.w mul64_err # yes
2685 1.1 is
2686 1.1 is mov.l %d0, %d3 # store multiplier in %d3
2687 1.1 is
2688 1.1 is bra.w mul64_multiplicand
2689 1.1 is
2690 1.1 is # we have to split out immediate data here because it must be read using
2691 1.1 is # imem_read() instead of dmem_read(). this becomes especially important
2692 1.1 is # if the fetch runs into some deadly fault.
2693 1.1 is mul64_immed:
2694 1.1 is addq.l &0x4,EXC_EXTWPTR(%a6)
2695 1.1 is bsr.l _imem_read_long # read immediate value
2696 1.1 is
2697 1.1 is tst.l %d1 # ifetch error?
2698 1.1 is bne.l isp_iacc # yes
2699 1.1 is
2700 1.1 is mov.l %d0,%d3
2701 1.1 is bra.w mul64_multiplicand
2702 1.1 is
2703 1.1 is ##########
2704 1.1 is
2705 1.1 is # if dmem_read_long() returns a fail message in d1, the package
2706 1.1 is # must create an access error frame. here, we pass a skeleton fslw
2707 1.1 is # and the failing address to the routine that creates the new frame.
2708 1.1 is # also, we call isp_restore in case the effective addressing mode was
2709 1.1 is # (an)+ or -(an) in which case the previous "an" value must be restored.
2710 1.1 is # FSLW:
2711 1.1 is # read = true
2712 1.1 is # size = longword
2713 1.1 is # TM = data
2714 1.1 is # software emulation error = true
2715 1.1 is mul64_err:
2716 1.1 is bsr.l isp_restore # restore addr reg
2717 1.1 is mov.l %a2,%a0 # pass failing address
2718 1.1 is mov.l &0x01010001,%d0 # pass fslw
2719 1.1 is bra.l isp_dacc
2720 1.1 is
2721 1.1 is #########################################################################
2722 1.1 is # XDEF **************************************************************** #
2723 1.1 is # _compandset2(): routine to emulate cas2() #
2724 1.1 is # (internal to package) #
2725 1.1 is # #
2726 1.1 is # _isp_cas2_finish(): store ccodes, store compare regs #
2727 1.1 is # (external to package) #
2728 1.1 is # #
2729 1.1 is # XREF **************************************************************** #
2730 1.1 is # _real_lock_page() - "callout" to lock op's page from page-outs #
2731 1.1 is # _cas_terminate2() - access error exit #
2732 1.1 is # _real_cas2() - "callout" to core cas2 emulation code #
2733 1.1 is # _real_unlock_page() - "callout" to unlock page #
2734 1.1 is # #
2735 1.1 is # INPUT *************************************************************** #
2736 1.1 is # _compandset2(): #
2737 1.1 is # d0 = instruction extension word #
2738 1.1 is # #
2739 1.1 is # _isp_cas2_finish(): #
2740 1.1 is # see cas2 core emulation code #
2741 1.1 is # #
2742 1.1 is # OUTPUT ************************************************************** #
2743 1.1 is # _compandset2(): #
2744 1.1 is # see cas2 core emulation code #
2745 1.1 is # #
2746 1.1 is # _isp_cas_finish(): #
2747 1.1 is # None (register file or memroy changed as appropriate) #
2748 1.1 is # #
2749 1.1 is # ALGORITHM *********************************************************** #
2750 1.1 is # compandset2(): #
2751 1.1 is # Decode the instruction and fetch the appropriate Update and #
2752 1.1 is # Compare operands. Then call the "callout" _real_lock_page() for each #
2753 1.1 is # memory operand address so that the operating system can keep these #
2754 1.1 is # pages from being paged out. If either _real_lock_page() fails, exit #
2755 1.1 is # through _cas_terminate2(). Don't forget to unlock the 1st locked page #
2756 1.1 is # using _real_unlock_paged() if the 2nd lock-page fails. #
2757 1.1 is # Finally, branch to the core cas2 emulation code by calling the #
2758 1.1 is # "callout" _real_cas2(). #
2759 1.1 is # #
2760 1.1 is # _isp_cas2_finish(): #
2761 1.1 is # Re-perform the comparison so we can determine the condition #
2762 1.1 is # codes which were too much trouble to keep around during the locked #
2763 1.1 is # emulation. Then unlock each operands page by calling the "callout" #
2764 1.1 is # _real_unlock_page(). #
2765 1.1 is # #
2766 1.1 is #########################################################################
2767 1.1 is
2768 1.1 is set ADDR1, EXC_TEMP+0xc
2769 1.1 is set ADDR2, EXC_TEMP+0x0
2770 1.1 is set DC2, EXC_TEMP+0xa
2771 1.1 is set DC1, EXC_TEMP+0x8
2772 1.1 is
2773 1.1 is global _compandset2
2774 1.1 is _compandset2:
2775 1.1 is mov.l %d0,EXC_TEMP+0x4(%a6) # store for possible restart
2776 1.1 is mov.l %d0,%d1 # extension word in d0
2777 1.1 is
2778 1.1 is rol.w &0x4,%d0
2779 1.1 is andi.w &0xf,%d0 # extract Rn2
2780 1.1 is mov.l (EXC_DREGS,%a6,%d0.w*4),%a1 # fetch ADDR2
2781 1.1 is mov.l %a1,ADDR2(%a6)
2782 1.1 is
2783 1.1 is mov.l %d1,%d0
2784 1.1 is
2785 1.1 is lsr.w &0x6,%d1
2786 1.1 is andi.w &0x7,%d1 # extract Du2
2787 1.1 is mov.l (EXC_DREGS,%a6,%d1.w*4),%d5 # fetch Update2 Op
2788 1.1 is
2789 1.1 is andi.w &0x7,%d0 # extract Dc2
2790 1.1 is mov.l (EXC_DREGS,%a6,%d0.w*4),%d3 # fetch Compare2 Op
2791 1.1 is mov.w %d0,DC2(%a6)
2792 1.1 is
2793 1.1 is mov.w EXC_EXTWORD(%a6),%d0
2794 1.1 is mov.l %d0,%d1
2795 1.1 is
2796 1.1 is rol.w &0x4,%d0
2797 1.1 is andi.w &0xf,%d0 # extract Rn1
2798 1.1 is mov.l (EXC_DREGS,%a6,%d0.w*4),%a0 # fetch ADDR1
2799 1.1 is mov.l %a0,ADDR1(%a6)
2800 1.1 is
2801 1.1 is mov.l %d1,%d0
2802 1.1 is
2803 1.1 is lsr.w &0x6,%d1
2804 1.1 is andi.w &0x7,%d1 # extract Du1
2805 1.1 is mov.l (EXC_DREGS,%a6,%d1.w*4),%d4 # fetch Update1 Op
2806 1.1 is
2807 1.1 is andi.w &0x7,%d0 # extract Dc1
2808 1.1 is mov.l (EXC_DREGS,%a6,%d0.w*4),%d2 # fetch Compare1 Op
2809 1.1 is mov.w %d0,DC1(%a6)
2810 1.1 is
2811 1.1 is btst &0x1,EXC_OPWORD(%a6) # word or long?
2812 1.1 is sne %d7
2813 1.1 is
2814 1.1 is btst &0x5,EXC_ISR(%a6) # user or supervisor?
2815 1.1 is sne %d6
2816 1.1 is
2817 1.1 is mov.l %a0,%a2
2818 1.1 is mov.l %a1,%a3
2819 1.1 is
2820 1.1 is mov.l %d7,%d1 # pass size
2821 1.1 is mov.l %d6,%d0 # pass mode
2822 1.1 is bsr.l _real_lock_page # lock page
2823 1.1 is mov.l %a2,%a0
2824 1.1 is tst.l %d0 # error?
2825 1.1 is bne.l _cas_terminate2 # yes
2826 1.1 is
2827 1.1 is mov.l %d7,%d1 # pass size
2828 1.1 is mov.l %d6,%d0 # pass mode
2829 1.1 is mov.l %a3,%a0 # pass addr
2830 1.1 is bsr.l _real_lock_page # lock page
2831 1.1 is mov.l %a3,%a0
2832 1.1 is tst.l %d0 # error?
2833 1.1 is bne.b cas_preterm # yes
2834 1.1 is
2835 1.1 is mov.l %a2,%a0
2836 1.1 is mov.l %a3,%a1
2837 1.1 is
2838 1.1 is bra.l _real_cas2
2839 1.1 is
2840 1.1 is # if the 2nd lock attempt fails, then we must still unlock the
2841 1.1 is # first page(s).
2842 1.1 is cas_preterm:
2843 1.1 is mov.l %d0,-(%sp) # save FSLW
2844 1.1 is mov.l %d7,%d1 # pass size
2845 1.1 is mov.l %d6,%d0 # pass mode
2846 1.1 is mov.l %a2,%a0 # pass ADDR1
2847 1.1 is bsr.l _real_unlock_page # unlock first page(s)
2848 1.1 is mov.l (%sp)+,%d0 # restore FSLW
2849 1.1 is mov.l %a3,%a0 # pass failing addr
2850 1.1 is bra.l _cas_terminate2
2851 1.1 is
2852 1.1 is #############################################################
2853 1.1 is
2854 1.1 is global _isp_cas2_finish
2855 1.1 is _isp_cas2_finish:
2856 1.1 is btst &0x1,EXC_OPWORD(%a6)
2857 1.1 is bne.b cas2_finish_l
2858 1.1 is
2859 1.1 is mov.w EXC_CC(%a6),%cc # load old ccodes
2860 1.1 is cmp.w %d0,%d2
2861 1.1 is bne.b cas2_finish_w_save
2862 1.1 is cmp.w %d1,%d3
2863 1.1 is cas2_finish_w_save:
2864 1.1 is mov.w %cc,EXC_CC(%a6) # save new ccodes
2865 1.1 is
2866 1.1 is tst.b %d4 # update compare reg?
2867 1.1 is bne.b cas2_finish_w_done # no
2868 1.1 is
2869 1.1 is mov.w DC2(%a6),%d3 # fetch Dc2
2870 1.1 is mov.w %d1,(2+EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
2871 1.1 is
2872 1.1 is mov.w DC1(%a6),%d2 # fetch Dc1
2873 1.1 is mov.w %d0,(2+EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
2874 1.1 is
2875 1.1 is cas2_finish_w_done:
2876 1.1 is btst &0x5,EXC_ISR(%a6)
2877 1.1 is sne %d2
2878 1.1 is mov.l %d2,%d0 # pass mode
2879 1.1 is sf %d1 # pass size
2880 1.1 is mov.l ADDR1(%a6),%a0 # pass ADDR1
2881 1.1 is bsr.l _real_unlock_page # unlock page
2882 1.1 is
2883 1.1 is mov.l %d2,%d0 # pass mode
2884 1.1 is sf %d1 # pass size
2885 1.1 is mov.l ADDR2(%a6),%a0 # pass ADDR2
2886 1.1 is bsr.l _real_unlock_page # unlock page
2887 1.1 is rts
2888 1.1 is
2889 1.1 is cas2_finish_l:
2890 1.1 is mov.w EXC_CC(%a6),%cc # load old ccodes
2891 1.1 is cmp.l %d0,%d2
2892 1.1 is bne.b cas2_finish_l_save
2893 1.1 is cmp.l %d1,%d3
2894 1.1 is cas2_finish_l_save:
2895 1.1 is mov.w %cc,EXC_CC(%a6) # save new ccodes
2896 1.1 is
2897 1.1 is tst.b %d4 # update compare reg?
2898 1.1 is bne.b cas2_finish_l_done # no
2899 1.1 is
2900 1.1 is mov.w DC2(%a6),%d3 # fetch Dc2
2901 1.1 is mov.l %d1,(EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
2902 1.1 is
2903 1.1 is mov.w DC1(%a6),%d2 # fetch Dc1
2904 1.1 is mov.l %d0,(EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
2905 1.1 is
2906 1.1 is cas2_finish_l_done:
2907 1.1 is btst &0x5,EXC_ISR(%a6)
2908 1.1 is sne %d2
2909 1.1 is mov.l %d2,%d0 # pass mode
2910 1.1 is st %d1 # pass size
2911 1.1 is mov.l ADDR1(%a6),%a0 # pass ADDR1
2912 1.1 is bsr.l _real_unlock_page # unlock page
2913 1.1 is
2914 1.1 is mov.l %d2,%d0 # pass mode
2915 1.1 is st %d1 # pass size
2916 1.1 is mov.l ADDR2(%a6),%a0 # pass ADDR2
2917 1.1 is bsr.l _real_unlock_page # unlock page
2918 1.1 is rts
2919 1.1 is
2920 1.1 is ########
2921 1.1 is global cr_cas2
2922 1.1 is cr_cas2:
2923 1.1 is mov.l EXC_TEMP+0x4(%a6),%d0
2924 1.1 is bra.w _compandset2
2925 1.1 is
2926 1.1 is #########################################################################
2927 1.1 is # XDEF **************************************************************** #
2928 1.1 is # _compandset(): routine to emulate cas w/ misaligned <ea> #
2929 1.1 is # (internal to package) #
2930 1.1 is # _isp_cas_finish(): routine called when cas emulation completes #
2931 1.1 is # (external and internal to package) #
2932 1.1 is # _isp_cas_restart(): restart cas emulation after a fault #
2933 1.1 is # (external to package) #
2934 1.1 is # _isp_cas_terminate(): create access error stack frame on fault #
2935 1.1 is # (external and internal to package) #
2936 1.1 is # _isp_cas_inrange(): checks whether instr addess is within range #
2937 1.1 is # of core cas/cas2emulation code #
2938 1.1 is # (external to package) #
2939 1.1 is # #
2940 1.1 is # XREF **************************************************************** #
2941 1.1 is # _calc_ea(): calculate effective address #
2942 1.1 is # #
2943 1.1 is # INPUT *************************************************************** #
2944 1.1 is # compandset(): #
2945 1.1 is # none #
2946 1.1 is # _isp_cas_restart(): #
2947 1.1 is # d6 = previous sfc/dfc #
2948 1.1 is # _isp_cas_finish(): #
2949 1.1 is # _isp_cas_terminate(): #
2950 1.1 is # a0 = failing address #
2951 1.1 is # d0 = FSLW #
2952 1.1 is # d6 = previous sfc/dfc #
2953 1.1 is # _isp_cas_inrange(): #
2954 1.1 is # a0 = instruction address to be checked #
2955 1.1 is # #
2956 1.1 is # OUTPUT ************************************************************** #
2957 1.1 is # compandset(): #
2958 1.1 is # none #
2959 1.1 is # _isp_cas_restart(): #
2960 1.1 is # a0 = effective address #
2961 1.1 is # d7 = word or longword flag #
2962 1.1 is # _isp_cas_finish(): #
2963 1.1 is # a0 = effective address #
2964 1.1 is # _isp_cas_terminate(): #
2965 1.1 is # initial register set before emulation exception #
2966 1.1 is # _isp_cas_inrange(): #
2967 1.1 is # d0 = 0 => in range; -1 => out of range #
2968 1.1 is # #
2969 1.1 is # ALGORITHM *********************************************************** #
2970 1.1 is # #
2971 1.1 is # compandset(): #
2972 1.1 is # First, calculate the effective address. Then, decode the #
2973 1.1 is # instruction word and fetch the "compare" (DC) and "update" (Du) #
2974 1.1 is # operands. #
2975 1.1 is # Next, call the external routine _real_lock_page() so that the #
2976 1.1 is # operating system can keep this page from being paged out while we're #
2977 1.1 is # in this routine. If this call fails, jump to _cas_terminate2(). #
2978 1.1 is # The routine then branches to _real_cas(). This external routine #
2979 1.1 is # that actually emulates cas can be supplied by the external os or #
2980 1.1 is # made to point directly back into the 060ISP which has a routine for #
2981 1.1 is # this purpose. #
2982 1.1 is # #
2983 1.1 is # _isp_cas_finish(): #
2984 1.1 is # Either way, after emulation, the package is re-entered at #
2985 1.1 is # _isp_cas_finish(). This routine re-compares the operands in order to #
2986 1.1 is # set the condition codes. Finally, these routines will call #
2987 1.1 is # _real_unlock_page() in order to unlock the pages that were previously #
2988 1.1 is # locked. #
2989 1.1 is # #
2990 1.1 is # _isp_cas_restart(): #
2991 1.1 is # This routine can be entered from an access error handler where #
2992 1.1 is # the emulation sequence should be re-started from the beginning. #
2993 1.1 is # #
2994 1.1 is # _isp_cas_terminate(): #
2995 1.1 is # This routine can be entered from an access error handler where #
2996 1.1 is # an emulation operand access failed and the operating system would #
2997 1.1 is # like an access error stack frame created instead of the current #
2998 1.1 is # unimplemented integer instruction frame. #
2999 1.1 is # Also, the package enters here if a call to _real_lock_page() #
3000 1.1 is # fails. #
3001 1.1 is # #
3002 1.1 is # _isp_cas_inrange(): #
3003 1.1 is # Checks to see whether the instruction address passed to it in #
3004 1.1 is # a0 is within the software package cas/cas2 emulation routines. This #
3005 1.1 is # can be helpful for an operating system to determine whether an access #
3006 1.1 is # error during emulation was due to a cas/cas2 emulation access. #
3007 1.1 is # #
3008 1.1 is #########################################################################
3009 1.1 is
3010 1.1 is set DC, EXC_TEMP+0x8
3011 1.1 is set ADDR, EXC_TEMP+0x4
3012 1.1 is
3013 1.1 is global _compandset
3014 1.1 is _compandset:
3015 1.1 is btst &0x1,EXC_OPWORD(%a6) # word or long operation?
3016 1.1 is bne.b compandsetl # long
3017 1.1 is
3018 1.1 is compandsetw:
3019 1.1 is movq.l &0x2,%d0 # size = 2 bytes
3020 1.1 is bsr.l _calc_ea # a0 = calculated <ea>
3021 1.1 is mov.l %a0,ADDR(%a6) # save <ea> for possible restart
3022 1.1 is sf %d7 # clear d7 for word size
3023 1.1 is bra.b compandsetfetch
3024 1.1 is
3025 1.1 is compandsetl:
3026 1.1 is movq.l &0x4,%d0 # size = 4 bytes
3027 1.1 is bsr.l _calc_ea # a0 = calculated <ea>
3028 1.1 is mov.l %a0,ADDR(%a6) # save <ea> for possible restart
3029 1.1 is st %d7 # set d7 for longword size
3030 1.1 is
3031 1.1 is compandsetfetch:
3032 1.1 is mov.w EXC_EXTWORD(%a6),%d0 # fetch cas extension word
3033 1.1 is mov.l %d0,%d1 # make a copy
3034 1.1 is
3035 1.1 is lsr.w &0x6,%d0
3036 1.1 is andi.w &0x7,%d0 # extract Du
3037 1.1 is mov.l (EXC_DREGS,%a6,%d0.w*4),%d2 # get update operand
3038 1.1 is
3039 1.1 is andi.w &0x7,%d1 # extract Dc
3040 1.1 is mov.l (EXC_DREGS,%a6,%d1.w*4),%d4 # get compare operand
3041 1.1 is mov.w %d1,DC(%a6) # save Dc
3042 1.1 is
3043 1.1 is btst &0x5,EXC_ISR(%a6) # which mode for exception?
3044 1.1 is sne %d6 # set on supervisor mode
3045 1.1 is
3046 1.1 is mov.l %a0,%a2 # save temporarily
3047 1.1 is mov.l %d7,%d1 # pass size
3048 1.1 is mov.l %d6,%d0 # pass mode
3049 1.1 is bsr.l _real_lock_page # lock page
3050 1.1 is tst.l %d0 # did error occur?
3051 1.1 is bne.w _cas_terminate2 # yes, clean up the mess
3052 1.1 is mov.l %a2,%a0 # pass addr in a0
3053 1.1 is
3054 1.1 is bra.l _real_cas
3055 1.1 is
3056 1.1 is ########
3057 1.1 is global _isp_cas_finish
3058 1.1 is _isp_cas_finish:
3059 1.1 is btst &0x1,EXC_OPWORD(%a6)
3060 1.1 is bne.b cas_finish_l
3061 1.1 is
3062 1.1 is # just do the compare again since it's faster than saving the ccodes
3063 1.1 is # from the locked routine...
3064 1.1 is cas_finish_w:
3065 1.1 is mov.w EXC_CC(%a6),%cc # restore cc
3066 1.1 is cmp.w %d0,%d4 # do word compare
3067 1.1 is mov.w %cc,EXC_CC(%a6) # save cc
3068 1.1 is
3069 1.1 is tst.b %d1 # update compare reg?
3070 1.1 is bne.b cas_finish_w_done # no
3071 1.1 is
3072 1.1 is mov.w DC(%a6),%d3
3073 1.1 is mov.w %d0,(EXC_DREGS+2,%a6,%d3.w*4) # Dc = destination
3074 1.1 is
3075 1.1 is cas_finish_w_done:
3076 1.1 is mov.l ADDR(%a6),%a0 # pass addr
3077 1.1 is sf %d1 # pass size
3078 1.1 is btst &0x5,EXC_ISR(%a6)
3079 1.1 is sne %d0 # pass mode
3080 1.1 is bsr.l _real_unlock_page # unlock page
3081 1.1 is rts
3082 1.1 is
3083 1.1 is # just do the compare again since it's faster than saving the ccodes
3084 1.1 is # from the locked routine...
3085 1.1 is cas_finish_l:
3086 1.1 is mov.w EXC_CC(%a6),%cc # restore cc
3087 1.1 is cmp.l %d0,%d4 # do longword compare
3088 1.1 is mov.w %cc,EXC_CC(%a6) # save cc
3089 1.1 is
3090 1.1 is tst.b %d1 # update compare reg?
3091 1.1 is bne.b cas_finish_l_done # no
3092 1.1 is
3093 1.1 is mov.w DC(%a6),%d3
3094 1.1 is mov.l %d0,(EXC_DREGS,%a6,%d3.w*4) # Dc = destination
3095 1.1 is
3096 1.1 is cas_finish_l_done:
3097 1.1 is mov.l ADDR(%a6),%a0 # pass addr
3098 1.1 is st %d1 # pass size
3099 1.1 is btst &0x5,EXC_ISR(%a6)
3100 1.1 is sne %d0 # pass mode
3101 1.1 is bsr.l _real_unlock_page # unlock page
3102 1.1 is rts
3103 1.1 is
3104 1.1 is ########
3105 1.1 is
3106 1.1 is global _isp_cas_restart
3107 1.1 is _isp_cas_restart:
3108 1.1 is mov.l %d6,%sfc # restore previous sfc
3109 1.1 is mov.l %d6,%dfc # restore previous dfc
3110 1.1 is
3111 1.1 is cmpi.b EXC_OPWORD+1(%a6),&0xfc # cas or cas2?
3112 1.1 is beq.l cr_cas2 # cas2
3113 1.1 is cr_cas:
3114 1.1 is mov.l ADDR(%a6),%a0 # load <ea>
3115 1.1 is btst &0x1,EXC_OPWORD(%a6) # word or long operation?
3116 1.1 is sne %d7 # set d7 accordingly
3117 1.1 is bra.w compandsetfetch
3118 1.1 is
3119 1.1 is ########
3120 1.1 is
3121 1.1 is # At this stage, it would be nice if d0 held the FSLW.
3122 1.1 is global _isp_cas_terminate
3123 1.1 is _isp_cas_terminate:
3124 1.1 is mov.l %d6,%sfc # restore previous sfc
3125 1.1 is mov.l %d6,%dfc # restore previous dfc
3126 1.1 is
3127 1.1 is global _cas_terminate2
3128 1.1 is _cas_terminate2:
3129 1.1 is mov.l %a0,%a2 # copy failing addr to a2
3130 1.1 is
3131 1.1 is mov.l %d0,-(%sp)
3132 1.1 is bsr.l isp_restore # restore An (if ()+ or -())
3133 1.1 is mov.l (%sp)+,%d0
3134 1.1 is
3135 1.1 is addq.l &0x4,%sp # remove sub return addr
3136 1.1 is subq.l &0x8,%sp # make room for bigger stack
3137 1.1 is subq.l &0x8,%a6 # shift frame ptr down, too
3138 1.1 is mov.l &26,%d1 # want to move 51 longwords
3139 1.1 is lea 0x8(%sp),%a0 # get address of old stack
3140 1.1 is lea 0x0(%sp),%a1 # get address of new stack
3141 1.1 is cas_term_cont:
3142 1.1 is mov.l (%a0)+,(%a1)+ # move a longword
3143 1.1 is dbra.w %d1,cas_term_cont # keep going
3144 1.1 is
3145 1.1 is mov.w &0x4008,EXC_IVOFF(%a6) # put new stk fmt, voff
3146 1.1 is mov.l %a2,EXC_IVOFF+0x2(%a6) # put faulting addr on stack
3147 1.1 is mov.l %d0,EXC_IVOFF+0x6(%a6) # put FSLW on stack
3148 1.1 is movm.l EXC_DREGS(%a6),&0x3fff # restore user regs
3149 1.1 is unlk %a6 # unlink stack frame
3150 1.1 is bra.l _real_access
3151 1.1 is
3152 1.1 is ########
3153 1.1 is
3154 1.1 is global _isp_cas_inrange
3155 1.1 is _isp_cas_inrange:
3156 1.1 is clr.l %d0 # clear return result
3157 1.1 is lea _CASHI(%pc),%a1 # load end of CAS core code
3158 1.1 is cmp.l %a1,%a0 # is PC in range?
3159 1.1 is blt.b cin_no # no
3160 1.1 is lea _CASLO(%pc),%a1 # load begin of CAS core code
3161 1.1 is cmp.l %a0,%a1 # is PC in range?
3162 1.1 is blt.b cin_no # no
3163 1.1 is rts # yes; return d0 = 0
3164 1.1 is cin_no:
3165 1.1 is mov.l &-0x1,%d0 # out of range; return d0 = -1
3166 1.1 is rts
3167 1.1 is
3168 1.1 is #################################################################
3169 1.1 is #################################################################
3170 1.1 is #################################################################
3171 1.1 is # This is the start of the cas and cas2 "core" emulation code. #
3172 1.1 is # This is the section that may need to be replaced by the host #
3173 1.1 is # OS if it is too operating system-specific. #
3174 1.1 is # Please refer to the package documentation to see how to #
3175 1.1 is # "replace" this section, if necessary. #
3176 1.1 is #################################################################
3177 1.1 is #################################################################
3178 1.1 is #################################################################
3179 1.1 is
3180 1.1 is # ###### ## ###### ####
3181 1.1 is # # # # # # #
3182 1.1 is # # ###### ###### #
3183 1.1 is # # # # # #
3184 1.1 is # ###### # # ###### ######
3185 1.1 is
3186 1.1 is #########################################################################
3187 1.1 is # XDEF **************************************************************** #
3188 1.1 is # _isp_cas2(): "core" emulation code for the cas2 instruction #
3189 1.1 is # #
3190 1.1 is # XREF **************************************************************** #
3191 1.1 is # _isp_cas2_finish() - only exit point for this emulation code; #
3192 1.1 is # do clean-up; calculate ccodes; store #
3193 1.1 is # Compare Ops if appropriate. #
3194 1.1 is # #
3195 1.1 is # INPUT *************************************************************** #
3196 1.1 is # *see chart below* #
3197 1.1 is # #
3198 1.1 is # OUTPUT ************************************************************** #
3199 1.1 is # *see chart below* #
3200 1.1 is # #
3201 1.1 is # ALGORITHM *********************************************************** #
3202 1.1 is # (1) Make several copies of the effective address. #
3203 1.1 is # (2) Save current SR; Then mask off all maskable interrupts. #
3204 1.1 is # (3) Save current SFC/DFC (ASSUMED TO BE EQUAL!!!); Then set #
3205 1.1 is # according to whether exception occurred in user or #
3206 1.1 is # supervisor mode. #
3207 1.1 is # (4) Use "plpaw" instruction to pre-load ATC with effective #
3208 1.1 is # address pages(s). THIS SHOULD NOT FAULT!!! The relevant #
3209 1.1 is # page(s) should have already been made resident prior to #
3210 1.1 is # entering this routine. #
3211 1.1 is # (5) Push the operand lines from the cache w/ "cpushl". #
3212 1.1 is # In the 68040, this was done within the locked region. In #
3213 1.1 is # the 68060, it is done outside of the locked region. #
3214 1.1 is # (6) Use "plpar" instruction to do a re-load of ATC entries for #
3215 1.1 is # ADDR1 since ADDR2 entries may have pushed ADDR1 out of the #
3216 1.1 is # ATC. #
3217 1.1 is # (7) Pre-fetch the core emulation instructions by executing #
3218 1.1 is # one branch within each physical line (16 bytes) of the code #
3219 1.1 is # before actually executing the code. #
3220 1.1 is # (8) Load the BUSCR w/ the bus lock value. #
3221 1.1 is # (9) Fetch the source operands using "moves". #
3222 1.1 is # (10)Do the compares. If both equal, go to step (13). #
3223 1.1 is # (11)Unequal. No update occurs. But, we do write the DST1 op #
3224 1.1 is # back to itself (as w/ the '040) so we can gracefully unlock #
3225 1.1 is # the bus (and assert LOCKE*) using BUSCR and the final move. #
3226 1.1 is # (12)Exit. #
3227 1.1 is # (13)Write update operand to the DST locations. Use BUSCR to #
3228 1.1 is # assert LOCKE* for the final write operation. #
3229 1.1 is # (14)Exit. #
3230 1.1 is # #
3231 1.1 is # The algorithm is actually implemented slightly differently #
3232 1.1 is # depending on the size of the operation and the misalignment of the #
3233 1.1 is # operands. A misaligned operand must be written in aligned chunks or #
3234 1.1 is # else the BUSCR register control gets confused. #
3235 1.1 is # #
3236 1.1 is #########################################################################
3237 1.1 is
3238 1.1 is #################################################################
3239 1.1 is # THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON #
3240 1.1 is # ENTERING _isp_cas2(). #
3241 1.1 is # #
3242 1.1 is # D0 = xxxxxxxx #
3243 1.1 is # D1 = xxxxxxxx #
3244 1.1 is # D2 = cmp operand 1 #
3245 1.1 is # D3 = cmp operand 2 #
3246 1.1 is # D4 = update oper 1 #
3247 1.1 is # D5 = update oper 2 #
3248 1.1 is # D6 = 'xxxxxxff if supervisor mode; 'xxxxxx00 if user mode #
3249 1.1 is # D7 = 'xxxxxxff if longword operation; 'xxxxxx00 if word #
3250 1.1 is # A0 = ADDR1 #
3251 1.1 is # A1 = ADDR2 #
3252 1.1 is # A2 = xxxxxxxx #
3253 1.1 is # A3 = xxxxxxxx #
3254 1.1 is # A4 = xxxxxxxx #
3255 1.1 is # A5 = xxxxxxxx #
3256 1.1 is # A6 = frame pointer #
3257 1.1 is # A7 = stack pointer #
3258 1.1 is #################################################################
3259 1.1 is
3260 1.1 is # align 0x1000
3261 1.1 is # beginning label used by _isp_cas_inrange()
3262 1.1 is global _CASLO
3263 1.1 is _CASLO:
3264 1.1 is
3265 1.1 is global _isp_cas2
3266 1.1 is _isp_cas2:
3267 1.1 is tst.b %d6 # user or supervisor mode?
3268 1.1 is bne.b cas2_supervisor # supervisor
3269 1.1 is cas2_user:
3270 1.1 is movq.l &0x1,%d0 # load user data fc
3271 1.1 is bra.b cas2_cont
3272 1.1 is cas2_supervisor:
3273 1.1 is movq.l &0x5,%d0 # load supervisor data fc
3274 1.1 is cas2_cont:
3275 1.1 is tst.b %d7 # word or longword?
3276 1.1 is beq.w cas2w # word
3277 1.1 is
3278 1.1 is ####
3279 1.1 is cas2l:
3280 1.1 is mov.l %a0,%a2 # copy ADDR1
3281 1.1 is mov.l %a1,%a3 # copy ADDR2
3282 1.1 is mov.l %a0,%a4 # copy ADDR1
3283 1.1 is mov.l %a1,%a5 # copy ADDR2
3284 1.1 is
3285 1.1 is addq.l &0x3,%a4 # ADDR1+3
3286 1.1 is addq.l &0x3,%a5 # ADDR2+3
3287 1.1 is mov.l %a2,%d1 # ADDR1
3288 1.1 is
3289 1.1 is # mask interrupts levels 0-6. save old mask value.
3290 1.1 is mov.w %sr,%d7 # save current SR
3291 1.1 is ori.w &0x0700,%sr # inhibit interrupts
3292 1.1 is
3293 1.1 is # load the SFC and DFC with the appropriate mode.
3294 1.1 is movc %sfc,%d6 # save old SFC/DFC
3295 1.1 is movc %d0,%sfc # store new SFC
3296 1.1 is movc %d0,%dfc # store new DFC
3297 1.1 is
3298 1.1 is # pre-load the operand ATC. no page faults should occur here because
3299 1.1 is # _real_lock_page() should have taken care of this.
3300 1.1 is plpaw (%a2) # load atc for ADDR1
3301 1.1 is plpaw (%a4) # load atc for ADDR1+3
3302 1.1 is plpaw (%a3) # load atc for ADDR2
3303 1.1 is plpaw (%a5) # load atc for ADDR2+3
3304 1.1 is
3305 1.1 is # push the operand lines from the cache if they exist.
3306 1.1 is cpushl %dc,(%a2) # push line for ADDR1
3307 1.1 is cpushl %dc,(%a4) # push line for ADDR1+3
3308 1.1 is cpushl %dc,(%a3) # push line for ADDR2
3309 1.1 is cpushl %dc,(%a5) # push line for ADDR2+2
3310 1.1 is
3311 1.1 is mov.l %d1,%a2 # ADDR1
3312 1.1 is addq.l &0x3,%d1
3313 1.1 is mov.l %d1,%a4 # ADDR1+3
3314 1.1 is # if ADDR1 was ATC resident before the above "plpaw" and was executed
3315 1.1 is # and it was the next entry scheduled for replacement and ADDR2
3316 1.1 is # shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
3317 1.1 is # entries from the ATC. so, we do a second set of "plpa"s.
3318 1.1 is plpar (%a2) # load atc for ADDR1
3319 1.1 is plpar (%a4) # load atc for ADDR1+3
3320 1.1 is
3321 1.1 is # load the BUSCR values.
3322 1.1 is mov.l &0x80000000,%a2 # assert LOCK* buscr value
3323 1.1 is mov.l &0xa0000000,%a3 # assert LOCKE* buscr value
3324 1.1 is mov.l &0x00000000,%a4 # buscr unlock value
3325 1.1 is
3326 1.1 is # there are three possible mis-aligned cases for longword cas. they
3327 1.1 is # are separated because the final write which asserts LOCKE* must
3328 1.1 is # be aligned.
3329 1.1 is mov.l %a0,%d0 # is ADDR1 misaligned?
3330 1.1 is andi.b &0x3,%d0
3331 1.1 is beq.b CAS2L_ENTER # no
3332 1.1 is cmpi.b %d0,&0x2
3333 1.1 is beq.w CAS2L2_ENTER # yes; word misaligned
3334 1.1 is bra.w CAS2L3_ENTER # yes; byte misaligned
3335 1.1 is
3336 1.1 is #
3337 1.1 is # D0 = dst operand 1 <-
3338 1.1 is # D1 = dst operand 2 <-
3339 1.1 is # D2 = cmp operand 1
3340 1.1 is # D3 = cmp operand 2
3341 1.1 is # D4 = update oper 1
3342 1.1 is # D5 = update oper 2
3343 1.1 is # D6 = old SFC/DFC
3344 1.1 is # D7 = old SR
3345 1.1 is # A0 = ADDR1
3346 1.1 is # A1 = ADDR2
3347 1.1 is # A2 = bus LOCK* value
3348 1.1 is # A3 = bus LOCKE* value
3349 1.1 is # A4 = bus unlock value
3350 1.1 is # A5 = xxxxxxxx
3351 1.1 is #
3352 1.1 is align 0x10
3353 1.1 is CAS2L_START:
3354 1.1 is movc %a2,%buscr # assert LOCK*
3355 1.1 is movs.l (%a1),%d1 # fetch Dest2[31:0]
3356 1.1 is movs.l (%a0),%d0 # fetch Dest1[31:0]
3357 1.1 is bra.b CAS2L_CONT
3358 1.1 is CAS2L_ENTER:
3359 1.1 is bra.b ~+16
3360 1.1 is
3361 1.1 is CAS2L_CONT:
3362 1.1 is cmp.l %d0,%d2 # Dest1 - Compare1
3363 1.1 is bne.b CAS2L_NOUPDATE
3364 1.1 is cmp.l %d1,%d3 # Dest2 - Compare2
3365 1.1 is bne.b CAS2L_NOUPDATE
3366 1.1 is movs.l %d5,(%a1) # Update2[31:0] -> DEST2
3367 1.1 is bra.b CAS2L_UPDATE
3368 1.1 is bra.b ~+16
3369 1.1 is
3370 1.1 is CAS2L_UPDATE:
3371 1.1 is movc %a3,%buscr # assert LOCKE*
3372 1.1 is movs.l %d4,(%a0) # Update1[31:0] -> DEST1
3373 1.1 is movc %a4,%buscr # unlock the bus
3374 1.1 is bra.b cas2l_update_done
3375 1.1 is bra.b ~+16
3376 1.1 is
3377 1.1 is CAS2L_NOUPDATE:
3378 1.1 is movc %a3,%buscr # assert LOCKE*
3379 1.1 is movs.l %d0,(%a0) # Dest1[31:0] -> DEST1
3380 1.1 is movc %a4,%buscr # unlock the bus
3381 1.1 is bra.b cas2l_noupdate_done
3382 1.1 is bra.b ~+16
3383 1.1 is
3384 1.1 is CAS2L_FILLER:
3385 1.1 is nop
3386 1.1 is nop
3387 1.1 is nop
3388 1.1 is nop
3389 1.1 is nop
3390 1.1 is nop
3391 1.1 is nop
3392 1.1 is bra.b CAS2L_START
3393 1.1 is
3394 1.1 is ####
3395 1.1 is
3396 1.1 is #################################################################
3397 1.1 is # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON #
3398 1.1 is # ENTERING _isp_cas2(). #
3399 1.1 is # #
3400 1.1 is # D0 = destination[31:0] operand 1 #
3401 1.1 is # D1 = destination[31:0] operand 2 #
3402 1.1 is # D2 = cmp[31:0] operand 1 #
3403 1.1 is # D3 = cmp[31:0] operand 2 #
3404 1.1 is # D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required #
3405 1.1 is # D5 = xxxxxxxx #
3406 1.1 is # D6 = xxxxxxxx #
3407 1.1 is # D7 = xxxxxxxx #
3408 1.1 is # A0 = xxxxxxxx #
3409 1.1 is # A1 = xxxxxxxx #
3410 1.1 is # A2 = xxxxxxxx #
3411 1.1 is # A3 = xxxxxxxx #
3412 1.1 is # A4 = xxxxxxxx #
3413 1.1 is # A5 = xxxxxxxx #
3414 1.1 is # A6 = frame pointer #
3415 1.1 is # A7 = stack pointer #
3416 1.1 is #################################################################
3417 1.1 is
3418 1.1 is cas2l_noupdate_done:
3419 1.1 is
3420 1.1 is # restore previous SFC/DFC value.
3421 1.1 is movc %d6,%sfc # restore old SFC
3422 1.1 is movc %d6,%dfc # restore old DFC
3423 1.1 is
3424 1.1 is # restore previous interrupt mask level.
3425 1.1 is mov.w %d7,%sr # restore old SR
3426 1.1 is
3427 1.1 is sf %d4 # indicate no update was done
3428 1.1 is bra.l _isp_cas2_finish
3429 1.1 is
3430 1.1 is cas2l_update_done:
3431 1.1 is
3432 1.1 is # restore previous SFC/DFC value.
3433 1.1 is movc %d6,%sfc # restore old SFC
3434 1.1 is movc %d6,%dfc # restore old DFC
3435 1.1 is
3436 1.1 is # restore previous interrupt mask level.
3437 1.1 is mov.w %d7,%sr # restore old SR
3438 1.1 is
3439 1.1 is st %d4 # indicate update was done
3440 1.1 is bra.l _isp_cas2_finish
3441 1.1 is ####
3442 1.1 is
3443 1.1 is align 0x10
3444 1.1 is CAS2L2_START:
3445 1.1 is movc %a2,%buscr # assert LOCK*
3446 1.1 is movs.l (%a1),%d1 # fetch Dest2[31:0]
3447 1.1 is movs.l (%a0),%d0 # fetch Dest1[31:0]
3448 1.1 is bra.b CAS2L2_CONT
3449 1.1 is CAS2L2_ENTER:
3450 1.1 is bra.b ~+16
3451 1.1 is
3452 1.1 is CAS2L2_CONT:
3453 1.1 is cmp.l %d0,%d2 # Dest1 - Compare1
3454 1.1 is bne.b CAS2L2_NOUPDATE
3455 1.1 is cmp.l %d1,%d3 # Dest2 - Compare2
3456 1.1 is bne.b CAS2L2_NOUPDATE
3457 1.1 is movs.l %d5,(%a1) # Update2[31:0] -> Dest2
3458 1.1 is bra.b CAS2L2_UPDATE
3459 1.1 is bra.b ~+16
3460 1.1 is
3461 1.1 is CAS2L2_UPDATE:
3462 1.1 is swap %d4 # get Update1[31:16]
3463 1.1 is movs.w %d4,(%a0)+ # Update1[31:16] -> DEST1
3464 1.1 is movc %a3,%buscr # assert LOCKE*
3465 1.1 is swap %d4 # get Update1[15:0]
3466 1.1 is bra.b CAS2L2_UPDATE2
3467 1.1 is bra.b ~+16
3468 1.1 is
3469 1.1 is CAS2L2_UPDATE2:
3470 1.1 is movs.w %d4,(%a0) # Update1[15:0] -> DEST1+0x2
3471 1.1 is movc %a4,%buscr # unlock the bus
3472 1.1 is bra.w cas2l_update_done
3473 1.1 is nop
3474 1.1 is bra.b ~+16
3475 1.1 is
3476 1.1 is CAS2L2_NOUPDATE:
3477 1.1 is swap %d0 # get Dest1[31:16]
3478 1.1 is movs.w %d0,(%a0)+ # Dest1[31:16] -> DEST1
3479 1.1 is movc %a3,%buscr # assert LOCKE*
3480 1.1 is swap %d0 # get Dest1[15:0]
3481 1.1 is bra.b CAS2L2_NOUPDATE2
3482 1.1 is bra.b ~+16
3483 1.1 is
3484 1.1 is CAS2L2_NOUPDATE2:
3485 1.1 is movs.w %d0,(%a0) # Dest1[15:0] -> DEST1+0x2
3486 1.1 is movc %a4,%buscr # unlock the bus
3487 1.1 is bra.w cas2l_noupdate_done
3488 1.1 is nop
3489 1.1 is bra.b ~+16
3490 1.1 is
3491 1.1 is CAS2L2_FILLER:
3492 1.1 is nop
3493 1.1 is nop
3494 1.1 is nop
3495 1.1 is nop
3496 1.1 is nop
3497 1.1 is nop
3498 1.1 is nop
3499 1.1 is bra.b CAS2L2_START
3500 1.1 is
3501 1.1 is #################################
3502 1.1 is
3503 1.1 is align 0x10
3504 1.1 is CAS2L3_START:
3505 1.1 is movc %a2,%buscr # assert LOCK*
3506 1.1 is movs.l (%a1),%d1 # fetch Dest2[31:0]
3507 1.1 is movs.l (%a0),%d0 # fetch Dest1[31:0]
3508 1.1 is bra.b CAS2L3_CONT
3509 1.1 is CAS2L3_ENTER:
3510 1.1 is bra.b ~+16
3511 1.1 is
3512 1.1 is CAS2L3_CONT:
3513 1.1 is cmp.l %d0,%d2 # Dest1 - Compare1
3514 1.1 is bne.b CAS2L3_NOUPDATE
3515 1.1 is cmp.l %d1,%d3 # Dest2 - Compare2
3516 1.1 is bne.b CAS2L3_NOUPDATE
3517 1.1 is movs.l %d5,(%a1) # Update2[31:0] -> DEST2
3518 1.1 is bra.b CAS2L3_UPDATE
3519 1.1 is bra.b ~+16
3520 1.1 is
3521 1.1 is CAS2L3_UPDATE:
3522 1.1 is rol.l &0x8,%d4 # get Update1[31:24]
3523 1.1 is movs.b %d4,(%a0)+ # Update1[31:24] -> DEST1
3524 1.1 is swap %d4 # get Update1[23:8]
3525 1.1 is movs.w %d4,(%a0)+ # Update1[23:8] -> DEST1+0x1
3526 1.1 is bra.b CAS2L3_UPDATE2
3527 1.1 is bra.b ~+16
3528 1.1 is
3529 1.1 is CAS2L3_UPDATE2:
3530 1.1 is rol.l &0x8,%d4 # get Update1[7:0]
3531 1.1 is movc %a3,%buscr # assert LOCKE*
3532 1.1 is movs.b %d4,(%a0) # Update1[7:0] -> DEST1+0x3
3533 1.1 is bra.b CAS2L3_UPDATE3
3534 1.1 is nop
3535 1.1 is bra.b ~+16
3536 1.1 is
3537 1.1 is CAS2L3_UPDATE3:
3538 1.1 is movc %a4,%buscr # unlock the bus
3539 1.1 is bra.w cas2l_update_done
3540 1.1 is nop
3541 1.1 is nop
3542 1.1 is nop
3543 1.1 is bra.b ~+16
3544 1.1 is
3545 1.1 is CAS2L3_NOUPDATE:
3546 1.1 is rol.l &0x8,%d0 # get Dest1[31:24]
3547 1.1 is movs.b %d0,(%a0)+ # Dest1[31:24] -> DEST1
3548 1.1 is swap %d0 # get Dest1[23:8]
3549 1.1 is movs.w %d0,(%a0)+ # Dest1[23:8] -> DEST1+0x1
3550 1.1 is bra.b CAS2L3_NOUPDATE2
3551 1.1 is bra.b ~+16
3552 1.1 is
3553 1.1 is CAS2L3_NOUPDATE2:
3554 1.1 is rol.l &0x8,%d0 # get Dest1[7:0]
3555 1.1 is movc %a3,%buscr # assert LOCKE*
3556 1.1 is movs.b %d0,(%a0) # Update1[7:0] -> DEST1+0x3
3557 1.1 is bra.b CAS2L3_NOUPDATE3
3558 1.1 is nop
3559 1.1 is bra.b ~+16
3560 1.1 is
3561 1.1 is CAS2L3_NOUPDATE3:
3562 1.1 is movc %a4,%buscr # unlock the bus
3563 1.1 is bra.w cas2l_noupdate_done
3564 1.1 is nop
3565 1.1 is nop
3566 1.1 is nop
3567 1.1 is bra.b ~+14
3568 1.1 is
3569 1.1 is CAS2L3_FILLER:
3570 1.1 is nop
3571 1.1 is nop
3572 1.1 is nop
3573 1.1 is nop
3574 1.1 is nop
3575 1.1 is nop
3576 1.1 is bra.w CAS2L3_START
3577 1.1 is
3578 1.1 is #############################################################
3579 1.1 is #############################################################
3580 1.1 is
3581 1.1 is cas2w:
3582 1.1 is mov.l %a0,%a2 # copy ADDR1
3583 1.1 is mov.l %a1,%a3 # copy ADDR2
3584 1.1 is mov.l %a0,%a4 # copy ADDR1
3585 1.1 is mov.l %a1,%a5 # copy ADDR2
3586 1.1 is
3587 1.1 is addq.l &0x1,%a4 # ADDR1+1
3588 1.1 is addq.l &0x1,%a5 # ADDR2+1
3589 1.1 is mov.l %a2,%d1 # ADDR1
3590 1.1 is
3591 1.1 is # mask interrupt levels 0-6. save old mask value.
3592 1.1 is mov.w %sr,%d7 # save current SR
3593 1.1 is ori.w &0x0700,%sr # inhibit interrupts
3594 1.1 is
3595 1.1 is # load the SFC and DFC with the appropriate mode.
3596 1.1 is movc %sfc,%d6 # save old SFC/DFC
3597 1.1 is movc %d0,%sfc # store new SFC
3598 1.1 is movc %d0,%dfc # store new DFC
3599 1.1 is
3600 1.1 is # pre-load the operand ATC. no page faults should occur because
3601 1.1 is # _real_lock_page() should have taken care of this.
3602 1.1 is plpaw (%a2) # load atc for ADDR1
3603 1.1 is plpaw (%a4) # load atc for ADDR1+1
3604 1.1 is plpaw (%a3) # load atc for ADDR2
3605 1.1 is plpaw (%a5) # load atc for ADDR2+1
3606 1.1 is
3607 1.1 is # push the operand cache lines from the cache if they exist.
3608 1.1 is cpushl %dc,(%a2) # push line for ADDR1
3609 1.1 is cpushl %dc,(%a4) # push line for ADDR1+1
3610 1.1 is cpushl %dc,(%a3) # push line for ADDR2
3611 1.1 is cpushl %dc,(%a5) # push line for ADDR2+1
3612 1.1 is
3613 1.1 is mov.l %d1,%a2 # ADDR1
3614 1.1 is addq.l &0x3,%d1
3615 1.1 is mov.l %d1,%a4 # ADDR1+3
3616 1.1 is # if ADDR1 was ATC resident before the above "plpaw" and was executed
3617 1.1 is # and it was the next entry scheduled for replacement and ADDR2
3618 1.1 is # shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
3619 1.1 is # entries from the ATC. so, we do a second set of "plpa"s.
3620 1.1 is plpar (%a2) # load atc for ADDR1
3621 1.1 is plpar (%a4) # load atc for ADDR1+3
3622 1.1 is
3623 1.1 is # load the BUSCR values.
3624 1.1 is mov.l &0x80000000,%a2 # assert LOCK* buscr value
3625 1.1 is mov.l &0xa0000000,%a3 # assert LOCKE* buscr value
3626 1.1 is mov.l &0x00000000,%a4 # buscr unlock value
3627 1.1 is
3628 1.1 is # there are two possible mis-aligned cases for word cas. they
3629 1.1 is # are separated because the final write which asserts LOCKE* must
3630 1.1 is # be aligned.
3631 1.1 is mov.l %a0,%d0 # is ADDR1 misaligned?
3632 1.1 is btst &0x0,%d0
3633 1.1 is bne.w CAS2W2_ENTER # yes
3634 1.1 is bra.b CAS2W_ENTER # no
3635 1.1 is
3636 1.1 is #
3637 1.1 is # D0 = dst operand 1 <-
3638 1.1 is # D1 = dst operand 2 <-
3639 1.1 is # D2 = cmp operand 1
3640 1.1 is # D3 = cmp operand 2
3641 1.1 is # D4 = update oper 1
3642 1.1 is # D5 = update oper 2
3643 1.1 is # D6 = old SFC/DFC
3644 1.1 is # D7 = old SR
3645 1.1 is # A0 = ADDR1
3646 1.1 is # A1 = ADDR2
3647 1.1 is # A2 = bus LOCK* value
3648 1.1 is # A3 = bus LOCKE* value
3649 1.1 is # A4 = bus unlock value
3650 1.1 is # A5 = xxxxxxxx
3651 1.1 is #
3652 1.1 is align 0x10
3653 1.1 is CAS2W_START:
3654 1.1 is movc %a2,%buscr # assert LOCK*
3655 1.1 is movs.w (%a1),%d1 # fetch Dest2[15:0]
3656 1.1 is movs.w (%a0),%d0 # fetch Dest1[15:0]
3657 1.1 is bra.b CAS2W_CONT2
3658 1.1 is CAS2W_ENTER:
3659 1.1 is bra.b ~+16
3660 1.1 is
3661 1.1 is CAS2W_CONT2:
3662 1.1 is cmp.w %d0,%d2 # Dest1 - Compare1
3663 1.1 is bne.b CAS2W_NOUPDATE
3664 1.1 is cmp.w %d1,%d3 # Dest2 - Compare2
3665 1.1 is bne.b CAS2W_NOUPDATE
3666 1.1 is movs.w %d5,(%a1) # Update2[15:0] -> DEST2
3667 1.1 is bra.b CAS2W_UPDATE
3668 1.1 is bra.b ~+16
3669 1.1 is
3670 1.1 is CAS2W_UPDATE:
3671 1.1 is movc %a3,%buscr # assert LOCKE*
3672 1.1 is movs.w %d4,(%a0) # Update1[15:0] -> DEST1
3673 1.1 is movc %a4,%buscr # unlock the bus
3674 1.1 is bra.b cas2w_update_done
3675 1.1 is bra.b ~+16
3676 1.1 is
3677 1.1 is CAS2W_NOUPDATE:
3678 1.1 is movc %a3,%buscr # assert LOCKE*
3679 1.1 is movs.w %d0,(%a0) # Dest1[15:0] -> DEST1
3680 1.1 is movc %a4,%buscr # unlock the bus
3681 1.1 is bra.b cas2w_noupdate_done
3682 1.1 is bra.b ~+16
3683 1.1 is
3684 1.1 is CAS2W_FILLER:
3685 1.1 is nop
3686 1.1 is nop
3687 1.1 is nop
3688 1.1 is nop
3689 1.1 is nop
3690 1.1 is nop
3691 1.1 is nop
3692 1.1 is bra.b CAS2W_START
3693 1.1 is
3694 1.1 is ####
3695 1.1 is
3696 1.1 is #################################################################
3697 1.1 is # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON #
3698 1.1 is # ENTERING _isp_cas2(). #
3699 1.1 is # #
3700 1.1 is # D0 = destination[15:0] operand 1 #
3701 1.1 is # D1 = destination[15:0] operand 2 #
3702 1.1 is # D2 = cmp[15:0] operand 1 #
3703 1.1 is # D3 = cmp[15:0] operand 2 #
3704 1.1 is # D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required #
3705 1.1 is # D5 = xxxxxxxx #
3706 1.1 is # D6 = xxxxxxxx #
3707 1.1 is # D7 = xxxxxxxx #
3708 1.1 is # A0 = xxxxxxxx #
3709 1.1 is # A1 = xxxxxxxx #
3710 1.1 is # A2 = xxxxxxxx #
3711 1.1 is # A3 = xxxxxxxx #
3712 1.1 is # A4 = xxxxxxxx #
3713 1.1 is # A5 = xxxxxxxx #
3714 1.1 is # A6 = frame pointer #
3715 1.1 is # A7 = stack pointer #
3716 1.1 is #################################################################
3717 1.1 is
3718 1.1 is cas2w_noupdate_done:
3719 1.1 is
3720 1.1 is # restore previous SFC/DFC value.
3721 1.1 is movc %d6,%sfc # restore old SFC
3722 1.1 is movc %d6,%dfc # restore old DFC
3723 1.1 is
3724 1.1 is # restore previous interrupt mask level.
3725 1.1 is mov.w %d7,%sr # restore old SR
3726 1.1 is
3727 1.1 is sf %d4 # indicate no update was done
3728 1.1 is bra.l _isp_cas2_finish
3729 1.1 is
3730 1.1 is cas2w_update_done:
3731 1.1 is
3732 1.1 is # restore previous SFC/DFC value.
3733 1.1 is movc %d6,%sfc # restore old SFC
3734 1.1 is movc %d6,%dfc # restore old DFC
3735 1.1 is
3736 1.1 is # restore previous interrupt mask level.
3737 1.1 is mov.w %d7,%sr # restore old SR
3738 1.1 is
3739 1.1 is st %d4 # indicate update was done
3740 1.1 is bra.l _isp_cas2_finish
3741 1.1 is ####
3742 1.1 is
3743 1.1 is align 0x10
3744 1.1 is CAS2W2_START:
3745 1.1 is movc %a2,%buscr # assert LOCK*
3746 1.1 is movs.w (%a1),%d1 # fetch Dest2[15:0]
3747 1.1 is movs.w (%a0),%d0 # fetch Dest1[15:0]
3748 1.1 is bra.b CAS2W2_CONT2
3749 1.1 is CAS2W2_ENTER:
3750 1.1 is bra.b ~+16
3751 1.1 is
3752 1.1 is CAS2W2_CONT2:
3753 1.1 is cmp.w %d0,%d2 # Dest1 - Compare1
3754 1.1 is bne.b CAS2W2_NOUPDATE
3755 1.1 is cmp.w %d1,%d3 # Dest2 - Compare2
3756 1.1 is bne.b CAS2W2_NOUPDATE
3757 1.1 is movs.w %d5,(%a1) # Update2[15:0] -> DEST2
3758 1.1 is bra.b CAS2W2_UPDATE
3759 1.1 is bra.b ~+16
3760 1.1 is
3761 1.1 is CAS2W2_UPDATE:
3762 1.1 is ror.l &0x8,%d4 # get Update1[15:8]
3763 1.1 is movs.b %d4,(%a0)+ # Update1[15:8] -> DEST1
3764 1.1 is movc %a3,%buscr # assert LOCKE*
3765 1.1 is rol.l &0x8,%d4 # get Update1[7:0]
3766 1.1 is bra.b CAS2W2_UPDATE2
3767 1.1 is bra.b ~+16
3768 1.1 is
3769 1.1 is CAS2W2_UPDATE2:
3770 1.1 is movs.b %d4,(%a0) # Update1[7:0] -> DEST1+0x1
3771 1.1 is movc %a4,%buscr # unlock the bus
3772 1.1 is bra.w cas2w_update_done
3773 1.1 is nop
3774 1.1 is bra.b ~+16
3775 1.1 is
3776 1.1 is CAS2W2_NOUPDATE:
3777 1.1 is ror.l &0x8,%d0 # get Dest1[15:8]
3778 1.1 is movs.b %d0,(%a0)+ # Dest1[15:8] -> DEST1
3779 1.1 is movc %a3,%buscr # assert LOCKE*
3780 1.1 is rol.l &0x8,%d0 # get Dest1[7:0]
3781 1.1 is bra.b CAS2W2_NOUPDATE2
3782 1.1 is bra.b ~+16
3783 1.1 is
3784 1.1 is CAS2W2_NOUPDATE2:
3785 1.1 is movs.b %d0,(%a0) # Dest1[7:0] -> DEST1+0x1
3786 1.1 is movc %a4,%buscr # unlock the bus
3787 1.1 is bra.w cas2w_noupdate_done
3788 1.1 is nop
3789 1.1 is bra.b ~+16
3790 1.1 is
3791 1.1 is CAS2W2_FILLER:
3792 1.1 is nop
3793 1.1 is nop
3794 1.1 is nop
3795 1.1 is nop
3796 1.1 is nop
3797 1.1 is nop
3798 1.1 is nop
3799 1.1 is bra.b CAS2W2_START
3800 1.1 is
3801 1.1 is # ###### ## ######
3802 1.1 is # # # # #
3803 1.1 is # # ###### ######
3804 1.1 is # # # # #
3805 1.1 is # ###### # # ######
3806 1.1 is
3807 1.1 is #########################################################################
3808 1.1 is # XDEF **************************************************************** #
3809 1.1 is # _isp_cas(): "core" emulation code for the cas instruction #
3810 1.1 is # #
3811 1.1 is # XREF **************************************************************** #
3812 1.1 is # _isp_cas_finish() - only exit point for this emulation code; #
3813 1.1 is # do clean-up #
3814 1.1 is # #
3815 1.1 is # INPUT *************************************************************** #
3816 1.1 is # *see entry chart below* #
3817 1.1 is # #
3818 1.1 is # OUTPUT ************************************************************** #
3819 1.1 is # *see exit chart below* #
3820 1.1 is # #
3821 1.1 is # ALGORITHM *********************************************************** #
3822 1.1 is # (1) Make several copies of the effective address. #
3823 1.1 is # (2) Save current SR; Then mask off all maskable interrupts. #
3824 1.1 is # (3) Save current DFC/SFC (ASSUMED TO BE EQUAL!!!); Then set #
3825 1.1 is # SFC/DFC according to whether exception occurred in user or #
3826 1.1 is # supervisor mode. #
3827 1.1 is # (4) Use "plpaw" instruction to pre-load ATC with efective #
3828 1.1 is # address page(s). THIS SHOULD NOT FAULT!!! The relevant #
3829 1.1 is # page(s) should have been made resident prior to entering #
3830 1.1 is # this routine. #
3831 1.1 is # (5) Push the operand lines from the cache w/ "cpushl". #
3832 1.1 is # In the 68040, this was done within the locked region. In #
3833 1.1 is # the 68060, it is done outside of the locked region. #
3834 1.1 is # (6) Pre-fetch the core emulation instructions by executing one #
3835 1.1 is # branch within each physical line (16 bytes) of the code #
3836 1.1 is # before actually executing the code. #
3837 1.1 is # (7) Load the BUSCR with the bus lock value. #
3838 1.1 is # (8) Fetch the source operand. #
3839 1.1 is # (9) Do the compare. If equal, go to step (12). #
3840 1.1 is # (10)Unequal. No update occurs. But, we do write the DST op back #
3841 1.1 is # to itself (as w/ the '040) so we can gracefully unlock #
3842 1.1 is # the bus (and assert LOCKE*) using BUSCR and the final move. #
3843 1.1 is # (11)Exit. #
3844 1.1 is # (12)Write update operand to the DST location. Use BUSCR to #
3845 1.1 is # assert LOCKE* for the final write operation. #
3846 1.1 is # (13)Exit. #
3847 1.1 is # #
3848 1.1 is # The algorithm is actually implemented slightly diferently #
3849 1.1 is # depending on the size of the operation and the misalignment of the #
3850 1.1 is # operand. A misaligned operand must be written in aligned chunks or #
3851 1.1 is # else the BUSCR register control gets confused. #
3852 1.1 is # #
3853 1.1 is #########################################################################
3854 1.1 is
3855 1.1 is #########################################################
3856 1.1 is # THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON #
3857 1.1 is # ENTERING _isp_cas(). #
3858 1.1 is # #
3859 1.1 is # D0 = xxxxxxxx #
3860 1.1 is # D1 = xxxxxxxx #
3861 1.1 is # D2 = update operand #
3862 1.1 is # D3 = xxxxxxxx #
3863 1.1 is # D4 = compare operand #
3864 1.1 is # D5 = xxxxxxxx #
3865 1.1 is # D6 = supervisor ('xxxxxxff) or user mode ('xxxxxx00) #
3866 1.1 is # D7 = longword ('xxxxxxff) or word size ('xxxxxx00) #
3867 1.1 is # A0 = ADDR #
3868 1.1 is # A1 = xxxxxxxx #
3869 1.1 is # A2 = xxxxxxxx #
3870 1.1 is # A3 = xxxxxxxx #
3871 1.1 is # A4 = xxxxxxxx #
3872 1.1 is # A5 = xxxxxxxx #
3873 1.1 is # A6 = frame pointer #
3874 1.1 is # A7 = stack pointer #
3875 1.1 is #########################################################
3876 1.1 is
3877 1.1 is global _isp_cas
3878 1.1 is _isp_cas:
3879 1.1 is tst.b %d6 # user or supervisor mode?
3880 1.1 is bne.b cas_super # supervisor
3881 1.1 is cas_user:
3882 1.1 is movq.l &0x1,%d0 # load user data fc
3883 1.1 is bra.b cas_cont
3884 1.1 is cas_super:
3885 1.1 is movq.l &0x5,%d0 # load supervisor data fc
3886 1.1 is
3887 1.1 is cas_cont:
3888 1.1 is tst.b %d7 # word or longword?
3889 1.1 is bne.w casl # longword
3890 1.1 is
3891 1.1 is ####
3892 1.1 is casw:
3893 1.1 is mov.l %a0,%a1 # make copy for plpaw1
3894 1.1 is mov.l %a0,%a2 # make copy for plpaw2
3895 1.1 is addq.l &0x1,%a2 # plpaw2 points to end of word
3896 1.1 is
3897 1.1 is mov.l %d2,%d3 # d3 = update[7:0]
3898 1.1 is lsr.w &0x8,%d2 # d2 = update[15:8]
3899 1.1 is
3900 1.1 is # mask interrupt levels 0-6. save old mask value.
3901 1.1 is mov.w %sr,%d7 # save current SR
3902 1.1 is ori.w &0x0700,%sr # inhibit interrupts
3903 1.1 is
3904 1.1 is # load the SFC and DFC with the appropriate mode.
3905 1.1 is movc %sfc,%d6 # save old SFC/DFC
3906 1.1 is movc %d0,%sfc # load new sfc
3907 1.1 is movc %d0,%dfc # load new dfc
3908 1.1 is
3909 1.1 is # pre-load the operand ATC. no page faults should occur here because
3910 1.1 is # _real_lock_page() should have taken care of this.
3911 1.1 is plpaw (%a1) # load atc for ADDR
3912 1.1 is plpaw (%a2) # load atc for ADDR+1
3913 1.1 is
3914 1.1 is # push the operand lines from the cache if they exist.
3915 1.1 is cpushl %dc,(%a1) # push dirty data
3916 1.1 is cpushl %dc,(%a2) # push dirty data
3917 1.1 is
3918 1.1 is # load the BUSCR values.
3919 1.1 is mov.l &0x80000000,%a1 # assert LOCK* buscr value
3920 1.1 is mov.l &0xa0000000,%a2 # assert LOCKE* buscr value
3921 1.1 is mov.l &0x00000000,%a3 # buscr unlock value
3922 1.1 is
3923 1.1 is # pre-load the instruction cache for the following algorithm.
3924 1.1 is # this will minimize the number of cycles that LOCK* will be asserted.
3925 1.1 is bra.b CASW_ENTER # start pre-loading icache
3926 1.1 is
3927 1.1 is #
3928 1.1 is # D0 = dst operand <-
3929 1.1 is # D1 = update[15:8] operand
3930 1.1 is # D2 = update[7:0] operand
3931 1.1 is # D3 = xxxxxxxx
3932 1.1 is # D4 = compare[15:0] operand
3933 1.1 is # D5 = xxxxxxxx
3934 1.1 is # D6 = old SFC/DFC
3935 1.1 is # D7 = old SR
3936 1.1 is # A0 = ADDR
3937 1.1 is # A1 = bus LOCK* value
3938 1.1 is # A2 = bus LOCKE* value
3939 1.1 is # A3 = bus unlock value
3940 1.1 is # A4 = xxxxxxxx
3941 1.1 is # A5 = xxxxxxxx
3942 1.1 is #
3943 1.1 is align 0x10
3944 1.1 is CASW_START:
3945 1.1 is movc %a1,%buscr # assert LOCK*
3946 1.1 is movs.w (%a0),%d0 # fetch Dest[15:0]
3947 1.1 is cmp.w %d0,%d4 # Dest - Compare
3948 1.1 is bne.b CASW_NOUPDATE
3949 1.1 is bra.b CASW_UPDATE
3950 1.1 is CASW_ENTER:
3951 1.1 is bra.b ~+16
3952 1.1 is
3953 1.1 is CASW_UPDATE:
3954 1.1 is movs.b %d2,(%a0)+ # Update[15:8] -> DEST
3955 1.1 is movc %a2,%buscr # assert LOCKE*
3956 1.1 is movs.b %d3,(%a0) # Update[7:0] -> DEST+0x1
3957 1.1 is bra.b CASW_UPDATE2
3958 1.1 is bra.b ~+16
3959 1.1 is
3960 1.1 is CASW_UPDATE2:
3961 1.1 is movc %a3,%buscr # unlock the bus
3962 1.1 is bra.b casw_update_done
3963 1.1 is nop
3964 1.1 is nop
3965 1.1 is nop
3966 1.1 is nop
3967 1.1 is bra.b ~+16
3968 1.1 is
3969 1.1 is CASW_NOUPDATE:
3970 1.1 is ror.l &0x8,%d0 # get Dest[15:8]
3971 1.1 is movs.b %d0,(%a0)+ # Dest[15:8] -> DEST
3972 1.1 is movc %a2,%buscr # assert LOCKE*
3973 1.1 is rol.l &0x8,%d0 # get Dest[7:0]
3974 1.1 is bra.b CASW_NOUPDATE2
3975 1.1 is bra.b ~+16
3976 1.1 is
3977 1.1 is CASW_NOUPDATE2:
3978 1.1 is movs.b %d0,(%a0) # Dest[7:0] -> DEST+0x1
3979 1.1 is movc %a3,%buscr # unlock the bus
3980 1.1 is bra.b casw_noupdate_done
3981 1.1 is nop
3982 1.1 is nop
3983 1.1 is bra.b ~+16
3984 1.1 is
3985 1.1 is CASW_FILLER:
3986 1.1 is nop
3987 1.1 is nop
3988 1.1 is nop
3989 1.1 is nop
3990 1.1 is nop
3991 1.1 is nop
3992 1.1 is nop
3993 1.1 is bra.b CASW_START
3994 1.1 is
3995 1.1 is #################################################################
3996 1.1 is # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON #
3997 1.1 is # CALLING _isp_cas_finish(). #
3998 1.1 is # #
3999 1.1 is # D0 = destination[15:0] operand #
4000 1.1 is # D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required #
4001 1.1 is # D2 = xxxxxxxx #
4002 1.1 is # D3 = xxxxxxxx #
4003 1.1 is # D4 = compare[15:0] operand #
4004 1.1 is # D5 = xxxxxxxx #
4005 1.1 is # D6 = xxxxxxxx #
4006 1.1 is # D7 = xxxxxxxx #
4007 1.1 is # A0 = xxxxxxxx #
4008 1.1 is # A1 = xxxxxxxx #
4009 1.1 is # A2 = xxxxxxxx #
4010 1.1 is # A3 = xxxxxxxx #
4011 1.1 is # A4 = xxxxxxxx #
4012 1.1 is # A5 = xxxxxxxx #
4013 1.1 is # A6 = frame pointer #
4014 1.1 is # A7 = stack pointer #
4015 1.1 is #################################################################
4016 1.1 is
4017 1.1 is casw_noupdate_done:
4018 1.1 is
4019 1.1 is # restore previous SFC/DFC value.
4020 1.1 is movc %d6,%sfc # restore old SFC
4021 1.1 is movc %d6,%dfc # restore old DFC
4022 1.1 is
4023 1.1 is # restore previous interrupt mask level.
4024 1.1 is mov.w %d7,%sr # restore old SR
4025 1.1 is
4026 1.1 is sf %d1 # indicate no update was done
4027 1.1 is bra.l _isp_cas_finish
4028 1.1 is
4029 1.1 is casw_update_done:
4030 1.1 is
4031 1.1 is # restore previous SFC/DFC value.
4032 1.1 is movc %d6,%sfc # restore old SFC
4033 1.1 is movc %d6,%dfc # restore old DFC
4034 1.1 is
4035 1.1 is # restore previous interrupt mask level.
4036 1.1 is mov.w %d7,%sr # restore old SR
4037 1.1 is
4038 1.1 is st %d1 # indicate update was done
4039 1.1 is bra.l _isp_cas_finish
4040 1.1 is
4041 1.1 is ################
4042 1.1 is
4043 1.1 is # there are two possible mis-aligned cases for longword cas. they
4044 1.1 is # are separated because the final write which asserts LOCKE* must
4045 1.1 is # be an aligned write.
4046 1.1 is casl:
4047 1.1 is mov.l %a0,%a1 # make copy for plpaw1
4048 1.1 is mov.l %a0,%a2 # make copy for plpaw2
4049 1.1 is addq.l &0x3,%a2 # plpaw2 points to end of longword
4050 1.1 is
4051 1.1 is mov.l %a0,%d1 # byte or word misaligned?
4052 1.1 is btst &0x0,%d1
4053 1.1 is bne.w casl2 # byte misaligned
4054 1.1 is
4055 1.1 is mov.l %d2,%d3 # d3 = update[15:0]
4056 1.1 is swap %d2 # d2 = update[31:16]
4057 1.1 is
4058 1.1 is # mask interrupts levels 0-6. save old mask value.
4059 1.1 is mov.w %sr,%d7 # save current SR
4060 1.1 is ori.w &0x0700,%sr # inhibit interrupts
4061 1.1 is
4062 1.1 is # load the SFC and DFC with the appropriate mode.
4063 1.1 is movc %sfc,%d6 # save old SFC/DFC
4064 1.1 is movc %d0,%sfc # load new sfc
4065 1.1 is movc %d0,%dfc # load new dfc
4066 1.1 is
4067 1.1 is # pre-load the operand ATC. no page faults should occur here because
4068 1.1 is # _real_lock_page() should have taken care of this.
4069 1.1 is plpaw (%a1) # load atc for ADDR
4070 1.1 is plpaw (%a2) # load atc for ADDR+3
4071 1.1 is
4072 1.1 is # push the operand lines from the cache if they exist.
4073 1.1 is cpushl %dc,(%a1) # push dirty data
4074 1.1 is cpushl %dc,(%a2) # push dirty data
4075 1.1 is
4076 1.1 is # load the BUSCR values.
4077 1.1 is mov.l &0x80000000,%a1 # assert LOCK* buscr value
4078 1.1 is mov.l &0xa0000000,%a2 # assert LOCKE* buscr value
4079 1.1 is mov.l &0x00000000,%a3 # buscr unlock value
4080 1.1 is
4081 1.1 is bra.b CASL_ENTER # start pre-loading icache
4082 1.1 is
4083 1.1 is #
4084 1.1 is # D0 = dst operand <-
4085 1.1 is # D1 = xxxxxxxx
4086 1.1 is # D2 = update[31:16] operand
4087 1.1 is # D3 = update[15:0] operand
4088 1.1 is # D4 = compare[31:0] operand
4089 1.1 is # D5 = xxxxxxxx
4090 1.1 is # D6 = old SFC/DFC
4091 1.1 is # D7 = old SR
4092 1.1 is # A0 = ADDR
4093 1.1 is # A1 = bus LOCK* value
4094 1.1 is # A2 = bus LOCKE* value
4095 1.1 is # A3 = bus unlock value
4096 1.1 is # A4 = xxxxxxxx
4097 1.1 is # A5 = xxxxxxxx
4098 1.1 is #
4099 1.1 is align 0x10
4100 1.1 is CASL_START:
4101 1.1 is movc %a1,%buscr # assert LOCK*
4102 1.1 is movs.l (%a0),%d0 # fetch Dest[31:0]
4103 1.1 is cmp.l %d0,%d4 # Dest - Compare
4104 1.1 is bne.b CASL_NOUPDATE
4105 1.1 is bra.b CASL_UPDATE
4106 1.1 is CASL_ENTER:
4107 1.1 is bra.b ~+16
4108 1.1 is
4109 1.1 is CASL_UPDATE:
4110 1.1 is movs.w %d2,(%a0)+ # Update[31:16] -> DEST
4111 1.1 is movc %a2,%buscr # assert LOCKE*
4112 1.1 is movs.w %d3,(%a0) # Update[15:0] -> DEST+0x2
4113 1.1 is bra.b CASL_UPDATE2
4114 1.1 is bra.b ~+16
4115 1.1 is
4116 1.1 is CASL_UPDATE2:
4117 1.1 is movc %a3,%buscr # unlock the bus
4118 1.1 is bra.b casl_update_done
4119 1.1 is nop
4120 1.1 is nop
4121 1.1 is nop
4122 1.1 is nop
4123 1.1 is bra.b ~+16
4124 1.1 is
4125 1.1 is CASL_NOUPDATE:
4126 1.1 is swap %d0 # get Dest[31:16]
4127 1.1 is movs.w %d0,(%a0)+ # Dest[31:16] -> DEST
4128 1.1 is swap %d0 # get Dest[15:0]
4129 1.1 is movc %a2,%buscr # assert LOCKE*
4130 1.1 is bra.b CASL_NOUPDATE2
4131 1.1 is bra.b ~+16
4132 1.1 is
4133 1.1 is CASL_NOUPDATE2:
4134 1.1 is movs.w %d0,(%a0) # Dest[15:0] -> DEST+0x2
4135 1.1 is movc %a3,%buscr # unlock the bus
4136 1.1 is bra.b casl_noupdate_done
4137 1.1 is nop
4138 1.1 is nop
4139 1.1 is bra.b ~+16
4140 1.1 is
4141 1.1 is CASL_FILLER:
4142 1.1 is nop
4143 1.1 is nop
4144 1.1 is nop
4145 1.1 is nop
4146 1.1 is nop
4147 1.1 is nop
4148 1.1 is nop
4149 1.1 is bra.b CASL_START
4150 1.1 is
4151 1.1 is #################################################################
4152 1.1 is # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON #
4153 1.1 is # CALLING _isp_cas_finish(). #
4154 1.1 is # #
4155 1.1 is # D0 = destination[31:0] operand #
4156 1.1 is # D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required #
4157 1.1 is # D2 = xxxxxxxx #
4158 1.1 is # D3 = xxxxxxxx #
4159 1.1 is # D4 = compare[31:0] operand #
4160 1.1 is # D5 = xxxxxxxx #
4161 1.1 is # D6 = xxxxxxxx #
4162 1.1 is # D7 = xxxxxxxx #
4163 1.1 is # A0 = xxxxxxxx #
4164 1.1 is # A1 = xxxxxxxx #
4165 1.1 is # A2 = xxxxxxxx #
4166 1.1 is # A3 = xxxxxxxx #
4167 1.1 is # A4 = xxxxxxxx #
4168 1.1 is # A5 = xxxxxxxx #
4169 1.1 is # A6 = frame pointer #
4170 1.1 is # A7 = stack pointer #
4171 1.1 is #################################################################
4172 1.1 is
4173 1.1 is casl_noupdate_done:
4174 1.1 is
4175 1.1 is # restore previous SFC/DFC value.
4176 1.1 is movc %d6,%sfc # restore old SFC
4177 1.1 is movc %d6,%dfc # restore old DFC
4178 1.1 is
4179 1.1 is # restore previous interrupt mask level.
4180 1.1 is mov.w %d7,%sr # restore old SR
4181 1.1 is
4182 1.1 is sf %d1 # indicate no update was done
4183 1.1 is bra.l _isp_cas_finish
4184 1.1 is
4185 1.1 is casl_update_done:
4186 1.1 is
4187 1.1 is # restore previous SFC/DFC value.
4188 1.1 is movc %d6,%sfc # restore old SFC
4189 1.1 is movc %d6,%dfc # restore old DFC
4190 1.1 is
4191 1.1 is # restore previous interrupts mask level.
4192 1.1 is mov.w %d7,%sr # restore old SR
4193 1.1 is
4194 1.1 is st %d1 # indicate update was done
4195 1.1 is bra.l _isp_cas_finish
4196 1.1 is
4197 1.1 is #######################################
4198 1.1 is casl2:
4199 1.1 is mov.l %d2,%d5 # d5 = Update[7:0]
4200 1.1 is lsr.l &0x8,%d2
4201 1.1 is mov.l %d2,%d3 # d3 = Update[23:8]
4202 1.1 is swap %d2 # d2 = Update[31:24]
4203 1.1 is
4204 1.1 is # mask interrupts levels 0-6. save old mask value.
4205 1.1 is mov.w %sr,%d7 # save current SR
4206 1.1 is ori.w &0x0700,%sr # inhibit interrupts
4207 1.1 is
4208 1.1 is # load the SFC and DFC with the appropriate mode.
4209 1.1 is movc %sfc,%d6 # save old SFC/DFC
4210 1.1 is movc %d0,%sfc # load new sfc
4211 1.1 is movc %d0,%dfc # load new dfc
4212 1.1 is
4213 1.1 is # pre-load the operand ATC. no page faults should occur here because
4214 1.1 is # _real_lock_page() should have taken care of this already.
4215 1.1 is plpaw (%a1) # load atc for ADDR
4216 1.1 is plpaw (%a2) # load atc for ADDR+3
4217 1.1 is
4218 1.1 is # puch the operand lines from the cache if they exist.
4219 1.1 is cpushl %dc,(%a1) # push dirty data
4220 1.1 is cpushl %dc,(%a2) # push dirty data
4221 1.1 is
4222 1.1 is # load the BUSCR values.
4223 1.1 is mov.l &0x80000000,%a1 # assert LOCK* buscr value
4224 1.1 is mov.l &0xa0000000,%a2 # assert LOCKE* buscr value
4225 1.1 is mov.l &0x00000000,%a3 # buscr unlock value
4226 1.1 is
4227 1.1 is # pre-load the instruction cache for the following algorithm.
4228 1.1 is # this will minimize the number of cycles that LOCK* will be asserted.
4229 1.1 is bra.b CASL2_ENTER # start pre-loading icache
4230 1.1 is
4231 1.1 is #
4232 1.1 is # D0 = dst operand <-
4233 1.1 is # D1 = xxxxxxxx
4234 1.1 is # D2 = update[31:24] operand
4235 1.1 is # D3 = update[23:8] operand
4236 1.1 is # D4 = compare[31:0] operand
4237 1.1 is # D5 = update[7:0] operand
4238 1.1 is # D6 = old SFC/DFC
4239 1.1 is # D7 = old SR
4240 1.1 is # A0 = ADDR
4241 1.1 is # A1 = bus LOCK* value
4242 1.1 is # A2 = bus LOCKE* value
4243 1.1 is # A3 = bus unlock value
4244 1.1 is # A4 = xxxxxxxx
4245 1.1 is # A5 = xxxxxxxx
4246 1.1 is #
4247 1.1 is align 0x10
4248 1.1 is CASL2_START:
4249 1.1 is movc %a1,%buscr # assert LOCK*
4250 1.1 is movs.l (%a0),%d0 # fetch Dest[31:0]
4251 1.1 is cmp.l %d0,%d4 # Dest - Compare
4252 1.1 is bne.b CASL2_NOUPDATE
4253 1.1 is bra.b CASL2_UPDATE
4254 1.1 is CASL2_ENTER:
4255 1.1 is bra.b ~+16
4256 1.1 is
4257 1.1 is CASL2_UPDATE:
4258 1.1 is movs.b %d2,(%a0)+ # Update[31:24] -> DEST
4259 1.1 is movs.w %d3,(%a0)+ # Update[23:8] -> DEST+0x1
4260 1.1 is movc %a2,%buscr # assert LOCKE*
4261 1.1 is bra.b CASL2_UPDATE2
4262 1.1 is bra.b ~+16
4263 1.1 is
4264 1.1 is CASL2_UPDATE2:
4265 1.1 is movs.b %d5,(%a0) # Update[7:0] -> DEST+0x3
4266 1.1 is movc %a3,%buscr # unlock the bus
4267 1.1 is bra.w casl_update_done
4268 1.1 is nop
4269 1.1 is bra.b ~+16
4270 1.1 is
4271 1.1 is CASL2_NOUPDATE:
4272 1.1 is rol.l &0x8,%d0 # get Dest[31:24]
4273 1.1 is movs.b %d0,(%a0)+ # Dest[31:24] -> DEST
4274 1.1 is swap %d0 # get Dest[23:8]
4275 1.1 is movs.w %d0,(%a0)+ # Dest[23:8] -> DEST+0x1
4276 1.1 is bra.b CASL2_NOUPDATE2
4277 1.1 is bra.b ~+16
4278 1.1 is
4279 1.1 is CASL2_NOUPDATE2:
4280 1.1 is rol.l &0x8,%d0 # get Dest[7:0]
4281 1.1 is movc %a2,%buscr # assert LOCKE*
4282 1.1 is movs.b %d0,(%a0) # Dest[7:0] -> DEST+0x3
4283 1.1 is bra.b CASL2_NOUPDATE3
4284 1.1 is nop
4285 1.1 is bra.b ~+16
4286 1.1 is
4287 1.1 is CASL2_NOUPDATE3:
4288 1.1 is movc %a3,%buscr # unlock the bus
4289 1.1 is bra.w casl_noupdate_done
4290 1.1 is nop
4291 1.1 is nop
4292 1.1 is nop
4293 1.1 is bra.b ~+16
4294 1.1 is
4295 1.1 is CASL2_FILLER:
4296 1.1 is nop
4297 1.1 is nop
4298 1.1 is nop
4299 1.1 is nop
4300 1.1 is nop
4301 1.1 is nop
4302 1.1 is nop
4303 1.1 is bra.b CASL2_START
4304 1.1 is
4305 1.1 is ####
4306 1.1 is ####
4307 1.1 is # end label used by _isp_cas_inrange()
4308 1.1 is global _CASHI
4309 1.1 is _CASHI:
4310