Gas64 (no more use of gcc, only gas) :-)

User projects written in or related to FreeBASIC.
SARG
Posts: 903
Joined: May 27, 2005 7:15
Location: FRANCE

Gas64 (no more use of gcc, only gas) :-)

Postby SARG » Mar 05, 2019 0:05

Hi all,

Since about 5 months I'm coding a 64bit gas version, no more use of gcc only gas.exe.
It's well advanced however still a bit of work, mostly tests.

For now it's only for Windows but our Linux's friends are not forgotten and I hope be able to extend this option for them.
The changes are handled in few procs so a relatively easy adaptation.

The current version can compile all the FBC modules without error. However just compiled, it doesn't mean that the execution will not be wrong....
And my test programs run fine.

http://users.freebasic-portal.de/sarg/fbcgas64.zip

Next steps :
- cleaning the code and adding more optimizations I thought about. For example the order of used registers.
- FBC self compilation and tests
- compiling every code of test suite to find missing cases. If someone is enough kind to do that and give me the report
- executing the obtained executables

I need some help in testing so try it and report every issue you meet by posting or sending the faulty code.
A second way could be to look at the generated code and suggest modifications.
However the generated asm is function of the flow of op codes so it's not possible to change everything as we want.

''--------------
Some precisions
''--------------
- The exe speed should be at least as good if not better that the gcc version (without the Ox options) could provide.
- To start the project I used the ir-llvm module (llvm is very close to assembly) and when necessary I look at the asm generated with gcc.
- One of trick is to reset the used registers for each basic line. So very big/complex lines could generate errors.
That also forces to use the -g option (for the moment).
- The asm file extension is .a64 (output from fbc and sent to the assembler) to distinguish from the current asm files.
- An a64 file contains a lot of information to easily debug the generated code (see example below). So these files can be very huge. Obviously that
will be removed in the future.
- There are few changes in the fbc modules mostly the add of a new module ir-gas64.bas.
* ast-node-proc : loadres for GAS64 (seems also missing for llvm)
* fb.bi : added FB_BACKEND_GAS64
* fbc : allowing GAS64 / only one stage / file name .a64
* ir.bi : extern vtbl
* ir : irgas64_vtbl
* parser-toplevel : commented lines to get the text code for all modules (include files)
* symb-mangling : added GAS64

''------------
''How use it
''------------
As usual with the new option -gen gas64 and adding -g is mandatory

*** compilation via 32 *** KEEP -g
fbc32_gas64 -arch 64 -RR -R -gen gas64 -v -g test_asm64.bas

*** compilation via 64 *** KEEP -g
fbc64_gas64 -RR -R -gen gas64 -v -g test_asm64.bas


''-----------------------------------------
'' Benchmark using example posted by Marpon
''-----------------------------------------
- gcc = 48.31
- gccO2/O3 = 43.86
- gas64 = 10.56 (64bit integer) <---- not so bad
- gas32 = 8.78 (32bit integer)
- gccft = 3.73


''----------------------------
''Example (partial) of a64 file
''----------------------------

Code: Select all

   # Info --> registers released
   # -----------------------------------------
   # basic --> If pold=pslh Then pold=999999
   # -----------------------------------------
   # Info --> CONVERTING vr188 [integer] := POLD+-152 [long]
   # Info --> vregdump v1=reg 188 [integer] xx 188
   # Info --> vregdump v2=var POLD ofs=-152 [long] symbdump=var local accessed declared POLD [long] xx -1
   # Info --> virtual register =188 real register=r11
   # Info --> size dst > size src  changing src dtype by dst dtype
   # Info --> marked as used register=r11
   movsxd r11, DWORD PTR -152[rbp]
   # Info --> CONVERTING vr189 [integer] := PSLH+-148 [long]
   # Info --> vregdump v1=reg 189 [integer] xx 189
   # Info --> vregdump v2=var PSLH ofs=-148 [long] symbdump=var local accessed declared PSLH [long] xx -1
   # Info --> virtual register =189 real register=r10
   # Info --> size dst > size src  changing src dtype by dst dtype
   # Info --> marked as used register=r10
   movsxd r10, DWORD PTR -148[rbp]
   # Info --> branchbop vr188 [integer] <> vr189 [integer] .Lt_0032
   # Info --> v1=reg 188 [integer]
   # Info --> v2=reg 189 [integer]
   # Info --> Vr=0 op =>icmp ne
   # Info --> virtual register =188 real register=r11
   # Info --> virtual register =189 real register=r10
   # Info --> Release done for register=r10
   # Info --> Release done for register=r11
   cmp r11, r10
   jne .Lt_0032
   # Info --> store POLD+-152 [long] := 999999 [long]
   # Info --> v1=var POLD ofs=-152 [long] symbdump=var local accessed declared POLD [long]
   # Info --> v2=imm 999999 [long]
   mov DWORD PTR -152[rbp], 999999
   .Lt_0032: #label not mangled=.Lt_0032


