Assembler - logN and many more .. lazarus / 62-General ---------------------------------------------------------------------- PeterX · 2016-07-18 20:08 Hi all, there's no sub forum for Assembler questions here .. .. which means, only a very few people are working on assembler code in FPC / LCL  ? I need some mathematical functions such as logN: ( Log.N(X) := Log.2(X) / Log.2(N) ) From which sources can I learn how to write working FPC / LCL assembler code to make my functions work ? Thanks, Peter The following code works in Delphi 5, but not in Lazarus (1.6). ----------------------------------------------------- function LogN( Base, X: Extended): Extended; {$ifdef FPC} begin {$ASMMODE intel} {$endif} asm         FLD1         FLD     X         FYL2X         FLD1         FLD     Base         FYL2X         FDIV           // Lazarus Warning: fdivrp without operand translated into fdivrpP         FWAIT end; {$ifdef FPC} end; {$endif} ---------------------------------------------------------------------- Jonas Maebe · 2016-07-19 18:02 Are you compiling that code in a unit that uses {$mode delphi}? When using Delphi code, always compile using {$mode delphi}. ---------------------------------------------------------------------- PeterX · 2016-07-19 20:27 Oh, yes, I compile with {$mode objfpc}{$H+} Does this have an influence on how the assembler code is compiled ? ---------------------------------------------------------------------- Jonas Maebe · 2016-07-19 20:30 It influences whether or need you need to use the "assembler" modifier for a pure assembly routine. It does not change how the inline assembly gets parsed. ---------------------------------------------------------------------- PeterX · 2016-07-19 20:35 Okay, because I switched back to DELPHI mode and the error messages are the same : FDIV: - Warning: fdivrp without operand translated into fdivrpP - Warning: "fdivrp" without operand translated into "fdivrp %st,%st(1)" ---------------------------------------------------------------------- Jonas Maebe · 2016-07-19 20:38 Those are not errors. They are warnings. If the resulting code has different behaviour in Delphi and FPC, please file a bug report at http://bugs.freepascal.org ---------------------------------------------------------------------- PeterX · 2016-07-19 20:39 Are You sure ? This is an old Dephi 5 project .. ---------------------------------------------------------------------- Jonas Maebe · 2016-07-19 20:40 Am I sure about what? ---------------------------------------------------------------------- PeterX · 2016-07-19 20:42 Well, did Borland / Inprise / Embarcadero probably change the synthax of assembler over the years ? I have no possibilities to verify this assembler code in an actual Delphi compiler .. ---------------------------------------------------------------------- Jonas Maebe · 2016-07-19 20:44 I did not say they changed the behaviour. I said to file a bug report with FPC if the behaviour is different in Delphi compared to FPC. ---------------------------------------------------------------------- PeterX · 2016-07-19 20:46 Okay, no problem. I'll file a bug report. But often I get the answer - "it is as it is". Is out there any table that translates DELPHI assembler  to AT&T or intel assembler ? ---------------------------------------------------------------------- Jonas Maebe · 2016-07-19 20:48 Delphi only supports Intel-style assembly. I.e., Intel-style assembly in FPC should behave the same as the assembly in Delphi. ---------------------------------------------------------------------- PeterX · 2016-07-19 20:49 Quote from: Jonas Maebe on July 19, 2016, 10:48:01 pmDelphi only supports Intel-style assembly. I.e., Intel-style assembly in FPC should behave the same as the assembly in Delphi. Okay, I take Your word .. ;-) ---------------------------------------------------------------------- PeterX · 2016-07-19 20:51 Bug report: Under "Category " there is no option "Assembler"  .. :-( ---------------------------------------------------------------------- Jonas Maebe · 2016-07-19 20:52 It's part of the compiler. ---------------------------------------------------------------------- PeterX · 2016-07-19 20:55 Thanks Jonas, I'll file it soon. ---------------------------------------------------------------------- PeterX · 2016-07-19 20:58 Submitted as 0030389: assembler code compiles different under Delphi 5 and Lazarus 1.6 ---------------------------------------------------------------------- Jonas Maebe · 2016-07-19 21:09 I just noticed you added begin/end between {$ifdef fpc}: that is wrong. It will probably also crash under Delphi if you would do that, because then it is no longer a pure assembly routine and the compiler will insert extra code around your assembler code. Remove the begin/end and use {$mode delphi} instead. ---------------------------------------------------------------------- PeterX · 2016-07-19 21:17 The whole project contains ~750.000 lines of code. It still compiles under Delphi 5 (yes, it was a lot of work .. the past years ..). And it still compiles under both Lazarus 1.6 AND Delphi 5 ! ---------------------------------------------------------------------- engkin · 2016-07-19 21:31 I just tried Jonas' suggestion: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$mode delphi} function LogN( Base, X: Extended): Extended;{$ifdef FPC}{$ASMMODE intel}{$endif}asm        FLD1        FLD     X        FYL2X        FLD1        FLD     Base        FYL2X        FDIV         // Lazarus Warning: fdivrp without operand translated into fdivrpP      FWAITend; begin  WriteLn('LogN(10,10000): ', LogN(10,10000));  ReadLn;end.  The result for LogN(10,10000) is 4. ---------------------------------------------------------------------- PeterX · 2016-07-19 21:46 I have a Test Project for this unit. I can confirm now that it compiles under both Lazarus 1.6 and Dephi 5 with {$mode delphi} ! ---------------------------------------------------------------------- PeterX · 2016-07-19 21:50 Switching back to  {$mode objfpc}{$H+} I get .. .. Fatal: Syntax error, "BEGIN" expected but "ASM" found Is there no way to make it compile with {$mode objfpc}{$H+}  ? I would like to leave behind the Delphi 5 version .. ---------------------------------------------------------------------- PeterX · 2016-07-19 22:13 Thanks Jonas and engkin ! Maybe it guides me to make a failing project work under Lazarus - tomorrow ! In my TimeZone it's time to go to bed now .. ;-) ---------------------------------------------------------------------- engkin · 2016-07-19 23:14 Quote from: PeterX on July 19, 2016, 11:50:37 pmSwitching back to  {$mode objfpc}{$H+} I get .. .. Fatal: Syntax error, "BEGIN" expected but "ASM" found Is there no way to make it compile with {$mode objfpc}{$H+}  ? I would like to leave behind the Delphi 5 version .. In objfpc mode you need to add the keyword assembler: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$mode objfpc} function LogN( Base, X: Extended): Extended; assembler; ---------------------------------------------------------------------- Jonas Maebe · 2016-07-20 08:49 Quote from: PeterX on July 19, 2016, 11:50:37 pmIs there no way to make it compile with {$mode objfpc}{$H+}  ? I would like to leave behind the Delphi 5 version .. See engkin's answer for that, but you can perfectly keep compiling your code using {$mode delphi} in FPC. We don't plan on removing this mode, nor on changing it so that it will break your code. All breaking changes added by Delphi 2009 and later will be added to {$mode delphiunicode} ---------------------------------------------------------------------- PeterX · 2016-07-20 09:50 Quote from: Jonas Maebe on July 20, 2016, 10:49:06 am.. you can perfectly keep compiling your code using {$mode delphi} in FPC. We don't plan on removing this mode, nor on changing it so that it will break your code. I try to avoid the DELPHI mode as far as possible. In FPC mode the rules are stricter. So - from my point of view - it helps cleaning the (foreign) code. In my project folder there are ~2.500 files (lots of overhead due to backups and TestProjects) But only 597 files still in {mode Delphi} Most of the differences between DELPHI 5 and LAZARUS can be solved. I just checked this - currently there are 2751 {$ifdef FPC} in my code ... hahaha ! OMG .. ---------------------------------------------------------------------- PeterX · 2016-07-20 09:52 Quote from: engkin on July 20, 2016, 01:14:29 amIn objfpc mode you need to add the keyword assembler Thanks for this hint ! I'll check this in both D' & L' version of the project. ---------------------------------------------------------------------- PeterX · 2016-07-20 09:53 Feedback from FPC bug tracker: "That is a known Delphi 5 bug:   Delphi compiles FDIV indeed as FDIVP." ---------------------------------------------------------------------- Thaddy · 2016-07-20 10:06 Indeed. Delphi users can verify the fact that FDIV is compiled as FDIVP through the CPU/FPU window. It is not an FPC bug and the bug is still (since 2004 at least) open in Delphi. I reported it at the time.... The solution for compatibility is to write FDIVP and that will be accepted by both Delphi and FPC. But it is a Delphi bug in BASM. Note this guidance also means that the other way around is hardly possible: compile fpc code that contains proper FDIV into Delphi ....would lead to floating point stack corruption. But in this case, changing Delphi sourcecode FDIV's to FDIVP's will solve it. ---------------------------------------------------------------------- Thaddy · 2016-07-20 10:31 Jonas, although you resolved that on Mantis with "The problem had nothing to do with fdiv/fdivp, but with the fact that the code contains an extra "begin .. end" around the assembler block when compiled with FPC. That means it was no longer a pure assembler routine, and the compiler inserted entry and exit code that did not expect a value to be left on the FPU stack at the end of the assembler block. " that is not really the case. I don't know if you have access to a Delphi compiler of that era D2,3,4,5,6,2005,2006)  but it is still a Delphi bug as you would be able to see if you open up the CPU/FPU window in delphi. It can of course be the case that there where actually 2 bugs. If you solved it both ways? Cudo's.... but I think there is more to it than just the begin/end. ---------------------------------------------------------------------- Jonas Maebe · 2016-07-20 10:37 This program prints exactly the same result when compiled with Kylix 3 (~ Delphi 6.5) and FPC 3.1.1: Code: [Select]fpc} {$mode delphi} {$endif} function LogN( Base, X: Extended): Extended; assembler; asm         FLD1         FLD     X         FYL2X         FLD1         FLD     Base         FYL2X         FDIV           // Lazarus Warning: fdivrp without operand translated into fdivrpP         FWAIT end; begin   writeln(logn(2,10)); end. Result: Code: [Select]$ dcc tt3.pp Borland Delphi for Linux Version 14.5 Copyright (c) 1983,2002 Borland Software Corporation tt3.pp(22) 23 lines, 0.01 seconds, 23412 bytes code, 3132 bytes data. $ ./tt3  3.32192809488736E+0000 $ ppn69 ./tt3.pp Free Pascal Compiler version 3.1.1 [2016/07/19] for i386 Copyright (c) 1993-2016 by Florian Klaempfl and others Target OS: Linux for i386 Compiling ./tt3.pp tt3.pp(14,9) Warning: fdivrp without operand translated into fdivrpP tt3.pp(14,9) Warning: "fdivrp" without operand translated into "fdivrp %st,%st(1)" Linking tt3 21 lines compiled, 0.2 sec 2 warning(s) issued $ ./tt3  3.32192809488736234781E+0000 So at least FPC and Kylix 3 interpret "fdiv" in Intel-style inline assembly in exactly the same way. ---------------------------------------------------------------------- PeterX · 2016-07-20 10:44 Quote from: Thaddy on July 20, 2016, 12:06:32 pmNote this guidance also means that the other way around is hardly possible: compile fpc code that contains proper FDIV into Delphi ....would lead to floating point stack corruption. But in this case, changing Delphi sourcecode FDIV's to FDIVP's will solve it. I have replaced the FDIV with FDIVP. Now Lazarus (1.6) reports for FDIVP:        Warning: "fdivrp" without operand translated into "fdivrp %st,%st(1)" What would be the proper assembler code for this in FreePascal ASM ? ---------------------------------------------------------------------- PeterX · 2016-07-20 11:23 Thaddy, Jonas, You both contributed to the solution ! Thaddy, the code I first presented, really crashes in Lazarus but not in Delphi ! => removed  begin .. end   and added   assembler; Jonas, I want correct code in FPC style, for the future. => replacing the FDIV with FDIVP is one step forward ! Thank You both ! ---------------------------------------------------------------------- PeterX · 2016-09-09 15:45 I am not finished with all these ancient assembler things .. I still have some warnings with unresolved ASM instructions. Today I found an old thread on google: https://groups.google.com/forum/#!topic/borland.public.delphi.language .basm/pJDd8LFXVQw Maybe this helps fixing all these old Delphi 5 code fragments, throwing - Warning: fmulp without operand translated into fmulpP - Warning: "faddp" without operand translated into "faddp %st,%st(1)" - Warning: "faddp" without operand translated into "faddp %st,%st(1)" etc ... ---------------------------------------------------------------------- PeterX · 2016-09-09 16:21 Okay, in the google thread I found a INTEL statement: ".. FADD instruction: The no operand version of the floating point add instructions always results in the register stack being popped.  In some assemblers, the mnemonic for this instruction is FADD rather than FADDP.     Sentences that are virtually identical to this appear for FSUB, FMUL, and FDIV.  What this means is that no matter how the no operand version of the instruction is implemented, be it FADD, or FADDP, it will pop the stack. This means that even though some assemblers choose to support the FADD mnemonic, it will always act like the FADDP instruction.  You can expect similar behavior for FSUB, FMUL, and FDIV." And from another post:    FADD = FADDP = FADDP ST(1) = FADDP ST(1),ST(0) This should make it clear, finally .. ---------------------------------------------------------------------- PeterX · 2016-09-09 16:53 .. and these warnings from Lazarus 1.6 are the wrong text: FADD   =>   Warning: faddp without operand translated into faddpP" FMUL   =>   "Warning: fmulp without operand translated into fmulpP" FSUB   =>   "Warning: fsubrp without operand translated into fsubrpP" ---------------------------------------------------------------------- PeterX · 2016-09-09 17:32 When I use "FDIVP", I get => Warning: "fdivrp" without operand translated into "fdivrp %st,%st(1)" When I then replace "FDIVP"   with   "fdivrp %st,%st(1)", I get => Fatal: illegal character "'%'" ($25) Wrong recommendation text ? Or because I use {$ASMMODE intel} ? ---------------------------------------------------------------------- marcov · 2016-09-09 19:14 I think you get a general errormessage that is for AT&T syntax. So probably you simply need to use two operand syntax fdivrp st1,st0 or so. I gambled that AT&T->intel required an inversion of arguments, but my copro asm is not really 100%. ---------------------------------------------------------------------- PeterX · 2016-09-10 14:31 Quote from: marcov on September 09, 2016, 09:14:10 pmI gambled that AT&T->intel required an inversion of arguments, but my copro asm is not really 100%. Yes, seems to be AT&T synthax. And  "fdivp st(1), st(0)"   instead of  "fdivrp %st,%st(1)"  compiles. ---------------------------------------------------------------------- PeterX · 2016-09-17 19:54 on     FSUB I get  "Warning: fsubrp without operand translated into fsubrpP" But to me  FSUB ST(1), ST(0)  is <>  fsubrpP