When RA made the source address register be the same register as the
destination register then we could have overwritten the address with the
move.
Use a temporary until we get RA constraints in place.
For loadstores to memory, this will use TSO ops to emulate x86
behaviour.
In the case that the source register is the stack pointer then it falls
back down to using regular loadstores. Since it is expected that stack
pointer usage will be thread specific.
With the AArch64 implementation this makes us be quite a bit closer to
being x86 TSO compliant
This patches unaligned LORegion loadstores with DMB wrapped loadstores.
This will ensure full cacheline consistency on loadstores, at the
expense of speed.
The performance can potentially be improved with "Half-barriers"
Described a bit here: https://github.com/dotnet/runtime/issues/8072
We can worry about that path after the initial implementation
This is the base implementation that uses LORegion loadstore
instructions to support the load/store release semantics, which these
instructions use.
Sadly these don't match the alignment requirements of x86 loadstores, so
if it was just used everywhere then it will cause alignment faults.
This means we need to catch the sigbus and backpatch the instruction to
do safe (aka expensive) TSO.
Currently this backpatch just falls back to regular loadstores
surrounded by DMB instructions.
Basically unaligned loadstores will fall back to nearly what we are
doing now, so significantly improved but not perfect.
A follow up PR will change this over to using a helper routine to be
100% safe
It needs to track guest SigAltAction and have its own definitions for
sigaction and sa_mask. sa_mask specifically is defined differently
between the kernel and glibc.
Also fixes some issues with the SignalDelegator that posix tests found
We are rebranding an x86-64 illegal instruction near VIA's old ALTINST
instruction as an instruction to handle returning from guest signals
cleanly.
If this ever collides with a new x86-64 (unlikely) then we will need to
change the instruction.
This ends up looking similar to what we will do for thunk callbacks
Just generates some context level x86 code space for our guest to jump
in to.
This is only currently used for sigret but will become more important as
we come to support vdso.
This was sort of partially worked around.
The issue comes down to REX.W and Operand size prefix ordering on an
instruction.
When an instruction has both prefixes, then the one that has occured
later will overwrite the previous one.
Additionally in the case of 66h being reused as an escape prefix, we
needed to ignore it in this case.
The previous workaround was that if an instruction happened to have both
widening and narrowing, then widening would win(for MODRM args),
but then later on in the instruction decoding the literal constant
decoding would properly check which order the flags came in.
This resulted in literal constants working, but not modrm bytes
Instead replace the "last" flag handling with a two deep stack that we
can push and pop the flags correctly on to it, this ensures that the
flags stay around in the 66h ignoring mode (so widening doesn't get
obliterated).
This effects every instruction that supports REX.W and 66h Operand size
prefix, so it could be fixing some unknown bugs elsewhere.
Very specifically this one was found in OpenSSL, because it looks like
GCC is padding a mov instruction with 66h.
Instruction Examples:
Only difference is the prefix order being swapped
0x00000000 4 66488b1f mov rbx, qword [rdi]
0x00000004 4 48668b1f mov bx, word [rdi]
AArch64's ADDV instruction doesn't support 8byte elements, it instead
needs to use ADDP(scalar) for the operation.
Fixes an assert and minor behaviour difference there
LORegion is a requirement of ARMv8.1, but the hypervisor of the c630
isn't exposing the identification register correctly.
If the host supports atomics, just assume it supports LORegions as well
Fixes an assert when building vixl in debug
Allows us to register host and guest signal delegators.
Currently only host signals are handled, guest signal delegation will
take a bit of work still.
Previously the ARM64 JIT didn't support cache clearing at all.
This adds support for clearing the JIT cache while keeping dispatcher
helpers around and the ASM dispatcher alive.
Improves compilation time by multiple minutes
Clang was taking multiple minutes to compile JIT.cpp for ARM.
This drops it down to a handful of seconds instead.
No functional behaviour change, only movement.
JIT compile times might deviate slightly moving from a switch to a jump
table, but will be negligible in either direction.
The break ir op is actually a block ender and it happened that in
regular code paths they were already ending the blocks correctly.
This enforces block ending in the Unimplemented op so multiblock still
generates the invalid code path correctly and it compiles.
We hit these a few times in multiblock for times in the code where it is
checking for CPU features and choosing a code path depending on CPUID
results.
Potentially these could be made in to no-ops since we'll never hit these
codepaths in practice, but it is nicer to break in case we actually do
hit one of these paths.
There's some history for this instruction. It is not in the official
instruction documentations from AMD or Intel but it is supported on
almost every x87 supporting CPU (I think there was some Cyrix that
missed it?)
This was originally implemented by accident on the Intel 80287 CPU.
It was then periodically documented in random documentation.
The instruction behaves exactly like FFREE but then pops the stack after
the operation.
For our current implementation of FFREE, which is a NOP, we just need to
pop the stack.