[DONE] TB1.3PR1.879 Problems with float/double in X64 mode

TailBite specific forum

Moderators: gnozal, ABBKlaus, lexvictory

ABBKlaus
Addict
Addict
Posts: 1143
Joined: Sat Apr 10, 2004 1:20 pm
Location: Germany

[DONE] TB1.3PR1.879 Problems with float/double in X64 mode

Post by ABBKlaus »

i´m having problems getting floats and doubles back from these TailBiten routines :

Code: Select all

ProcedureDLL.b Test_Byte()
  ProcedureReturn 123
EndProcedure

ProcedureDLL.w Test_Word()
  ProcedureReturn 600
EndProcedure

ProcedureDLL.l Test_Long()
  ProcedureReturn 600
EndProcedure

ProcedureDLL.f Test_Float()
  ProcedureReturn 600
EndProcedure

ProcedureDLL.d Test_Double()
  ProcedureReturn 600
EndProcedure

ProcedureDLL.q Test_Quad()
  ProcedureReturn 600
EndProcedure

ProcedureDLL.s Test_String()
  ProcedureReturn "TEST"
EndProcedure

ProcedureDLL.i Test_Integer()
  ProcedureReturn 600
EndProcedure

Code: Select all

Debug Test_Byte() ; 123
Debug Test_Word() ; 600
Debug Test_Long() ; 600
Debug Test_Float() ; 0.0 <- wrong
Debug Test_Double() ; 0.0 <- wrong
Debug Test_Quad() ; 600
Debug Test_String() ; TEST
Debug Test_Integer() ; 600
There are no problems when its compiled as shared dll.

Affected Versions : PureBasic4.30X64 (X86 runs fine !)

Here is the compiled lib including asm sources : http://www.tailbite.com/downloads/float ... .30X64.zip

I already PM´d Fred and he answered this :
IMHO, it's a bug in the pbcompiler when using ProcedureDLL, as it still returns the result in ST0 instead of XMM0. I will take a look.
Last edited by ABBKlaus on Fri Jun 19, 2009 8:15 am, edited 1 time in total.
lexvictory
Addict
Addict
Posts: 1027
Joined: Sun May 15, 2005 5:15 am
Location: Australia
Contact:

Post by lexvictory »

After quite a bit of googling, I think that TailBite can fix this. (just need to figure out the string matching)

for the float, the "FLD dword " instruction needs to be changed to "MOVSD xmm0,qword" (the qword works for 600, I've not tested with a decimal place)
for the double, the "FLD qword " needs to be changed to "MOVSD xmm0,qword"

fixing it manually in the ASM works :)
Demonio Ardente

Currently managing Linux & OS X Tailbite
OS X TailBite now up to date with Windows!
ABBKlaus
Addict
Addict
Posts: 1143
Joined: Sat Apr 10, 2004 1:20 pm
Location: Germany

Post by ABBKlaus »

great news :D
i will try to integrate this ASAP.
lexvictory
Addict
Addict
Posts: 1027
Joined: Sun May 15, 2005 5:15 am
Location: Australia
Contact:

Post by lexvictory »

ok, fixed it.

However, Floats seem to lose some accuracy...
changing the float to return 600.600, this happens:

Code: Select all

Debug Test_Float();600.5999755859375
Debug 600.600;600.60000000000002
I know they are never exact... but this does not seem right...
Demonio Ardente

Currently managing Linux & OS X Tailbite
OS X TailBite now up to date with Windows!
jack
Addict
Addict
Posts: 1336
Joined: Fri Apr 25, 2003 11:10 pm

Post by jack »

if the first number printed is a float then it's OK, as you know a float is only accurate to about 6 digits.
lexvictory
Addict
Addict
Posts: 1027
Joined: Sun May 15, 2005 5:15 am
Location: Australia
Contact:

Post by lexvictory »

jack wrote:as you know
Personally I dont :lol:
My programming class at Uni hasn't gone into that much detail - plus java uses double by default (and I'm not doing Computer Science)

But thanks for that info - it just seems strange that the debug is accurate but the function return isn't (presumably because I'm fooling the ASM into thinking it's putting a qword into xmm0 when it's really a dword...)
Demonio Ardente

Currently managing Linux & OS X Tailbite
OS X TailBite now up to date with Windows!
ABBKlaus
Addict
Addict
Posts: 1143
Joined: Sat Apr 10, 2004 1:20 pm
Location: Germany

Post by ABBKlaus »

i just tested the new feature and it didn´t work well :

Tailbiten function pdf_GetStringWidth(String$)

Code: Select all

format MS64 COFF

Public PB_pdf_GetStringWidth


Extrn SYS_FastAllocateString4
Extrn PurePDF_ipf_GetStringWidth
Extrn SYS_FreeString


section '.text' code readable executable