''----------------------------------
''2 Examples of optimization
''----------------------------------
1/ #O5lea r11, -136[rbp]
#O5mov r10, r11
lea r10, -136[rbp] #Optim 5

2/ mov r11, rax
#O1 mov rax, r11
jepalza
Posts: 25
Joined: Feb 24, 2010 10:08
Location: Spain (Bilbao)

Re: Gas64 (no more use of gcc, only gas) :-)

Postby jepalza » Mar 05, 2019 6:11

With complicated porjects, like mine, with several big modules, can't compile it.

Look:

Code: Select all

assembling:   C:\Aplis\FreeBasic\bin\win64\as.exe --64 "_80486_emu.a64" -o "_80486_emu.o"
_80486_emu.a64: Assembler messages:
_80486_emu.a64:389: Error: invalid use of register
_80486_emu.a64:62160: Error: unsupported instruction `mov'
_80486_emu.a64:62187: Error: no such instruction: `found AN ERROR:virtual register=-1 no real register corresponding,using KREG_XXX'
_80486_emu.a64:62190: Error: bad expression
_80486_emu.a64:62190: Error: bad expression
_80486_emu.a64:62190: Error: junk `r11+* X_Q]' after expression
_80486_emu.a64:62430: Error: no such instruction: `found AN ERROR:virtual register=-1 no real register corresponding,using KREG_XXX'
_80486_emu.a64:62433: Error: bad expression
_80486_emu.a64:62433: Error: bad expression
_80486_emu.a64:62433: Error: junk `r11+* X_Q]' after expression
_80486_emu.a64:62718: Error: invalid use of register
_80486_emu.a64:62823: Error: invalid use of register

..... several more

_80486_emu.a64:71218: Error: invalid use of register
_80486_emu.a64:72087: Error: invalid use of register
_80486_emu.a64:73322: Error: operand size mismatch for `movzx'
_80486_emu.a64:74121: Error: operand size mismatch for `movzx'
_80486_emu.a64:82465: Error: no such instruction: `found AN ERROR:no free reg use RAX'
_80486_emu.a64:82477: Error: no such instruction: `found AN ERROR:no free reg use RAX'
_80486_emu.a64:82491: Error: no such instruction: `found AN ERROR:no free reg use RAX'
_80486_emu.a64:82501: Error: no such instruction: `found AN ERROR:Warning rax used before a function call,should not happen 38'
_80486_emu.a64:82560: Error: no such instruction: `found AN ERROR:no free reg use RAX'
_80486_emu.a64:91849: Error: invalid use of register
_80486_emu.a64:91919: Error: invalid use of register
_80486_emu.a64:91989: Error: invalid use of register
_80486_emu.a64:121190: Error: operand size mismatch for `movzx'
_80486_emu.a64:125431: Error: operand size mismatch for `movzx'

... several more

