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_add.S (4044B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2	.file	"reg_u_add.S"
      3/*---------------------------------------------------------------------------+
      4 |  reg_u_add.S                                                              |
      5 |                                                                           |
      6 | Add two valid (TAG_Valid) FPU_REG numbers, of the same sign, and put the  |
      7 |   result in a destination FPU_REG.                                        |
      8 |                                                                           |
      9 | Copyright (C) 1992,1993,1995,1997                                         |
     10 |                  W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
     11 |                  E-mail   billm@suburbia.net                              |
     12 |                                                                           |
     13 | Call from C as:                                                           |
     14 |   int  FPU_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,             |
     15 |                                                int control_w)             |
     16 |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
     17 |    one was raised, or -1 on internal error.                               |
     18 |                                                                           |
     19 +---------------------------------------------------------------------------*/
     20
     21/*
     22 |    Kernel addition routine FPU_u_add(reg *arg1, reg *arg2, reg *answ).
     23 |    Takes two valid reg f.p. numbers (TAG_Valid), which are
     24 |    treated as unsigned numbers,
     25 |    and returns their sum as a TAG_Valid or TAG_Special f.p. number.
     26 |    The returned number is normalized.
     27 |    Basic checks are performed if PARANOID is defined.
     28 */
     29
     30#include "exception.h"
     31#include "fpu_emu.h"
     32#include "control_w.h"
     33
     34.text
     35SYM_FUNC_START(FPU_u_add)
     36	pushl	%ebp
     37	movl	%esp,%ebp
     38	pushl	%esi
     39	pushl	%edi
     40	pushl	%ebx
     41
     42	movl	PARAM1,%esi		/* source 1 */
     43	movl	PARAM2,%edi		/* source 2 */
     44
     45	movl	PARAM6,%ecx
     46	movl	%ecx,%edx
     47	subl	PARAM7,%ecx			/* exp1 - exp2 */
     48	jge	L_arg1_larger
     49
     50	/* num1 is smaller */
     51	movl	SIGL(%esi),%ebx
     52	movl	SIGH(%esi),%eax
     53
     54	movl	%edi,%esi
     55	movl	PARAM7,%edx
     56	negw	%cx
     57	jmp	L_accum_loaded
     58
     59L_arg1_larger:
     60	/* num1 has larger or equal exponent */
     61	movl	SIGL(%edi),%ebx
     62	movl	SIGH(%edi),%eax
     63
     64L_accum_loaded:
     65	movl	PARAM3,%edi		/* destination */
     66	movw	%dx,EXP(%edi)		/* Copy exponent to destination */
     67
     68	xorl	%edx,%edx		/* clear the extension */
     69
     70#ifdef PARANOID
     71	testl	$0x80000000,%eax
     72	je	L_bugged
     73
     74	testl	$0x80000000,SIGH(%esi)
     75	je	L_bugged
     76#endif /* PARANOID */
     77
     78/* The number to be shifted is in %eax:%ebx:%edx */
     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	movl	%eax,%edx
    118	orl	%ebx,%ebx
    119	jz	L_more_63_no_low
    120
    121	orl	$1,%edx
    122	jmp	L_more_63_no_low
    123
    124L_more_than_64:
    125	movl	$1,%edx		/* The shifted nr always at least one '1' */
    126
    127L_more_63_no_low:
    128	xorl	%ebx,%ebx
    129	xorl	%eax,%eax
    130
    131L_shift_done:
    132	/* Now do the addition */
    133	addl	SIGL(%esi),%ebx
    134	adcl	SIGH(%esi),%eax
    135	jnc	L_round_the_result
    136
    137	/* Overflow, adjust the result */
    138	rcrl	$1,%eax
    139	rcrl	$1,%ebx
    140	rcrl	$1,%edx
    141	jnc	L_no_bit_lost
    142
    143	orl	$1,%edx
    144
    145L_no_bit_lost:
    146	incw	EXP(%edi)
    147
    148L_round_the_result:
    149	jmp	fpu_reg_round	/* Round the result */
    150
    151
    152
    153#ifdef PARANOID
    154/* If we ever get here then we have problems! */
    155L_bugged:
    156	pushl	EX_INTERNAL|0x201
    157	call	EXCEPTION
    158	pop	%ebx
    159	movl	$-1,%eax
    160	jmp	L_exit
    161
    162L_exit:
    163	popl	%ebx
    164	popl	%edi
    165	popl	%esi
    166	leave
    167	RET
    168#endif /* PARANOID */
    169SYM_FUNC_END(FPU_u_add)