summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/m68k/m68040/fpsp/smovecr.S
blob: 000adcf8cd77dc7f01afc44cb12dcb85a252102c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
//
//      $Id$
//
//	smovecr.sa 3.1 12/10/90
//
//	The entry point sMOVECR returns the constant at the
//	offset given in the instruction field.
//
//	Input: An offset in the instruction word.
//
//	Output:	The constant rounded to the user's rounding
//		mode unchecked for overflow.
//
//	Modified: fp0.
//
//
//		Copyright (C) Motorola, Inc. 1990
//			All Rights Reserved
//
//	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
//	The copyright notice above does not evidence any
//	actual or intended publication of such source code.

//SMOVECR	idnt	2,1 | Motorola 040 Floating Point Software Package

	|section 8

#include "fpsp.defs"

	|xref	nrm_set
	|xref	round
	|xref	PIRN
	|xref	PIRZRM
	|xref	PIRP
	|xref	SMALRN
	|xref	SMALRZRM
	|xref	SMALRP
	|xref	BIGRN
	|xref	BIGRZRM
	|xref	BIGRP

FZERO:	.long	00000000
//
//	FMOVECR
//
	.global	smovcr
smovcr:
	bfextu	CMDREG1B(%a6){#9:#7},%d0 //get offset
	bfextu	USER_FPCR(%a6){#26:#2},%d1 //get rmode
//
// check range of offset
//
	tstb	%d0		//if zero, offset is to pi
	beqs	PI_TBL		//it is pi
	cmpib	#0x0a,%d0		//check range $01 - $0a
	bles	Z_VAL		//if in this range, return zero
	cmpib	#0x0e,%d0		//check range $0b - $0e
	bles	SM_TBL		//valid constants in this range
	cmpib	#0x2f,%d0		//check range $10 - $2f
	bles	Z_VAL		//if in this range, return zero
	cmpib	#0x3f,%d0		//check range $30 - $3f
	ble  	BG_TBL		//valid constants in this range
Z_VAL:
	fmoves	FZERO,%fp0
	rts
PI_TBL:
	tstb	%d1		//offset is zero, check for rmode
	beqs	PI_RN		//if zero, rn mode
	cmpib	#0x3,%d1		//check for rp
	beqs	PI_RP		//if 3, rp mode
PI_RZRM:
	leal	PIRZRM,%a0	//rmode is rz or rm, load PIRZRM in a0
	bra	set_finx
PI_RN:
	leal	PIRN,%a0		//rmode is rn, load PIRN in a0
	bra	set_finx
PI_RP:
	leal	PIRP,%a0		//rmode is rp, load PIRP in a0
	bra	set_finx
SM_TBL:
	subil	#0xb,%d0		//make offset in 0 - 4 range
	tstb	%d1		//check for rmode
	beqs	SM_RN		//if zero, rn mode
	cmpib	#0x3,%d1		//check for rp
	beqs	SM_RP		//if 3, rp mode
SM_RZRM:
	leal	SMALRZRM,%a0	//rmode is rz or rm, load SMRZRM in a0
	cmpib	#0x2,%d0		//check if result is inex
	ble	set_finx	//if 0 - 2, it is inexact
	bra	no_finx		//if 3, it is exact
SM_RN:
	leal	SMALRN,%a0	//rmode is rn, load SMRN in a0
	cmpib	#0x2,%d0		//check if result is inex
	ble	set_finx	//if 0 - 2, it is inexact
	bra	no_finx		//if 3, it is exact
SM_RP:
	leal	SMALRP,%a0	//rmode is rp, load SMRP in a0
	cmpib	#0x2,%d0		//check if result is inex
	ble	set_finx	//if 0 - 2, it is inexact
	bra	no_finx		//if 3, it is exact
BG_TBL:
	subil	#0x30,%d0		//make offset in 0 - f range
	tstb	%d1		//check for rmode
	beqs	BG_RN		//if zero, rn mode
	cmpib	#0x3,%d1		//check for rp
	beqs	BG_RP		//if 3, rp mode
BG_RZRM:
	leal	BIGRZRM,%a0	//rmode is rz or rm, load BGRZRM in a0
	cmpib	#0x1,%d0		//check if result is inex
	ble	set_finx	//if 0 - 1, it is inexact
	cmpib	#0x7,%d0		//second check
	ble	no_finx		//if 0 - 7, it is exact
	bra	set_finx	//if 8 - f, it is inexact
BG_RN:
	leal	BIGRN,%a0	//rmode is rn, load BGRN in a0
	cmpib	#0x1,%d0		//check if result is inex
	ble	set_finx	//if 0 - 1, it is inexact
	cmpib	#0x7,%d0		//second check
	ble	no_finx		//if 0 - 7, it is exact
	bra	set_finx	//if 8 - f, it is inexact
BG_RP:
	leal	BIGRP,%a0	//rmode is rp, load SMRP in a0
	cmpib	#0x1,%d0		//check if result is inex
	ble	set_finx	//if 0 - 1, it is inexact
	cmpib	#0x7,%d0		//second check
	ble	no_finx		//if 0 - 7, it is exact
//	bra	set_finx	;if 8 - f, it is inexact
set_finx:
	orl	#inx2a_mask,USER_FPSR(%a6) //set inex2/ainex
no_finx:
	mulul	#12,%d0			//use offset to point into tables
	movel	%d1,L_SCR1(%a6)		//load mode for round call
	bfextu	USER_FPCR(%a6){#24:#2},%d1	//get precision
	tstl	%d1			//check if extended precision
//
// Precision is extended
//
	bnes	not_ext			//if extended, do not call round
	fmovemx (%a0,%d0),%fp0-%fp0		//return result in fp0
	rts
//
// Precision is single or double
//
not_ext:
	swap	%d1			//rnd prec in upper word of d1
	addl	L_SCR1(%a6),%d1		//merge rmode in low word of d1
	movel	(%a0,%d0),FP_SCR1(%a6)	//load first word to temp storage
	movel	4(%a0,%d0),FP_SCR1+4(%a6)	//load second word
	movel	8(%a0,%d0),FP_SCR1+8(%a6)	//load third word
	clrl	%d0			//clear g,r,s
	lea	FP_SCR1(%a6),%a0
	btstb	#sign_bit,LOCAL_EX(%a0)
	sne	LOCAL_SGN(%a0)		//convert to internal ext. format

	bsr	round			//go round the mantissa

	bfclr	LOCAL_SGN(%a0){#0:#8}	//convert back to IEEE ext format
	beqs	fin_fcr
	bsetb	#sign_bit,LOCAL_EX(%a0)
fin_fcr:
	fmovemx (%a0),%fp0-%fp0
	rts

	|end