_80486_emu.a64:144859: Error: missing right bracket
_80486_emu.a64:144859: Error: junk `X_Q]' after expression
_80486_emu.a64:144876: Error: no such instruction: `found AN ERROR:virtual register=-1 no real register corresponding,using KREG_XXX'
_80486_emu.a64:144880: Error: bad expression
_80486_emu.a64:144880: Error: missing right bracket
_80486_emu.a64:144880: Error: junk `X_Q]' after expression
_80486_emu.a64:145921: Error: invalid use of register
_80486_emu.a64:146884: Error: invalid use of register
_80486_emu.a64:147074: Error: operand size mismatch for `movzx'
_80486_emu.a64:149631: Error: no such instruction: `found AN ERROR:virtual register=-1 no real register corresponding,using KREG_XXX'
_80486_emu.a64:149635: Error: bad expression
_80486_emu.a64:149635: Error: missing right bracket
_80486_emu.a64:149635: Error: junk `X_Q]' after expression
_80486_emu.a64:150344: Error: operand size mismatch for `movzx'
_80486_emu.a64:150882: Error: operand size mismatch for `movzx'
_80486_emu.a64:151170: Error: invalid use of register
_80486_emu.a64:151175: Error: invalid use of register
_80486_emu.a64:151292: Error: invalid use of register
_80486_emu.a64:151297: Error: invalid use of register
_80486_emu.a64:151728: Error: unsupported instruction `mov'

.... several more

_80486_emu.a64:342027: Error: operand size mismatch for `movzx'
_80486_emu.a64:343067: Error: invalid use of register
_80486_emu.a64:345035: Error: operand size mismatch for `movzx'
_80486_emu.a64:345105: Error: operand size mismatch for `movsx'
_80486_emu.a64:345804: Error: operand size mismatch for `movzx'
_80486_emu.a64:347466: Error: operand size mismatch for `movzx'
_80486_emu.a64:348185: Error: operand size mismatch for `movzx'
_80486_emu.a64:355615: Error: operand size mismatch for `movzx'
_80486_emu.a64:356462: Error: operand size mismatch for `movzx'
assembling failed: 'C:\Aplis\FreeBasic\bin\win64\as.exe' terminated with exit code 1

build error(s)
*** terminated ***
jepalza
Posts: 25
Joined: Feb 24, 2010 10:08
Location: Spain (Bilbao)

Re: Gas64 (no more use of gcc, only gas) :-)

Postby jepalza » Mar 05, 2019 6:12

but I've done the test with a simple module, which draws millions of pixels on the screen, and the speed gains almost double !!!
srvaldez
Posts: 2019
Joined: Sep 25, 2005 21:54

Re: Gas64 (no more use of gcc, only gas) :-)

Postby srvaldez » Mar 05, 2019 10:34

hello SARG :-)
this is exciting news, will test asap.
thank you for the initiative.
Last edited by srvaldez on Mar 05, 2019 14:21, edited 1 time in total.
SARG
Posts: 903
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Gas64 (no more use of gcc, only gas) :-)

Postby SARG » Mar 05, 2019 14:04

Thank you for posting.

jepalza wrote:With complicated porjects, like mine, with several big modules, can't compile it.
It's still WIP. As I wrote complex lines may use more registers than available, in this case split them if possible.
Could you send me an example, at least small parts of the a64 file. Also don't forget the -g option as it's very important even when not debugging.
Nota when compiling if an error occurs an asm error is also forced for easily seeing it.


jepalza wrote:but I've done the test with a simple module, which draws millions of pixels on the screen, and the speed gains almost double !!!
Good news :-)

srvaldez wrote:hello SARG :-)
this is exiting news, will test asap.
thank you for the initiative.
I guess exCiting not exiting ;-)
I look forward to the test results.
srvaldez
Posts: 2019
Joined: Sep 25, 2005 21:54

Re: Gas64 (no more use of gcc, only gas) :-)

Postby srvaldez » Mar 05, 2019 16:20

@SARG
I have many examples that don't compile, here's one however that compiles ok but gives the wrong result
nbody.bas

Code: Select all

'https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/nbody-gcc-1.html
' The Computer Language Benchmarks Game
' https://benchmarksgame-team.pages.debian.net/benchmarksgame/

' contributed by Christoph Bauer
'
' https://benchmarksgame-team.pages.debian.net/benchmarksgame/license.html

' translated to FreeBasic by srvaldez

dim as ushort oldcw, cwdouble=&h27F, cwsingle=&h7F

asm
  fstcw word ptr [oldcw]
  fldcw word ptr [cwdouble] 'set FPU precision to double
end asm
   
Declare Function main(Byval argc As Long) As Long

   Dim As Double t=Timer
   main(50000000)
   Print "elapsed time ";timer-t;" seconds"
End


Const pi = 3.141592653589793
Const solar_mass = (4 * pi) * pi
Const days_per_year = 365.24

Type planet
   x As Double
   y As Double
   z As Double
   vx As Double
   vy As Double
   vz As Double
   mass As Double
End Type

Private Sub advance(Byval nbodies As Long, bodies() As planet, Byval dt As Double)
   Dim i As Long
   Dim j As Long
   For i = 0To nbodies-1
      Dim b As planet Ptr = @bodies(i)
      For j = i + 1 To nbodies-1
         Dim b2 As planet Ptr = @bodies(j)
         Dim dx As Double = b->x - b2->x
         Dim dy As Double = b->y - b2->y
         Dim dz As Double = b->z - b2->z
         Dim distance As Double = Sqr(((dx * dx) + (dy * dy)) + (dz * dz))
         Dim mag As Double = dt / ((distance * distance) * distance)
         b->vx -= (dx * b2->mass) * mag
         b->vy -= (dy * b2->mass) * mag
         b->vz -= (dz * b2->mass) * mag
         b2->vx += (dx * b->mass) * mag
         b2->vy += (dy * b->mass) * mag
         b2->vz += (dz * b->mass) * mag
      Next
   Next
   For i = 0 To nbodies-1
      Dim b As planet Ptr = @bodies(i)
      b->x += dt * b->vx
      b->y += dt * b->vy
      b->z += dt * b->vz
   Next
End Sub

Private Function energy(Byval nbodies As Long, bodies() As planet) As Double
   Dim e As Double
   Dim i As Long
   Dim j As Long
   e = 0.0
   For i = 0 To nbodies-1
      Dim b As planet Ptr = @bodies(i)
      e += (0.5 * b->mass) * (((b->vx * b->vx) + (b->vy * b->vy)) + (b->vz * b->vz))
      For j = i + 1 To nbodies-1
         Dim b2 As planet Ptr = @bodies(j)
         Dim dx As Double = b->x - b2->x
         Dim dy As Double = b->y - b2->y
         Dim dz As Double = b->z - b2->z
         Dim distance As Double = Sqr(((dx * dx) + (dy * dy)) + (dz * dz))
         e -= (b->mass * b2->mass) / distance
      Next
   Next
   Return e
End Function

Private Sub offset_momentum(Byval nbodies As Long, bodies() As planet)
   Dim px As Double = 0.0
   Dim py As Double = 0.0
   Dim pz As Double = 0.0
   Dim i As Long
   For i = 0 To nbodies-1
      px += bodies(i).vx * bodies(i).mass
      py += bodies(i).vy * bodies(i).mass
      pz += bodies(i).vz * bodies(i).mass
   Next
   bodies(0).vx = (-px) / ((4 * 3.141592653589793) * 3.141592653589793)
   bodies(0).vy = (-py) / ((4 * 3.141592653589793) * 3.141592653589793)
   bodies(0).vz = (-pz) / ((4 * 3.141592653589793) * 3.141592653589793)
End Sub

Const NBODIES = 5
Extern     bodies(0 To 4) As planet
Dim Shared bodies(0 To 4) As planet = {(0, 0, 0, 0, 0, 0,_
                                      (4 * 3.141592653589793) * 3.141592653589793),_
                                      (4.84143144246472090e+00, -1.16032004402742839e+00,_
                                      -1.03622044471123109e-01, 1.66007664274403694e-03 * _
                                      365.24, 7.69901118419740425e-03 * 365.24, _
                                      (-6.90460016972063023e-05) * 365.24, _
                                      9.54791938424326609e-04 * ((4 * 3.141592653589793) * _
                                      3.141592653589793)), (8.34336671824457987e+00, _
                                      4.12479856412430479e+00, -4.03523417114321381e-01, _
                                      (-2.76742510726862411e-03) * 365.24, _
                                      4.99852801234917238e-03 * 365.24, _
                                      2.30417297573763929e-05 * 365.24, _
                                      2.85885980666130812e-04 * ((4 * 3.141592653589793) * _
                                      3.141592653589793)), (1.28943695621391310e+01, _
                                      -1.51111514016986312e+01, -2.23307578892655734e-01, _
                                      2.96460137564761618e-03 * 365.24, _
                                      2.37847173959480950e-03 * 365.24, _
                                      (-2.96589568540237556e-05) * 365.24, _
                                      4.36624404335156298e-05 * ((4 * 3.141592653589793) * _
                                      3.141592653589793)), (1.53796971148509165e+01, _
                                      -2.59193146099879641e+01, 1.79258772950371181e-01, _
                                      2.68067772490389322e-03 * 365.24, _
                                      1.62824170038242295e-03 * 365.24, _
                                      (-9.51592254519715870e-05) * 365.24, _
                                      5.15138902046611451e-05 * ((4 * 3.141592653589793) * _
                                      3.141592653589793))}

Private Function main(Byval argc As Long) As Long
   Dim n As Long = argc
   Dim i As Long
   offset_momentum(5, bodies())
   Print Using "##.#########"; energy(NBODIES, bodies())
   For i = 1 To n
      advance(NBODIES, bodies(), 0.01)
   Next
   Print Using "##.#########"; energy(NBODIES, bodies())
   Return 0
End Function

main(50000000)
asm
  fldcw word ptr [oldcw] 'restore control word
end asm

result

Code: Select all

-0.169289903
-0.169289903
elapsed time  77.10315989999981 seconds

if compiled with -gen gcc without optimization, the result is

Code: Select all

-0.169075164
-0.169059907
elapsed time  25.9693898999999 seconds

see https://benchmarksgame-team.pages.debia ... gcc-1.html
srvaldez
Posts: 2019
Joined: Sep 25, 2005 21:54

Re: Gas64 (no more use of gcc, only gas) :-)

Postby srvaldez » Mar 05, 2019 17:56

hello SARG
this program ioldouble.bas fails to compile, compiler gives the following output

Code: Select all

C:\dev\FreeBASIC-1.06.0-win64\fbc64_gas64 -RR -R -gen gas64 -g -v "ioldouble.bas" (in directory: F:\FreeBASIC Programs)
FreeBASIC Compiler - Version 1.06.0 (03-05-2019), built for win64 (64bit)
Copyright (C) 2004-2019 The FreeBASIC development team.
standalone
target:       win64, x86-64, 64bit
compiling:    ioldouble.bas -o ioldouble.a64 (main module)
assembling:   C:\dev\FreeBASIC-1.06.0-win64\bin\win64\as.exe --64 "ioldouble.a64" -o "ioldouble.o"
linking:      C:\dev\FreeBASIC-1.06.0-win64\bin\win64\ld.exe -m i386pep -o "ioldouble.exe" -subsystem console "C:\dev\FreeBASIC-1.06.0-win64\lib\win64\fbextra.x" --stack 1048576,1048576 -L "C:\dev\FreeBASIC-1.06.0-win64\lib\win64" -L "." "C:\dev\FreeBASIC-1.06.0-win64\lib\win64\crt2.o" "C:\dev\FreeBASIC-1.06.0-win64\lib\win64\crtbegin.o" "C:\dev\FreeBASIC-1.06.0-win64\lib\win64\fbrt0.o" "ioldouble.o" "-(" -lfb -lgcc -lmsvcrt -lkernel32 -luser32 -lmingw32 -lmingwex -lmoldname -lgcc_eh "-)" "C:\dev\FreeBASIC-1.06.0-win64\lib\win64\crtend.o"
ioldouble.o:ioldouble.bas:(.text+0xce): undefined reference to `.Lt_0035'
ioldouble.o:ioldouble.bas:(.text+0xfc): undefined reference to `.Lt_0035'
ioldouble.o:ioldouble.bas:(.text+0x48b): undefined reference to `.Lt_00BE'
ioldouble.o:ioldouble.bas:(.text+0x1ac8): undefined reference to `.Lt_037E'
ioldouble.o:ioldouble.bas:(.text+0x1c61): undefined reference to `.Lt_03C0'
ioldouble.o:ioldouble.bas:(.text+0x1c9d): undefined reference to `.Lt_03C0'
ioldouble.o:ioldouble.bas:(.text+0x1d8f): undefined reference to `.Lt_03C0'
ioldouble.o:ioldouble.bas:(.text+0x1da4): undefined reference to `.Lt_03C0'
ioldouble.o:ioldouble.bas:(.text+0x1e87): undefined reference to `.Lt_03C0'
linking failed: 'C:\dev\FreeBASIC-1.06.0-win64\bin\win64\ld.exe' terminated with exit code 1
Compilation failed.
jepalza
Posts: 25
Joined: Feb 24, 2010 10:08
Location: Spain (Bilbao)

