Visual C++ x86 ABI: how does VC++ return value? - visual-c++

I know 1/2/4-byte integers are returned in eax, and 8-byte integers are returned in eax:edx.
By the way, how are 4/8/16-byte floating-point values (Maybe I remember long double might be 16 bytes..) returned in cdecl/stdcall?
Thanks to #MatteoItalia, I know that VC++'s long double is 8-byte; Then, how can I use 16-byte floating-point?
(Don't say me "just use 8 byte!". I really need it.)
Um, I think I should be satisfied with 10-byte floating point...

FP return values are returned in the ST0 x87 register (see e.g. here).
By the way, in VC++ long double (which in x87 is 80 bit) is effectively a synonym for double.

You didn't provide the architecture but x86 returns floating-point values in ST(0) and x86_64 return in XMM0. See x86 calling conventions
But long double in VC for x86 and x86_64 is the same as double and won't provide you any more precision. So on Windows to do 80-bit floating-point operations you need to use another compiler such as GCC, Clang or ICC. Also, 80-bit long double is calculated by x87 so it may perform worse than a good SSE library.
If you need more than 10-byte long double then you must implement your own floating-point library or use some external libraries. GCC 4.3 and above have built-in support for __float128 through a soft library. See long double (GCC specific) and __float128
Another approach is using double-double to implement near-quadruple precision values like in PowerPC or SPARC. It's not IEEE compatible but you can utilize hardware double suport to speedup so it'll be faster than soft __float128

Related

It is possible to represent a 64-bit number as string when hardware doesn't support 64-bit number?

I want to show a 64-bit number as string. The problem is that my hardware doesn't support 64-bit number, just 32-bit.
So, I have the 64-bit number splitted into two 32-bit number (High and low part).
Example: 64-bit number : 12345678987654321 (002B DC54 6291 F4B1h)
32-bit low part: 1653732529 (6291 F4B1h)
32-bit high part: 2874452 (002B DC54h)
I think the solution to my problem would be showing this number as string.
It is possible?
Thanks.
yes you can use an array of 32 bit uints or even lower bit-width ...
for printing you can use this:
hex to dec
so first print a hex string which is easy on any bit-width (as you just stack up the lower bit-widths prints together from MSW to LSW) and then convert the hex text to dec text...
With this chained array of units you can do the math operations like this:
Cant make value propagate through carry
Doing operation on array of uints is much much more faster than on strings ...
but if you insist yes you can use string representation too ...
There are also hybrid representation like BCD that are suitable for this but your MCU would need to have support for it ...
Depending on your language of choice, the language may allow you to use greater-than-32bit integers, even on 32bits architectures (like python).
If that is the case the problem becomes trivial: compute the value, then compute the corresponding hex string.

Flipping bits in the mxcsr register

I'm attempting to set bits in the mxcsr control register. I know how to do this with gcc (fesetenv), but I haven't been able to get this working MSVC. The possibilities I've considered are:
Assembly, which isn't supported inline on MSVC x64.
The _controlfp function, which doesn't seem to match up one to one (note that I may be completely misunderstanding this function, but all of this is poorly documented).
Specifically, I want to set these bits:
"Denormals are zeros"
"Flush to zeros"
Any ideas for how I can do this?
The _controlfp routine is a generic routine that works across ARM, x86 and x64 - there is no reason to expect it to use the same bits the actual hardware registers use.
From the article _controlfp, it appears that _controlfp does not allow for individual control of input and output denormals, but sets them together.
To set the x64 SSE2 to flush denormal operands and outputs to zero, use
_controlfp(_DN_FLUSH, _MCW_DN);

Transferring parameters on 64 bit Linux in registers

I understand 64 bit Linux allows one to pass the first six integer function parameters and first eight floating point function parameters via registers.
If I had seven integer parameters to pass, is there any way for me to use one of the un-used float registers for the seventh integer, without sacrificing performance?
If you are writing your own assembly code, you can utilize the registers in whatever way you want (ok, maybe not quite that liberal, but you can be free to ignore the ABI, sorta). However, if you are interfacing with library code (or system calls, or parts of your program compiled from a higher level language, or ...) that was written to follow the standard ABI, you will have to follow the same restrictions in the portions of your code that form/use the ABI-compliant interfaces.

Is there a difference between datatypes on different bit-size OSes?

I have a C program that I know works on 32-bit systems. On 64-Bit systems (at least mine) it works to a point and then stops. Reading some forums the program may not be 64-bit safe? I assume it has to do with differences of data types between 32-bit and 64-bit systems.
Is a char the same on both? what about int or long or their unsigned variants? Is there any other way a 32-bit program wouldn't be 64-bit safe? If I wanted to verify the application is 64-bit safe, what steps should I take?
Regular data types in C has minimum ranges of values rather than specific bit widths. For example, a short has to be able to represent, at a minimum, -32767 thru 32767 inclusive.
So,yes, if your code depends on values wrapping around at 32768, it's unlikely to behave well if the short is some big honking 128-bit behemoth.
If you want specific-width data types, look into stdint.h for things like int64_t and so on. There are a wide variety to choose from, specific widths, "at-least" widths, and so on. They also mandate two's complement for these, unlike the "regular" integral types:
integer types having certain exact widths;
integer types having at least certain specified widths;
fastest integer types having at least certain specified widths;
integer types wide enough to hold pointers to objects;
integer types having greatest width.
For example, from C11 7.20.1.1 Exact-width integer types:
The typedef name intN_t designates a signed integer type with width N, no padding
bits, and a two’s complement representation. Thus, int8_t denotes such a signed
integer type with a width of exactly 8 bits.
Provided you have followed the rules (things like not casting pointers to integers), your code should compile and run on any implementation, and any architecture.
If it doesn't, you'll just have to start debugging, then post the detailed information and code that seems to be causing problem on a forum site dedicated to such things. Now where have I seen one of those recently? :-)

