flat assembler
Message board for the users of flat assembler.
 flat assembler > Main > load 128 bit signed integer to st0
Author
petelomax

Joined: 19 Jan 2013
Posts: 4
Location: London

# load 128 bit signed integer to st0

OK, I am starting to feel a little stupid now.. I have a 128-bit signed integer in rdx:rax, how do I get it (or a reasonable representation of it) into st0?

It is in an error handler, so neither speed nor pin-point accuracy is an issue, but getting 0 or -Infinity, the best I have yet managed, just because it is 65 bits (about 3e19) is not on!

Pete
31 Jul 2017, 09:44
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 15480
I guess the process could be like this:
1. Scan the integer for the most significant bit (note that negative numbers make this a little bit tricky).
2. Shift it left to move out the higher bits.
3. Load the highest 64-bit part of the integer into st0.
4. Scale st0 into range by the amount you shifted in step 2.
31 Jul 2017, 10:23
Furs

Joined: 04 Mar 2016
Posts: 1010
Load rax into st1, rdx into st0, multiply st0 by 2^64 (adjusting exponent only really), add st0 and st1 and pop?

EDIT: hmm seems the numbers are signed, I guess you'll have to convert them to abs value somehow (not individually) or the simple method won't work
31 Jul 2017, 12:28
Tomasz Grysztar
Assembly Artist

Joined: 16 Jun 2003
Posts: 6730
Location: Kraków, Poland
The 80-bit format used by FPU is actually quite simple and you can do such conversion without any FPU instructions. I quickly scribbled this version:
 Code: int128_to_float80: ; in: rdx:rax = singed 128-bit integer ; out: dx:rax = 80-bit float         test    rdx,rdx         jns     uint128_to_float80         not     rdx     ;\         not     rax     ; \  this is just a         add     rax,1   ; /  neg rdx:rax         adc     rdx,0   ;/         call    uint128_to_float80         or      dx,8000h         retn uint128_to_float80: ; in: rdx:rax = unsigned 128-bit integer ; out: dx:rax = 80-bit float         bsr     r8,rdx         jz      .low         mov     cl,63         sub     cl,r8l         shld    rdx,rax,cl         mov     rax,rdx         lea     rdx,[16383+64+r8]         retn     .low:         bsr     r8,rax         jz      .zero         mov     cl,63         sub     cl,r8l         shl     rax,cl         lea     rdx,[16383+r8]         retn     .zero:         xor     eax,eax         xor     edx,edx         retn
Since you need the result in ST0, you'd have to use it like this:
 Code: call    int128_to_float80         mov     qword [tmp],rax         mov     word [tmp+8],dx         fld     tword [tmp]
31 Jul 2017, 15:25
Furs

Joined: 04 Mar 2016
Posts: 1010
You could shave off a few instructions with lzcnt instead of bsr (check the carry flag instead of zero though).

(also if optimizing for size -- xor eax, eax/xor edx, edx can be replaced by xor eax, eax/cdq)
31 Jul 2017, 15:56
petelomax

Joined: 19 Jan 2013
Posts: 4
Location: London
 Tomasz Grysztar wrote: I quickly scribbled this version:

Excellent stuff, works perfectly.

As a bonus, I don't feel quite so stupid for asking now!

Many thanks,
Pete
31 Jul 2017, 19:49
 Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First

 Jump to: Select a forum Official----------------Blog General----------------MainDOSWindowsLinuxUnixMenuetOS Specific----------------MacroinstructionsCompiler InternalsIDE DevelopmentOS ConstructionNon-x86 architecturesHigh Level LanguagesProgramming Language DesignProjects and IdeasExamples and Tutorials Other----------------FeedbackHeapTest Area

Forum Rules:
 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot vote in polls in this forumYou cannot attach files in this forumYou can download files in this forum