Re: Gas64 (no more use of gcc, only gas) :-)

Postby jepalza » Mar 06, 2019 5:32

SARG wrote:Could you send me an example, at least small parts of the a64 file.


Sorry, i'm using "google translate" to write most of my text (don't speak english or write it), and forget paste link of my complex project:
viewtopic.php?f=8&t=27435

It has a lot of code.
frisian
Posts: 249
Joined: Oct 08, 2009 17:25

Re: Gas64 (no more use of gcc, only gas) :-)

Postby frisian » Mar 06, 2019 9:48

@SARG
I was very excited to see your effort to produce gas64 code, that I tried many programs but forgot to take notes.
I hope to make up for it in the next few days.
I have tested your fbc64_gas64.exe on small programs (most Rosetta Code stuff)
I have a few programs that compiled and run correctly, most programs will compile but produce no output.
A few even crashed. A few programs would not compile.
One program produced the wrong output, but I found a way around it.
Safe primes.bas [Rosetta Code]

Code: Select all

Const As UInteger max = 10000000
Dim As UInteger i, j, sc1, usc1, sc2, usc2
Dim As String safeprimes, unsafeprimes
Dim As UByte sieve()

ReDim sieve(max)
' 0 = prime, 1 = no prime
sieve(0) = 1 : sieve(1) = 1
'i = 0 : sieve(i) = 1 : i = 1 : sieve(i) = 1

