View Full Version : Softwire 64 bit version ready
sh0dan
18th November 2006, 13:04
Nicolas Capens has just committed a new version of Softwire, which is capable of generating 64 bit code. I have only briefly looked at the code, but it looks like it always has.
https://gna.org/projects/softwire#options
Hopefully we can now get some code ported to the 64 bit version.
squid_80
19th November 2006, 12:05
The offsets in the generated code are 32-bit absolute (which is obviously wrong) when they should be 32-bit RIP relative. Is there any documentation on the new 64-bit additions anywhere?
squid_80
19th November 2006, 17:03
I got it working (kind of) by using relative addressing with a zeroed register as the base. It's a very bad way of doing it since it will fail if the memory location is higher than 4gb.
Additional problems to watch out for if anyone else wants to experiment with it:
Several push r(8-15) instructions generate the wrong opcodes. For example push r14 generates the opcode for pop rsi. Fairly easy to catch because when you load a function parameter from the stack it's something completely different to what it should be. The wrong instruction sticks out like a sore thumb when viewing disassembled code.
Several pop r(8-15) instructions generate the wrong opcodes. Slightly harder to find than the previous bug, because it appears to work... until the epilog is executed, the function returns and the instruction pointer ends up in no mans land.
Invalid inc/dec instructions (dec ebx) don't throw an error and are generated as x86 opcodes which are interpreted as rex prefixes and ignored upon execution. This one was nasty. I had a loop copying data from src to dst, and dst happened to be just below the dynamic code. Since the count wasn't being decremented the loop kept going... and overwrote the dynamic code. Disassembly showed the dec instruction was completely missing, until I realized dec ebx is invalid in long mode and that's why the following opcode had 2 REX prefixes.
c0d1f1ed
20th November 2006, 09:42
Hi guys,
It's a first experimental release so it's largely untested. I just added all 64-bit instructions and implemented the REX byte. But there's still a number of things to implement...
Thanks for identifying those issues. Feel free to e-mail me directly for features or bugs.
Cheers,
Nicolas
c0d1f1ed
20th November 2006, 12:31
I have RIP-relative addressing ready now (not yet committed), but I was wondering whether absolute addressing would still be useful, and how to expose it. I think it's only useful for O.S. and driver development, so I can probably ignore it in SoftWire. But please let me know if it's a useful feature, and how you'd like to use it.
squid_80
20th November 2006, 12:54
I've only done x64 coding for windows, but the only time I've seen anything but RIP-relative addressing being used is in the exception handling data (.pdata).
One simple request while I'm here: when using align, the padding space required is filled with NOPs. In 64-bit mode it's possible to prefix the NOP instruction (0x90) with up to two size override bytes (0x66). So if we needed 8 bytes of padding, instead of putting:
0x90
0x90
0x90
0x90
0x90
0x90
0x90
0x90
We could use:
0x66 0x66 0x90
0x66 0x66 0x90
0x66 0x90
and get better instruction-decode performance. More info available in the amd64 optimization guide, chapter 4.11.
squid_80
21st November 2006, 12:59
The RIP-relative addressing works perfect. It's all looking very promising. (One small bug: the x64 prologue() and epilogue() don't match up.)
Is there a chance to get some polymorphic types for OperandMEM and OperandREG, based on the pointer size of the architecture being used? For example, for 32-bit code I can do this:
void* gen_dstp;
void* gen_temp_dstp;
Assembler x86(false);
x86.mov(eax, dword_ptr [&gen_dstp]);
x86.mov(dword_ptr [&gen_temp_dstp], eax);
While for 64-bit it looks like this:
void* gen_dstp;
void* gen_temp_dstp;
Assembler x86(true);
x86.mov(rax, qword_ptr [&gen_dstp]);
x86.mov(qword_ptr [&gen_temp_dstp], rax);
If I had polymorphic types called something like pax (ax register as a pointer, =eax on 32-bit, =rax on 64-bit) and ptr_ptr (=dword_ptr on 32-bit, =qword_ptr on 64-bit) I could do this:
void* gen_dstp;
void* gen_temp_dstp;
Assembler x86(_AMD64_); //defined by project configuration
x86.mov(pax, ptr_ptr [&gen_dstp]);
x86.mov(ptr_ptr [&gen_temp_dstp], pax);
Hence the same code could be used for 32-bit or 64-bit builds.
c0d1f1ed
21st November 2006, 14:49
One simple request while I'm here: when using align, the padding space required is filled with NOPs. In 64-bit mode it's possible to prefix the NOP instruction (0x90) with up to two size override bytes (0x66).
I verified that it's also valid in 32-bit mode. I'm not sure though if it runs optimally on Intel processors. Their documentation specifies other multi-byte nops. The real nop gets optimized to have no dependencies, but I'm not sure if that's still the case with 66h prefixes.
squid_80
21st November 2006, 14:53
Is the add(R_M64, dword) implemented? I can't seem to find it anywhere.
c0d1f1ed
21st November 2006, 15:13
Is there a chance to get some polymorphic types for OperandMEM and OperandREG, based on the pointer size of the architecture being used?
It's possible, but not without serious pitfalls.
At this moment SoftWire is still an assembler, not a compiler, so it's up to the programmer to rewrite the code when targetting a new architecture.
Anyway, I'll definitely keep this in mind when taking SoftWire to the next level.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.