source: rtems/bsps/m68k/shared/fpsp/x_operr.S @ 3cf2bf63

5
Last change on this file since 3cf2bf63 was 3cf2bf63, checked in by Sebastian Huber <sebastian.huber@…>, on 03/26/18 at 10:17:06

bsps/m68k: Move fpsp support to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 9.8 KB
Line 
1#include "fpsp-namespace.h"
2//
3//
4//      x_operr.sa 3.5 7/1/91
5//
6//      fpsp_operr --- FPSP handler for operand error exception
7//
8//      See 68040 User's Manual pp. 9-44f
9//
10// Note 1: For trap disabled 040 does the following:
11// If the dest is a fp reg, then an extended precision non_signaling
12// NAN is stored in the dest reg.  If the dest format is b, w, or l and
13// the source op is a NAN, then garbage is stored as the result (actually
14// the upper 32 bits of the mantissa are sent to the integer unit). If
15// the dest format is integer (b, w, l) and the operr is caused by
16// integer overflow, or the source op is inf, then the result stored is
17// garbage.
18// There are three cases in which operr is incorrectly signaled on the
19// 040.  This occurs for move_out of format b, w, or l for the largest
20// negative integer (-2^7 for b, -2^15 for w, -2^31 for l).
21//
22//        On opclass = 011 fmove.(b,w,l) that causes a conversion
23//        overflow -> OPERR, the exponent in wbte (and fpte) is:
24//              byte    56 - (62 - exp)
25//              word    48 - (62 - exp)
26//              long    32 - (62 - exp)
27//
28//                      where exp = (true exp) - 1
29//
30//  So, wbtemp and fptemp will contain the following on erroneously
31//        signalled operr:
32//                      fpts = 1
33//                      fpte = $4000  (15 bit externally)
34//              byte    fptm = $ffffffff ffffff80
35//              word    fptm = $ffffffff ffff8000
36//              long    fptm = $ffffffff 80000000
37//
38// Note 2: For trap enabled 040 does the following:
39// If the inst is move_out, then same as Note 1.
40// If the inst is not move_out, the dest is not modified.
41// The exceptional operand is not defined for integer overflow
42// during a move_out.
43//
44
45//              Copyright (C) Motorola, Inc. 1990
46//                      All Rights Reserved
47//
48//      THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
49//      The copyright notice above does not evidence any
50//      actual or intended publication of such source code.
51
52X_OPERR:        //idnt    2,1 | Motorola 040 Floating Point Software Package
53
54        |section        8
55
56#include "fpsp.defs"
57
58        |xref   mem_write
59        |xref   real_operr
60        |xref   real_inex
61        |xref   get_fline
62        |xref   fpsp_done
63        |xref   reg_dest
64
65        .global fpsp_operr
66fpsp_operr:
67//
68        link            %a6,#-LOCAL_SIZE
69        fsave           -(%a7)
70        moveml          %d0-%d1/%a0-%a1,USER_DA(%a6)
71        fmovemx %fp0-%fp3,USER_FP0(%a6)
72        fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
73
74//
75// Check if this is an opclass 3 instruction.
76//  If so, fall through, else branch to operr_end
77//
78        btstb   #TFLAG,T_BYTE(%a6)
79        beqs    operr_end
80
81//
82// If the destination size is B,W,or L, the operr must be
83// handled here.
84//
85        movel   CMDREG1B(%a6),%d0
86        bfextu  %d0{#3:#3},%d0  //0=long, 4=word, 6=byte
87        cmpib   #0,%d0          //determine size; check long
88        beq     operr_long
89        cmpib   #4,%d0          //check word
90        beq     operr_word
91        cmpib   #6,%d0          //check byte
92        beq     operr_byte
93
94//
95// The size is not B,W,or L, so the operr is handled by the
96// kernel handler.  Set the operr bits and clean up, leaving
97// only the integer exception frame on the stack, and the
98// fpu in the original exceptional state.
99//
100operr_end:
101        bsetb           #operr_bit,FPSR_EXCEPT(%a6)
102        bsetb           #aiop_bit,FPSR_AEXCEPT(%a6)
103
104        moveml          USER_DA(%a6),%d0-%d1/%a0-%a1
105        fmovemx USER_FP0(%a6),%fp0-%fp3
106        fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
107        frestore        (%a7)+
108        unlk            %a6
109        bral            real_operr
110
111operr_long:
112        moveql  #4,%d1          //write size to d1
113        moveb   STAG(%a6),%d0   //test stag for nan
114        andib   #0xe0,%d0               //clr all but tag
115        cmpib   #0x60,%d0               //check for nan
116        beq     operr_nan
117        cmpil   #0x80000000,FPTEMP_LO(%a6) //test if ls lword is special
118        bnes    chklerr         //if not equal, check for incorrect operr
119        bsr     check_upper     //check if exp and ms mant are special
120        tstl    %d0
121        bnes    chklerr         //if d0 is true, check for incorrect operr
122        movel   #0x80000000,%d0 //store special case result
123        bsr     operr_store
124        bra     not_enabled     //clean and exit
125//
126//      CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
127//
128chklerr:
129        movew   FPTEMP_EX(%a6),%d0
130        andw    #0x7FFF,%d0     //ignore sign bit
131        cmpw    #0x3FFE,%d0     //this is the only possible exponent value
132        bnes    chklerr2
133fixlong:
134        movel   FPTEMP_LO(%a6),%d0
135        bsr     operr_store
136        bra     not_enabled
137chklerr2:
138        movew   FPTEMP_EX(%a6),%d0
139        andw    #0x7FFF,%d0     //ignore sign bit
140        cmpw    #0x4000,%d0
141        bcc     store_max       //exponent out of range
142
143        movel   FPTEMP_LO(%a6),%d0
144        andl    #0x7FFF0000,%d0 //look for all 1's on bits 30-16
145        cmpl    #0x7FFF0000,%d0
146        beqs    fixlong
147
148        tstl    FPTEMP_LO(%a6)
149        bpls    chklepos
150        cmpl    #0xFFFFFFFF,FPTEMP_HI(%a6)
151        beqs    fixlong
152        bra     store_max
153chklepos:
154        tstl    FPTEMP_HI(%a6)
155        beqs    fixlong
156        bra     store_max
157
158operr_word:
159        moveql  #2,%d1          //write size to d1
160        moveb   STAG(%a6),%d0   //test stag for nan
161        andib   #0xe0,%d0               //clr all but tag
162        cmpib   #0x60,%d0               //check for nan
163        beq     operr_nan
164        cmpil   #0xffff8000,FPTEMP_LO(%a6) //test if ls lword is special
165        bnes    chkwerr         //if not equal, check for incorrect operr
166        bsr     check_upper     //check if exp and ms mant are special
167        tstl    %d0
168        bnes    chkwerr         //if d0 is true, check for incorrect operr
169        movel   #0x80000000,%d0 //store special case result
170        bsr     operr_store
171        bra     not_enabled     //clean and exit
172//
173//      CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
174//
175chkwerr:
176        movew   FPTEMP_EX(%a6),%d0
177        andw    #0x7FFF,%d0     //ignore sign bit
178        cmpw    #0x3FFE,%d0     //this is the only possible exponent value
179        bnes    store_max
180        movel   FPTEMP_LO(%a6),%d0
181        swap    %d0
182        bsr     operr_store
183        bra     not_enabled
184
185operr_byte:
186        moveql  #1,%d1          //write size to d1
187        moveb   STAG(%a6),%d0   //test stag for nan
188        andib   #0xe0,%d0               //clr all but tag
189        cmpib   #0x60,%d0               //check for nan
190        beqs    operr_nan
191        cmpil   #0xffffff80,FPTEMP_LO(%a6) //test if ls lword is special
192        bnes    chkberr         //if not equal, check for incorrect operr
193        bsr     check_upper     //check if exp and ms mant are special
194        tstl    %d0
195        bnes    chkberr         //if d0 is true, check for incorrect operr
196        movel   #0x80000000,%d0 //store special case result
197        bsr     operr_store
198        bra     not_enabled     //clean and exit
199//
200//      CHECK FOR INCORRECTLY GENERATED OPERR EXCEPTION HERE
201//
202chkberr:
203        movew   FPTEMP_EX(%a6),%d0
204        andw    #0x7FFF,%d0     //ignore sign bit
205        cmpw    #0x3FFE,%d0     //this is the only possible exponent value
206        bnes    store_max
207        movel   FPTEMP_LO(%a6),%d0
208        asll    #8,%d0
209        swap    %d0
210        bsr     operr_store
211        bra     not_enabled
212
213//
214// This operr condition is not of the special case.  Set operr
215// and aiop and write the portion of the nan to memory for the
216// given size.
217//
218operr_nan:
219        orl     #opaop_mask,USER_FPSR(%a6) //set operr & aiop
220
221        movel   ETEMP_HI(%a6),%d0       //output will be from upper 32 bits
222        bsr     operr_store
223        bra     end_operr
224//
225// Store_max loads the max pos or negative for the size, sets
226// the operr and aiop bits, and clears inex and ainex, incorrectly
227// set by the 040.
228//
229store_max:
230        orl     #opaop_mask,USER_FPSR(%a6) //set operr & aiop
231        bclrb   #inex2_bit,FPSR_EXCEPT(%a6)
232        bclrb   #ainex_bit,FPSR_AEXCEPT(%a6)
233        fmovel  #0,%FPSR
234
235        tstw    FPTEMP_EX(%a6)  //check sign
236        blts    load_neg
237        movel   #0x7fffffff,%d0
238        bsr     operr_store
239        bra     end_operr
240load_neg:
241        movel   #0x80000000,%d0
242        bsr     operr_store
243        bra     end_operr
244
245//
246// This routine stores the data in d0, for the given size in d1,
247// to memory or data register as required.  A read of the fline
248// is required to determine the destination.
249//
250operr_store:
251        movel   %d0,L_SCR1(%a6) //move write data to L_SCR1
252        movel   %d1,-(%a7)      //save register size
253        bsrl    get_fline       //fline returned in d0
254        movel   (%a7)+,%d1
255        bftst   %d0{#26:#3}             //if mode is zero, dest is Dn
256        bnes    dest_mem
257//
258// Destination is Dn.  Get register number from d0. Data is on
259// the stack at (a7). D1 has size: 1=byte,2=word,4=long/single
260//
261        andil   #7,%d0          //isolate register number
262        cmpil   #4,%d1
263        beqs    op_long         //the most frequent case
264        cmpil   #2,%d1
265        bnes    op_con
266        orl     #8,%d0
267        bras    op_con
268op_long:
269        orl     #0x10,%d0
270op_con:
271        movel   %d0,%d1         //format size:reg for reg_dest
272        bral    reg_dest        //call to reg_dest returns to caller
273//                              ;of operr_store
274//
275// Destination is memory.  Get <ea> from integer exception frame
276// and call mem_write.
277//
278dest_mem:
279        leal    L_SCR1(%a6),%a0 //put ptr to write data in a0
280        movel   EXC_EA(%a6),%a1 //put user destination address in a1
281        movel   %d1,%d0         //put size in d0
282        bsrl    mem_write
283        rts
284//
285// Check the exponent for $c000 and the upper 32 bits of the
286// mantissa for $ffffffff.  If both are true, return d0 clr
287// and store the lower n bits of the least lword of FPTEMP
288// to d0 for write out.  If not, it is a real operr, and set d0.
289//
290check_upper:
291        cmpil   #0xffffffff,FPTEMP_HI(%a6) //check if first byte is all 1's
292        bnes    true_operr      //if not all 1's then was true operr
293        cmpiw   #0xc000,FPTEMP_EX(%a6) //check if incorrectly signalled
294        beqs    not_true_operr  //branch if not true operr
295        cmpiw   #0xbfff,FPTEMP_EX(%a6) //check if incorrectly signalled
296        beqs    not_true_operr  //branch if not true operr
297true_operr:
298        movel   #1,%d0          //signal real operr
299        rts
300not_true_operr:
301        clrl    %d0             //signal no real operr
302        rts
303
304//
305// End_operr tests for operr enabled.  If not, it cleans up the stack
306// and does an rte.  If enabled, it cleans up the stack and branches
307// to the kernel operr handler with only the integer exception
308// frame on the stack and the fpu in the original exceptional state
309// with correct data written to the destination.
310//
311end_operr:
312        btstb           #operr_bit,FPCR_ENABLE(%a6)
313        beqs            not_enabled
314enabled:
315        moveml          USER_DA(%a6),%d0-%d1/%a0-%a1
316        fmovemx USER_FP0(%a6),%fp0-%fp3
317        fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
318        frestore        (%a7)+
319        unlk            %a6
320        bral            real_operr
321
322not_enabled:
323//
324// It is possible to have either inex2 or inex1 exceptions with the
325// operr.  If the inex enable bit is set in the FPCR, and either
326// inex2 or inex1 occurred, we must clean up and branch to the
327// real inex handler.
328//
329ck_inex:
330        moveb   FPCR_ENABLE(%a6),%d0
331        andb    FPSR_EXCEPT(%a6),%d0
332        andib   #0x3,%d0
333        beq     operr_exit
334//
335// Inexact enabled and reported, and we must take an inexact exception.
336//
337take_inex:
338        moveb           #INEX_VEC,EXC_VEC+1(%a6)
339        movel           USER_FPSR(%a6),FPSR_SHADOW(%a6)
340        orl             #sx_mask,E_BYTE(%a6)
341        moveml          USER_DA(%a6),%d0-%d1/%a0-%a1
342        fmovemx USER_FP0(%a6),%fp0-%fp3
343        fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
344        frestore        (%a7)+
345        unlk            %a6
346        bral            real_inex
347//
348// Since operr is only an E1 exception, there is no need to frestore
349// any state back to the fpu.
350//
351operr_exit:
352        moveml          USER_DA(%a6),%d0-%d1/%a0-%a1
353        fmovemx USER_FP0(%a6),%fp0-%fp3
354        fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
355        unlk            %a6
356        bral            fpsp_done
357
358        |end
Note: See TracBrowser for help on using the repository browser.