print "=========================================="
for i = 0 to 1
    print "sieve("; i; ") = "; sieve(i); ", should be 1"
next
print "=========================================="
print : print

For i = 4 To max Step 2
    sieve(i) = 1
Next
For i = 3 To Sqr(max) +1 Step 2
    If sieve(i) = 0 Then
        For j = i * i To max Step i * 2
            sieve(j) = 1
        Next
    End If
Next

usc1 = 1 : unsafeprimes = "2"
For i = 3 To 3001 Step 2
    If sieve(i) = 0 Then
        If sieve(i \ 2) = 0 Then
            sc1 += 1
            If sc1 <= 35 Then
                safeprimes += " " + Str(i)
            End If
        Else
            usc1 += 1
            If usc1 <= 40 Then
                unsafeprimes +=  " " + Str(i)
            End If
        End If
    End If
Next

For i = 3003 To max \ 10 Step 2
    If sieve(i) = 0 Then
        If sieve(i \ 2) = 0 Then
            sc1 += 1
        Else
            usc1 += 1
        End If
    End If
Next

sc2 = sc1 : usc2 = usc1
For i = max \ 10 +1 To max Step 2
    If sieve(i) = 0 Then
        If sieve(i \ 2) = 0  Then
            sc2 += 1
        Else
            usc2 += 1
        End If
    End If
