arch/sh/kernel/cpu/sh4/softfloat.c

Source file repositories/reference/linux-study-clean/arch/sh/kernel/cpu/sh4/softfloat.c

File Facts

System
Linux kernel
Corpus path
arch/sh/kernel/cpu/sh4/softfloat.c
Extension
.c
Size
22912 bytes
Lines
931
Domain
Architecture Layer
Bucket
arch/sh
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (aExp == 0x7FF) {
			return a;
		}
		if (bExp == 0) {
			--expDiff;
		} else {
			bSig |= LIT64(0x2000000000000000);
		}
		shift64RightJamming(bSig, expDiff, &bSig);
		zExp = aExp;
	} else if (expDiff < 0) {
		if (bExp == 0x7FF) {
			return packFloat64(zSign, 0x7FF, 0);
		}
		if (aExp == 0) {
			++expDiff;
		} else {
			aSig |= LIT64(0x2000000000000000);
		}
		shift64RightJamming(aSig, -expDiff, &aSig);
		zExp = bExp;
	} else {
		if (aExp == 0x7FF) {
			return a;
		}
		if (aExp == 0)
			return packFloat64(zSign, 0, (aSig + bSig) >> 9);
		zSig = LIT64(0x4000000000000000) + aSig + bSig;
		zExp = aExp;
		goto roundAndPack;
	}
	aSig |= LIT64(0x2000000000000000);
	zSig = (aSig + bSig) << 1;
	--zExp;
	if ((sbits64) zSig < 0) {
		zSig = aSig + bSig;
		++zExp;
	}
      roundAndPack:
	return roundAndPackFloat64(zSign, zExp, zSig);

}

float32 packFloat32(flag zSign, int16 zExp, bits32 zSig)
{
	return (((bits32) zSign) << 31) + (((bits32) zExp) << 23) + zSig;
}

void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr)
{
	bits32 z;
	if (count == 0) {
		z = a;
	} else if (count < 32) {
		z = (a >> count) | ((a << ((-count) & 31)) != 0);
	} else {
		z = (a != 0);
	}
	*zPtr = z;
}

static float32 roundAndPackFloat32(flag zSign, int16 zExp, bits32 zSig)
{
	flag roundNearestEven;
	int8 roundIncrement, roundBits;
	flag isTiny;

	/* SH4 has only 2 rounding modes - round to nearest and round to zero */
	roundNearestEven = (float_rounding_mode() == FPSCR_RM_NEAREST);
	roundIncrement = 0x40;
	if (!roundNearestEven) {
		roundIncrement = 0;
	}
	roundBits = zSig & 0x7F;
	if (0xFD <= (bits16) zExp) {
		if ((0xFD < zExp)
		    || ((zExp == 0xFD)
			&& ((sbits32) (zSig + roundIncrement) < 0))
		    ) {
			float_raise(FPSCR_CAUSE_OVERFLOW | FPSCR_CAUSE_INEXACT);
			return packFloat32(zSign, 0xFF,
					   0) - (roundIncrement == 0);
		}
		if (zExp < 0) {
			isTiny = (zExp < -1)
			    || (zSig + roundIncrement < 0x80000000);
			shift32RightJamming(zSig, -zExp, &zSig);
			zExp = 0;
			roundBits = zSig & 0x7F;
			if (isTiny && roundBits)

Annotation

Implementation Notes