# LDS

### From Msim

This page refers to the LDS instruction.

## Details

LDS loads from memory an single precision floating point.

lds Ra, Sign Extended Offset(Rb) Ra is a floating point register Rb is a general purpose register Ra = Memory[Sign Extended Offset + Rb] The result in Ra is a double precision value. Therefore, it must be converted from single to double precision.

## Implementation

#define LDS_IMPL \ { \ sqword_t _longhold, _e1, _e2; \ enum md_fault_type _fault; \ \ _longhold = READ_WORD(GPR(RB) + SEXT(OFS), _fault); \ if(_fault != md_fault_none) \ DECLARE_FAULT(_fault); \ \ _e1 = _longhold & 0x40000000; \ _e2 = (_longhold >> 23) & ULL(0x7f); \ if(_e1) \ { \ if(_e2 == ULL(0x7f)) \ _e2 = ULL(0x7ff); \ else \ _e2 |= ULL(0x400); \ } \ else \ { \ if(_e2 != 0) \ _e2 |= ULL(0x380); \ } \ SET_FPR_Q(RA, ((_longhold & ULL(0x80000000)) << 32 \ | _e2 << 52 | (_longhold & ULL(0x7fffff)) << 29)); \ }

## Correction

In the original code:

#define LDS_IMPL \ { \ sqword_t _longhold, _e1, _e2; \ enum md_fault_type _fault; \ \ _longhold = READ_WORD(GPR(RB) + SEXT(OFS), _fault); \ if (_fault != md_fault_none) \ DECLARE_FAULT(_fault); \ \ _e1 = _longhold & 0x40000000; \ _e2 = (_longhold >> 23) & ULL(0x7f); \ if (_e1) \ { \if (_e2 == ULL(0x3f800000))\ _e2 = ULL(0x7ff); \ else \ _e2 |= ULL(0x400); \ } \ else \ { \if (_e2 == 0) \ _e2 = 0; \ else \ _e2 |= ULL(0x380);\ } \ SET_FPR_Q(RA, ((_longhold & ULL(0x80000000)) << 32 \ | _e2 << 52 | (_longhold & ULL(0x7fffff)) << 29)); \ }

The first bolded part is incorrect:

- _e2 is bitmasked with 0x7f (lowest 7 bits) and theref3re can never equal 0x3f800000. Since the code changed _e2 to 0x7ff, this reflects an all 1s exponent in double precision. The correct check is for 0x7f which reflect 7 of the 8 exponent bits from a single precision value (_e1 retains the MSB exponent bit). If the _e2 hadn't been shifted (and been bitmasked for only the exponent bits) the original check would have been correct.

The second bolded part was fine but has been optimized:

- e2 was not changed if it equaled zero. It would be ORed with 0x380 if it was not equal to zero. Therefore, we change the case to check and change on _e2 != 0 only.