Next

Print "the first 35 Safeprimes are: "; safeprimes
Print
Print "the first 40 Unsafeprimes are:  "; unsafeprimes
Print
Print "                  Safeprimes     Unsafeprimes"
Print "    Below         ---------------------------"
Print Using "##########,      ";  max \ 10; sc1; usc1
Print Using "##########,      ";  max     ; sc2; usc2

' empty keyboard buffer
While Inkey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End

Gives wrong answer.

Code: Select all

==========================================
sieve(0) = 0, should be 1
sieve(1) = 0, should be 1
==========================================

the first 35 Safeprimes are:  3 5 7 11 23 47 59 83 107 167 179 227 263 347 359 383 467 479 503 563 587 719 839 863 887 983 1019 1187 1283 1307 1319 1367 1439 1487 1523

the first 40 Unsafeprimes are:  2 13 17 19 29 31 37 41 43 53 61 67 71 73 79 89 97 101 103 109 113 127 131 137 139 149 151 157 163 173 181 191 193 197 199 211 223 229 233 239

                  Safeprimes     Unsafeprimes
    Below         ---------------------------
  1,000,000            4,325           74,173
 10,000,000           30,658          633,921 

When the line sieve(0) = 1 : sieve(1) = 1 is changed into i = 0 : sieve(i) = 1 : i = 1 : sieve(i) = 1 the correct answer is given.

Code: Select all

==========================================
sieve(0) = 1, should be 1
sieve(1) = 1, should be 1
==========================================

the first 35 Safeprimes are:  5 7 11 23 47 59 83 107 167 179 227 263 347 359 383 467 479 503 563 587 719 839 863 887 983 1019 1187 1283 1307 1319 1367 1439 1487 1523 1619

the first 40 Unsafeprimes are:  2 3 13 17 19 29 31 37 41 43 53 61 67 71 73 79 89 97 101 103 109 113 127 131 137 139 149 151 157 163 173 181 191 193 197 199 211 223 229 233

                  Safeprimes     Unsafeprimes
    Below         ---------------------------
  1,000,000            4,324           74,174
 10,000,000           30,657          633,922

The next two programs give compiler errors.
loop index within.bas [Rosetta Code]

Code: Select all

Function isprime(number As ULongInt) As UInteger

    If number Mod 2 = 0 Then Return 0
    If number Mod 3 = 0 Then Return 0
    Dim As UInteger i, max = Sqr(number)

    For i = 5 To max Step 2
        If number Mod i = 0 Then Return 0
    Next

    Return 1

End Function

' ------=< MAIN >=------

Dim As UInteger counter
Dim As ULongInt i

Print : Print
counter = 0
For i = 42 To &HFFFFFFFFFFFFFFFF    ' for next loop, loop maximum = 2^64-1
    If isprime(i) Then
        counter += 1
        Print Using "n =### ##################,"; counter; i
        If counter >= 42 Then Exit for
        i += i -1
    End If
Next

' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End

Error log

Code: Select all