PB_pdf_GetStringWidth:
MOV    qword [rsp+8],rcx
PS134=64
XOR    rax,rax
PUSH   rax
PUSH   rax
SUB    rsp,40
MOV    rdx,[rsp+PS134+0]
LEA    rcx,[rsp+40]
SUB    rsp,16
CALL   SYS_FastAllocateString4
ADD    rsp,16
; Protected res.f
;
; res = ipf_GetStringWidth(String$)
ADD    rsp,-8
PUSH   qword [rsp+48]
POP    rcx
ADD    rsp,-8
CALL  PurePDF_ipf_GetStringWidth
ADD    rsp,16
FSTP   dword [rsp+48]
; ProcedureReturn res
MOVSD xmm0,qword [rsp+48]
MOVSXD rax,eax
JMP   _EndProcedure135
; EndProcedure
FLDZ
_EndProcedure135:
PUSH   rax
MOV    rcx,qword [rsp+48]
SUB    rsp,32
CALL   SYS_FreeString
ADD    rsp,32
POP    rax
ADD    rsp,56
RET
pdf_GetStringWidth(String$) from PurePDF.pb (modified to work with TB!)

Code: Select all

ProcedureDLL.f pdf_GetStringWidth(String$) ;Get width of a string in the current font.
  Protected res.f
  
  res = ipf_GetStringWidth(String$)
  ;ProcedureReturn ipf_GetStringWidth(String$) ; <- TB won´t detect this
  ProcedureReturn res
EndProcedure
Results from Example Tutorial03 StringWidth.pb :

Code: Select all

X64:
-9223372036854775808
-9223372036854775808
-9223372036854775808
-9223372036854775808
X86:
84
84
84
84

Code: Select all

;The pdf_GetStringWidth() method allows to determine the length of a string in the current font, 
;which is used here to calculate the position and the width of the frame surrounding the title. 
;Then colors are set (via pdf_SetDrawColor(), pdf_SetFillColor() and pdf_SetTextColor()) and the 
;thickness of the line is set to 1 mm (against 0.2 by default) with pdf_SetLineWidth(). Finally, 
;we output the cell (the last parameter to 1 indicates that the background must be filled). 

;The method used to print the paragraphs is pdf_MultiCell(). Each time a line reaches the right 
;extremity of the cell or a carriage-return character is met, a line break is issued and a new cell 
;automatically created under the current one. Text is justified by default. 

;Two document properties are defined: title (pdf_SetTitle()) and author (pdf_SetAuthor()). 
;Properties can be viewed by two means. First is open the document directly with Acrobat Reader, 
;go to the File menu, Document info, General. Second, also available from the plug-in, is click on 
;the triangle just above the right scrollbar and choose Document info. 

Global title.s
title="20000 Leagues Under the Seas"

