cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

reg_u_sub.S (6189B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2	.file	"reg_u_sub.S"
      3/*---------------------------------------------------------------------------+
      4 |  reg_u_sub.S                                                              |
      5 |                                                                           |
      6 | Core floating point subtraction routine.                                  |
      7 |                                                                           |
      8 | Copyright (C) 1992,1993,1995,1997                                         |
      9 |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
     10 |                  E-mail   billm@suburbia.net                              |
     11 |                                                                           |
     12 | Call from C as:                                                           |
     13 |    int FPU_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,             |
     14 |                                                int control_w)             |
     15 |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
     16 |    one was raised, or -1 on internal error.                               |
     17 |                                                                           |
     18 +---------------------------------------------------------------------------*/
     19
     20/*
     21 |    Kernel subtraction routine FPU_u_sub(reg *arg1, reg *arg2, reg *answ).
     22 |    Takes two valid reg f.p. numbers (TAG_Valid), which are
     23 |    treated as unsigned numbers,
     24 |    and returns their difference as a TAG_Valid or TAG_Zero f.p.
     25 |    number.
     26 |    The first number (arg1) must be the larger.
     27 |    The returned number is normalized.
     28 |    Basic checks are performed if PARANOID is defined.
     29 */
     30
     31#include "exception.h"
     32#include "fpu_emu.h"
     33#include "control_w.h"
     34
     35.text
     36SYM_FUNC_START(FPU_u_sub)
     37	pushl	%ebp
     38	movl	%esp,%ebp
     39	pushl	%esi
     40	pushl	%edi
     41	pushl	%ebx
     42
     43	movl	PARAM1,%esi	/* source 1 */
     44	movl	PARAM2,%edi	/* source 2 */
     45	
     46	movl	PARAM6,%ecx
     47	subl	PARAM7,%ecx	/* exp1 - exp2 */
     48
     49#ifdef PARANOID
     50	/* source 2 is always smaller than source 1 */
     51	js	L_bugged_1
     52
     53	testl	$0x80000000,SIGH(%edi)	/* The args are assumed to be be normalized */
     54	je	L_bugged_2
     55
     56	testl	$0x80000000,SIGH(%esi)
     57	je	L_bugged_2
     58#endif /* PARANOID */
     59
     60/*--------------------------------------+
     61 |	Form a register holding the     |
     62 |	smaller number                  |
     63 +--------------------------------------*/
     64	movl	SIGH(%edi),%eax	/* register ms word */
     65	movl	SIGL(%edi),%ebx	/* register ls word */
     66
     67	movl	PARAM3,%edi	/* destination */
     68	movl	PARAM6,%edx
     69	movw	%dx,EXP(%edi)	/* Copy exponent to destination */
     70
     71	xorl	%edx,%edx	/* register extension */
     72
     73/*--------------------------------------+
     74 |	Shift the temporary register	|
     75 |      right the required number of	|
     76 |	places.				|
     77 +--------------------------------------*/
     78
     79	cmpw	$32,%cx		/* shrd only works for 0..31 bits */
     80	jnc	L_more_than_31
     81
     82/* less than 32 bits */
     83	shrd	%cl,%ebx,%edx
     84	shrd	%cl,%eax,%ebx
     85	shr	%cl,%eax
     86	jmp	L_shift_done
     87
     88L_more_than_31:
     89	cmpw	$64,%cx
     90	jnc	L_more_than_63
     91
     92	subb	$32,%cl
     93	jz	L_exactly_32
     94
     95	shrd	%cl,%eax,%edx
     96	shr	%cl,%eax
     97	orl	%ebx,%ebx
     98	jz	L_more_31_no_low	/* none of the lowest bits is set */
     99
    100	orl	$1,%edx			/* record the fact in the extension */
    101
    102L_more_31_no_low:
    103	movl	%eax,%ebx
    104	xorl	%eax,%eax
    105	jmp	L_shift_done
    106
    107L_exactly_32:
    108	movl	%ebx,%edx
    109	movl	%eax,%ebx
    110	xorl	%eax,%eax
    111	jmp	L_shift_done
    112
    113L_more_than_63:
    114	cmpw	$65,%cx
    115	jnc	L_more_than_64
    116
    117	/* Shift right by 64 bits */
    118	movl	%eax,%edx
    119	orl	%ebx,%ebx
    120	jz	L_more_63_no_low
    121
    122	orl	$1,%edx
    123	jmp	L_more_63_no_low
    124
    125L_more_than_64:
    126	jne	L_more_than_65
    127
    128	/* Shift right by 65 bits */
    129	/* Carry is clear if we get here */
    130	movl	%eax,%edx
    131	rcrl	%edx
    132	jnc	L_shift_65_nc
    133
    134	orl	$1,%edx
    135	jmp	L_more_63_no_low
    136
    137L_shift_65_nc:
    138	orl	%ebx,%ebx
    139	jz	L_more_63_no_low
    140
    141	orl	$1,%edx
    142	jmp	L_more_63_no_low
    143
    144L_more_than_65:
    145	movl	$1,%edx		/* The shifted nr always at least one '1' */
    146
    147L_more_63_no_low:
    148	xorl	%ebx,%ebx
    149	xorl	%eax,%eax
    150
    151L_shift_done:
    152L_subtr:
    153/*------------------------------+
    154 |	Do the subtraction	|
    155 +------------------------------*/
    156	xorl	%ecx,%ecx
    157	subl	%edx,%ecx
    158	movl	%ecx,%edx
    159	movl	SIGL(%esi),%ecx
    160	sbbl	%ebx,%ecx
    161	movl	%ecx,%ebx
    162	movl	SIGH(%esi),%ecx
    163	sbbl	%eax,%ecx
    164	movl	%ecx,%eax
    165
    166#ifdef PARANOID
    167	/* We can never get a borrow */
    168	jc	L_bugged
    169#endif /* PARANOID */
    170
    171/*--------------------------------------+
    172 |	Normalize the result		|
    173 +--------------------------------------*/
    174	testl	$0x80000000,%eax
    175	jnz	L_round		/* no shifting needed */
    176
    177	orl	%eax,%eax
    178	jnz	L_shift_1	/* shift left 1 - 31 bits */
    179
    180	orl	%ebx,%ebx
    181	jnz	L_shift_32	/* shift left 32 - 63 bits */
    182
    183/*
    184 *	 A rare case, the only one which is non-zero if we got here
    185 *         is:           1000000 .... 0000
    186 *                      -0111111 .... 1111 1
    187 *                       -------------------- 
    188 *                       0000000 .... 0000 1 
    189 */
    190
    191	cmpl	$0x80000000,%edx
    192	jnz	L_must_be_zero
    193
    194	/* Shift left 64 bits */
    195	subw	$64,EXP(%edi)
    196	xchg	%edx,%eax
    197	jmp	fpu_reg_round
    198
    199L_must_be_zero:
    200#ifdef PARANOID
    201	orl	%edx,%edx
    202	jnz	L_bugged_3
    203#endif /* PARANOID */ 
    204
    205	/* The result is zero */
    206	movw	$0,EXP(%edi)		/* exponent */
    207	movl	$0,SIGL(%edi)
    208	movl	$0,SIGH(%edi)
    209	movl	TAG_Zero,%eax
    210	jmp	L_exit
    211
    212L_shift_32:
    213	movl	%ebx,%eax
    214	movl	%edx,%ebx
    215	movl	$0,%edx
    216	subw	$32,EXP(%edi)	/* Can get underflow here */
    217
    218/* We need to shift left by 1 - 31 bits */
    219L_shift_1:
    220	bsrl	%eax,%ecx	/* get the required shift in %ecx */
    221	subl	$31,%ecx
    222	negl	%ecx
    223	shld	%cl,%ebx,%eax
    224	shld	%cl,%edx,%ebx
    225	shl	%cl,%edx
    226	subw	%cx,EXP(%edi)	/* Can get underflow here */
    227
    228L_round:
    229	jmp	fpu_reg_round	/* Round the result */
    230
    231
    232#ifdef PARANOID
    233L_bugged_1:
    234	pushl	EX_INTERNAL|0x206
    235	call	EXCEPTION
    236	pop	%ebx
    237	jmp	L_error_exit
    238
    239L_bugged_2:
    240	pushl	EX_INTERNAL|0x209
    241	call	EXCEPTION
    242	pop	%ebx
    243	jmp	L_error_exit
    244
    245L_bugged_3:
    246	pushl	EX_INTERNAL|0x210
    247	call	EXCEPTION
    248	pop	%ebx
    249	jmp	L_error_exit
    250
    251L_bugged_4:
    252	pushl	EX_INTERNAL|0x211
    253	call	EXCEPTION
    254	pop	%ebx
    255	jmp	L_error_exit
    256
    257L_bugged:
    258	pushl	EX_INTERNAL|0x212
    259	call	EXCEPTION
    260	pop	%ebx
    261	jmp	L_error_exit
    262
    263L_error_exit:
    264	movl	$-1,%eax
    265
    266#endif /* PARANOID */
    267
    268L_exit:
    269	popl	%ebx
    270	popl	%edi
    271	popl	%esi
    272	leave
    273	RET
    274SYM_FUNC_END(FPU_u_sub)