Strategies for parallel implementation of Lua numbers and a 64bit integer

Lua by default uses a double precision floating point (double) type as its only numeric type. That's nice and useful. However, I'm working on software that expects to see 64bit integers, for which I don't get around using actual 64bit integers one way or another.
The place where the integer type becomes relevant is for file sizes. Although I don't truly expect to see file sizes beyond what Lua can represent with full "integer" precision using a double, I want to be prepared.
What strategies can you recommend when using a 64bit integer type in parallel with the default numeric type of Lua? I don't really want to throw the default implementation overboard (and I'm not worried of its performance compared to integer arithmetics), but I need some way of representing 64bit integers up to their full precision without too much of a performance penalty.
My problem is that I'm unsure where to modify the behavior. Should I modify the syntax and extend the parser (numbers with appended LL or ULL come to mind, which to my knowledge doesn't exist in default Lua) or should I instead write my own C module and define a userdata type that represents the 64bit integer, along with library functions able to manipulate the values? ...
Note: yes, I am embedding Lua, so I am free to extend it whichever way I please.
As part of LuaJIT's port to ARM CPUs (which often have poor floating-point), LuaJIT implemented a "Dual-number VM", which allows it to switch between integers and floats dynamically as needed. You could use this yourself, just switch between 64-bit integers and doubles instead of 32-bit integers and floats.
It's currently live in builds, so you may want to consider using LuaJIT as your Lua "interpreter." Or you could use it as a way to learn how to do this sort of thing.
However, I do agree with Marcelo; the 53-bit mantissa should be plenty. You shouldn't really need this for a good 10 years or so.
I'd suggest storing your data outside of Lua and use some type of reference to retrieve it when calling your other libraries. You can then push various results onto the Lua stack for the user the see, you can even retrieve the value as a string to be precise, but I would avoid modifying them in Lua and relying on the Lua values when calling your external library.
If you're not going to need floating-point precision at any point in the program, you can just redefine LUA_NUMBER to __int64 (or whatever 64-bit int may be in your environment) in luaconf.h.
Otherwise, you can just bring in another library to handle your integers- for infinite precision, you can use a bignum library such as lhf's lbn.

Resources