FreeBASIC Compiler - Version 1.06.0 (03-05-2019), built for win64 (64bit)
Copyright (C) 2004-2019 The FreeBASIC development team.
standalone
target:       win64, x86-64, 64bit
compiling:    loop index within.bas -o loop index within.a64 (main module)
assembling:   C:\FBC106win64\bin\win64\as.exe --64 "loop index within.a64" -o "loop index within.o"
linking:      C:\FBC106win64\bin\win64\ld.exe -m i386pep -o "loop index within.exe" -subsystem console "C:\FBC106win64\lib\win64\fbextra.x"
--stack 1048576,1048576 -L "C:\FBC106win64\lib\win64" -L "." "C:\FBC106win64\lib\win64\crt2.o" "C:\FBC106win64\lib\win64\crtbegin.o" "C:\FBC
106win64\lib\win64\fbrt0.o" "loop index within.o" "-(" -lfb -lgcc -lmsvcrt -lkernel32 -luser32 -lmingw32 -lmingwex -lmoldname -lgcc_eh "-)"
"C:\FBC106win64\lib\win64\crtend.o"
loop index within.o:loop index within.bas:(.text+0x2e): undefined reference to `.Lt_0005'
loop index within.o:loop index within.bas:(.text+0x57): undefined reference to `.Lt_0005'
loop index within.o:loop index within.bas:(.text+0x119): undefined reference to `.Lt_0005'
linking failed: 'C:\FBC106win64\bin\win64\ld.exe' terminated with exit code 1


Lagrande.bas

Code: Select all

Sub lagrange(num As ULongInt)
  ' finds one solution, sometimes the are more solution possible
  ' after the first solution found it return to caller
  ' number must be smaller then 2^64-1 (limit ULongInt)

  If num = 0 Then
    Print num;" = 0^2 + 0^2 + 0^2 + 0^2 = 0"
    Return
  EndIf

  Dim As Integer halve = num \ 2
  Dim As UInteger tmp = Sqr(num / 4)
  tmp = IIf(tmp<1, 1, tmp)

  For a As LongInt = Sqr(num) To tmp Step -1
    Dim As LongInt r1 = num - a*a
    If r1 < 0 Then Continue For
    For b As LongInt = Sqr(r1) To Sqr(r1 / 3) Step -1
      Dim As LongInt r2 = r1 - b*b
      If r2 < 0 Or r2 > halve Then Continue for
      For c As Integer = Sqr(r2) To Sqr(r2 / 2) Step -1
        Dim As Integer r3 = r2 - c*c
        Dim As Integer d = Sqr(r3)
        If d*d = r3 Then
          Dim As ULongInt sum = a*a + b*b + c*c + d*d
          Print num;" =";
          Print a;"^2 +";b;"^2 +";c;"^2 +";d;"^2 = ";sum
          If num <> sum Then
            Beep
            Print "Error "
            Sleep
            End
          EndIf
          Return
        EndIf
      Next
    Next
  Next
  Beep
  Print "sorry no solution found"  ' you should never see this
  Return
End Sub

' =========================================================================
' MAIN
' =========================================================================

Randomize Timer
Dim As Double float = Rnd

lagrange (156)

Print
Print

Dim As Integer i
For i = 0 To 10
  lagrange( 1 * 10^i )
Next

Print
Print "ready"
Sleep
End

Error log

Code: Select all

FreeBASIC Compiler - Version 1.06.0 (03-05-2019), built for win64 (64bit)
Copyright (C) 2004-2019 The FreeBASIC development team.
standalone
target:       win64, x86-64, 64bit
compiling:    lagrande.bas -o lagrande.a64 (main module)
assembling:   C:\FBC106win64\bin\win64\as.exe --64 "lagrande.a64" -o "lagrande.o"
linking:      C:\FBC106win64\bin\win64\ld.exe -m i386pep -o "lagrande.exe" -subsystem console "C:\FBC106win64\lib\win64\fbextra.x" --stack 1
048576,1048576 -L "C:\FBC106win64\lib\win64" -L "." "C:\FBC106win64\lib\win64\crt2.o" "C:\FBC106win64\lib\win64\crtbegin.o" "C:\FBC106win64\
lib\win64\fbrt0.o" "lagrande.o" "-(" -ladvapi32 -lfb -lgcc -lmsvcrt -lkernel32 -luser32 -lmingw32 -lmingwex -lmoldname -lgcc_eh "-)" "C:\FBC
106win64\lib\win64\crtend.o"
lagrande.o:lagrande.bas:(.text+0x56): undefined reference to `.Lt_0005'
lagrande.o:lagrande.bas:(.text+0x539): undefined reference to `.Lt_0005'
linking failed: 'C:\FBC106win64\bin\win64\ld.exe' terminated with exit code 1


I hope it helps.

Thanks for your fbc64_gas32/64 it's my opinion that a basic compiler should compile to assembler, not convert to C.
frisian
Posts: 249
Joined: Oct 08, 2009 17:25

Re: Gas64 (no more use of gcc, only gas) :-)

Postby frisian » Mar 06, 2019 13:32

@SARG
The following program does compile, but produces no output
Department Numbers.bas [Rosetta Code]

Code: Select all

Dim As Integer fire, police, sanitation

Print "police fire sanitation"
Print "----------------------"

For police = 2 To 7 Step 2
    For fire = 1 To 7
        If fire = police Then Continue For
        sanitation = 12 - police - fire
        If sanitation = fire Or sanitation = police Then Continue For
        If sanitation >= 1 And sanitation <= 7 Then
            Print Using "   #     #       # "; police; fire; sanitation
        End If
    Next
Next

' empty keyboard buffer
While Inkey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End


Changing the Or statement into OrElse and the And statement into AndAlso produces the correct output.

Correct output

Code: Select all

police fire sanitation
----------------------
   2     3       7
   2     4       6
   2     6       4
   2     7       3
   4     1       7
   4     2       6
   4     3       5
   4     5       3
   4     6       2
   4     7       1
   6     1       5
   6     2       4
   6     4       2
   6     5       1
dodicat
Posts: 5890
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Gas64 (no more use of gcc, only gas) :-)

Postby dodicat » Mar 06, 2019 14:37

I tested some string indexing from a multiply routine.

Code: Select all


Dim Shared As Integer _Mod(0 To 99),_Div(0 To 99)
For z As Integer=0 To 99:_Mod(z)=(z Mod 10+48):_Div(z)=z\10:Next
   
    Function Qmult(a As String,b As String) As String
        Var flag=0,la = Len(a),lb = Len(b)
        If Len(b)>Len(a) Then flag=1:Swap a,b:Swap la,lb
        Dim As Ubyte n,carry,ai
        Var c =String(la+lb,"0")
        For i As Integer =la-1 To 0 Step -1
            carry=0:ai=a[i]-48
            For j As Integer =lb-1 To 0 Step -1
                n = ai * (b[j]-48) + (c[i+j+1]-48) + carry
                carry =_Div(n):c[i+j+1]=_Mod(n)
            Next j
            c[i]+=carry
        Next i
        If flag Then Swap a,b
        Return Ltrim(c,"0")
    End Function
   
     Dim As String s1=String(10000000,"7")
    Dim As Double t
   
    For z As Long=1 To 5
        t=Timer
        dim as string g0=qmult(s1,"1234567654321")
        Print "Timings ";Timer-t,Mid(g0,1,50)+ " . . ."
        Print "__________________"
        print
    Next z
    print "done"
    Sleep
     


Compiles OK but with differing results.
64 bits fbc64_gas64.exe with switches
-arch 64 -RR -R -gen gas64 -v -g

Code: Select all

first run run with gas64
Timings  1.144299036241137  e7  (plus other characters which are omitted by the forum)

first run with fb64 v1.06
Timings  1.597983197076246  96021928669411111111111111111111111111111111111111 . . .




Please note I had to omit GoRc.exe from the 1.06 version, Avira deleted it and has blocked the folder.
SARG
Posts: 903
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Gas64 (no more use of gcc, only gas) :-)

Postby SARG » Mar 07, 2019 9:02

Frisian, dodicat thanks you for your reportings.

@frisian
The undefined reference error is fixed. Too strong optimization.....Just one line to remove. Updated exes in the zip file.
I understand why the other bugs but I need a bit of time to fix them.

@Others who posted
Not enough time to find the reasons.

I'll be without computer until next sunday so no updates before monday.
jj2007
Posts: 1210
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Gas64 (no more use of gcc, only gas) :-)

Postby jj2007 » Mar 07, 2019 11:44

Hi SARG,

I've opened a benchmarking thread here, and would be curious how Gas64 performs.

Btw the archive posted on top of this thread opens in 7zip but throws errors: "unsupported compression methods" etc
dodicat
Posts: 5890
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Gas64 (no more use of gcc, only gas) :-)

Postby dodicat » Mar 07, 2019 11:52

Hi SARG
The problem in my code was the inability to store an array of integer.
example

Code: Select all





dim as integer a(1 to 5)
for n as long=1 to 5
a(n)=21*n
next

for n as long=1 to 5
print a(n)
next


print
sleep
 


my result

Code: Select all

 452384991765
 1767128874
 6902847
 26964
 105

 

So I had to skip using lookup arrays viz;

Code: Select all


   
    Function Qmult(a As String,b As String) As String
        Var flag=0,la = Len(a),lb = Len(b)
        If Len(b)>Len(a) Then flag=1:Swap a,b:Swap la,lb
        Dim As Ubyte n,carry,ai
        Var c =String(la+lb,"0")
        For i As Integer =la-1 To 0 Step -1
            carry=0:ai=a[i]-48
            For j As Integer =lb-1 To 0 Step -1
                n = ai * (b[j]-48) + (c[i+j+1]-48) + carry
                carry=n\10:c[i+j+1]=n mod 10 +48
            Next j
            c[i]+=carry
        Next i
        If flag Then Swap a,b
        Return Ltrim(c,"0")
    End Function
   
     Dim As String s1=String(10000000,"7")
    Dim As Double t
   
    For z As Long=1 To 5
        t=Timer
        dim as string g0=qmult(s1,"1234567654321")
        Print "Timings ";Timer-t,Mid(g0,1,50)+ " . . ."
        Print "__________________"
        print
    Next z
    print "done"
    Sleep
       

Which compiles and runs OK, but a bit slower than 64 bits.
For any further testing things I shall try and debug before posting.
Thank you.
jj2007
Posts: 1210
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Gas64 (no more use of gcc, only gas) :-)

Postby jj2007 » Mar 07, 2019 12:21

Am I the only one who cannot open the archive at http://users.freebasic-portal.de/sarg/fbcgas64.zip? I've reinstalled 7zip, and now instead of "unsupported compression method" I get plenty of "header errors"...

Return to “Projects”

Who is online

Users browsing this forum: No registered users and 19 guests