Procedure Header()
  pdf_SetFont("Arial","B",15)
  w = pdf_GetStringWidth(title)+6
  Debug w
  pdf_SetX((210 - w)/2)
  pdf_SetDrawColor(0,80,180)
  pdf_SetFillColor(230,230,0)
  pdf_SetTextColor(220,50,50)
  pdf_SetLineWidth(1)
  pdf_Cell(w,9,title,1,1,#PDF_ALIGN_CENTER,1)
  pdf_Ln(10)
EndProcedure

Procedure footer()
  pdf_SetY(-15)
  pdf_SetFont("Arial","I",8)
  pdf_SetTextColor(128)
  txt.s = "Page " + Str(pdf_GetPageNo())
  pdf_Cell(0,10,txt,0,0,#PDF_ALIGN_CENTER)
EndProcedure

Procedure ChapterTitle(num, label.s)
  pdf_SetFont("Arial", "",12)
  pdf_SetFillColor(200,220,255)
  pdf_Cell(0,6,"Chapter " + Str(num) + " : " + label,0,1,#PDF_ALIGN_LEFT,1)
  pdf_Ln(4)
EndProcedure

Procedure ChapterBody(file.s)
  txt.s = ""
  FileID=OpenFile(#PB_Any,file)
  If FileID
    l = Lof(FileID)
    If l
      *MemoryBuffer = AllocateMemory(l+2) 
      If *MemoryBuffer
        l = ReadData(FileID,*MemoryBuffer,l)
        txt = PeekS(*MemoryBuffer,l,#PB_Ascii) 
        FreeMemory(*MemoryBuffer)
      EndIf
    EndIf
    CloseFile(FileID)
  EndIf
  
  If txt
    pdf_SetFont("Times","",12)
    
    txt=pdf_MultiCell(0,5,txt)
    pdf_Cell(0,5,txt)
    pdf_Ln()
    pdf_SetFont("","I")
    pdf_Cell(0,5,"(end of excerpt)")
  EndIf
EndProcedure

Procedure PrintChapter(num,atitle.s,file.s)
  pdf_AddPage()
  ChapterTitle(num,atitle)
  ChapterBody(file)
EndProcedure

pdf_Create()
pdf_SetProcFooter(@Footer())
pdf_SetProcHeader(@Header())
pdf_SetTitle(title)
pdf_SetAuthor("Jules Verne")

PrintChapter(1,"A RUNAWAY REEF","20k_c1.txt");
PrintChapter(2,"THE PROS And CONS","20k_c2.txt");

pdf_Save("Tutorial03 StringWidth.pdf")
lexvictory
Addict
Addict
Posts: 1027
Joined: Sun May 15, 2005 5:15 am
Location: Australia
Contact:

Post by lexvictory »

ok, I'll have a look.

I know its not what you want, but does it work with changing the return type to a double?
Demonio Ardente

Currently managing Linux & OS X Tailbite
OS X TailBite now up to date with Windows!
lexvictory
Addict
Addict
Posts: 1027
Joined: Sun May 15, 2005 5:15 am
Location: Australia
Contact:

Post by lexvictory »

I've tried and tried, but to no avail. We need an asm guru if we're to fix it.

I think it's safe to say that only doubles (please don't tell me they don't work either :lol:) will work properly in x64 with PB 4.30.
Hopefully in PB 4.40 the compiler will return floats/doubles in xmm0
Demonio Ardente

Currently managing Linux & OS X Tailbite
OS X TailBite now up to date with Windows!
ABBKlaus
Addict
Addict
Posts: 1143
Joined: Sat Apr 10, 2004 1:20 pm
Location: Germany

Post by ABBKlaus »

no changing the return type to double does not work either :(
i get the same results as mentioned above.

Code: Select all

  Protected w.d
  pdf_SetFont("Arial","B",15)
  w = pdf_GetStringWidth(title)
  Debug w
if the variable w is defined as double i get -1.#IND
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

Can you cheat by converting all return doubles to quads and then use something similar to PeekD(@Result.q)? The same could be done for floats as well.
lexvictory
Addict
Addict
Posts: 1027
Joined: Sun May 15, 2005 5:15 am
Location: Australia
Contact:

Post by lexvictory »

modifying the ASM to return the double in rax, and adding !mov [p.v_w], qword rax in the tutorial 3 (and a similar one in pdf_GetStringWidth());
I get this:

Code: Select all

77.644622667789463
77.644622667789463
77.644622667789463
77.644622667789463
This is not really a good solution for a big userlib though...
Demonio Ardente

Currently managing Linux & OS X Tailbite
OS X TailBite now up to date with Windows!
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

lexvictory wrote:This is not really a good solution for a big userlib though...
Can you be more specific? Is it not working? I've had no problems passing floats as integers in PureBasic 32-bit and using PeekF(@Result) to read it back.
lexvictory
Addict
Addict
Posts: 1027
Joined: Sun May 15, 2005 5:15 am
Location: Australia
Contact:

Post by lexvictory »

Userlib mod:

Code: Select all

ProcedureDLL.d pdf_GetStringWidth(String$) ;Get width of a string in the current font.
  Protected res.d
 
  res = ipf_GetStringWidth(String$)
  !mov [p.v_res], qword rax;<--this has to be added after every function that returns a double
  ;ProcedureReturn ipf_GetStringWidth(String$) ; <- TB won´t detect this

  ProcedureReturn res 
EndProcedure
program mod:

Code: Select all

Procedure Header()
  pdf_SetFont("Arial","B",15)
  w.d = pdf_GetStringWidth(title);+6
  !mov [p.v_w], qword rax;<-- here
  Debug w
  pdf_SetX((210 - w)/2)
  pdf_SetDrawColor(0,80,180)
  pdf_SetFillColor(230,230,0)
  pdf_SetTextColor(220,50,50)
  pdf_SetLineWidth(1)
  pdf_Cell(w,9,title,1,1,#PDF_ALIGN_CENTER,1)
  pdf_Ln(10)
EndProcedure
Demonio Ardente

Currently managing Linux & OS X Tailbite
OS X TailBite now up to date with Windows!
lexvictory
Addict
Addict
Posts: 1027
Joined: Sun May 15, 2005 5:15 am
Location: Australia
Contact:

Post by lexvictory »

Well, I don't quite know whether to believe it or not, but I've completely fixed this.
Please test it. (probably best to test that the fix doesn't kick in on x86 too - I haven't tested that)

You can now do

Code: Select all

ProcedureReturn ipf_GetStringWidth(String$)
And you won't notice the difference.
On my tests, I get 84 for the sample 3 Debug

The main trouble with this was that it's only DLL functions that have to be fixed.
After a call to a Procedure with a double/float return, PB pops the value out. However when calling userlib functions (DLL funcs) from programs, it obeys the calling convention and looks in xmm0 for the float/double.

On a side note: should Adobe Acrobat be asking me to safe the pdf when I close it? (I have the full (professional) version)
It doesn't say there's anything wrong with it (like it did when I was experimenting with the fix), but it still asks to save...
Demonio Ardente

Currently managing Linux & OS X Tailbite
OS X TailBite now up to date with Windows!
Post Reply