Based on @phire's idea, Inline constants are constants that can be used as imms in instructions.
This
- Adds OP_INLINECONSTANT to represent them in the IR
- Modifies the ConstProp pass to transform OP_CONSTANT to OP_INLINECONSTANT based on per-platform heuristics
- Modifies the backends to use imms
- Supported opcodes: Add, Sub, Lsl, Lsr, Asr, Ror, Rol
This should really be done later in a sperate PR.
1. We don't have proper unit test coverage
2. I still didn't get this right at time of removal
3. I haven't done the jit changes to go along with this.
This interface is for native host code to be able to call back in to JIT
to execute guest code.
This is mainly for thunks but could be used for other purposes.
This can cross a couple ABI boundaries so one must be careful when
calling in to this
Add and substract were the main culprits here.
We are trying to more towards a state where:
* Every IR op can expect it isn't given extra bits
on it's input
* Every IR op never sets more bits than it's size
* All unnessicary BFEs are never emitted
* ARM doesn't have to implement special 8 and 16bit versions of IR ops
All masking required to implement 8/16bit math on
arm should be explictly generated from Opcode decoder
The IR mostly worked this way already.
The one change I needed to make was in DCSE.
DCSE needs to add an explict truncate whenever an eliminated store was
doing an implict trunctate.
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
This implements support for 130 of the 132 x87 ops as interpreter
fallbacks.
The two missing ops are the BCD load and BCD store instructions and can
be implemented another time.
This allows us to no longer have to rely on a libstdc++ modification to
handle their usage of long double. This instead works entirely through
using `long double` directly in the interpreter. Which will either use
real x87 on an x86 host. Or in the case of ARM devices, fall down
glibc's long double soft float path.
This doesn't necessarily need to be quick right now. It's more important
to have the compatibility improvement from this.
The IRHeader itself contains a flag for if a block should fallback to
the interpreter.
This is necessary for the case that an IR is loaded and the Frontend
object no longer has the data necessary to know if it should do an
interpreter fallback.
This is super useful for bisecting JIT versus Intepreter failures, and
also cases where falling back to intepreter for compatibility is a lot
more simple than wiring things through the JIT (ala x87)
This isn't currently utilized, but will be once x87 work lands
Sadly this is a fairly substantial change that can't be broken in to
something smaller.
The gist of the problem is that most of the vector ops declared their
own uint8_t RegisterSize and ElementSize variables in their structs.
This was initially done because there were assumptions elsewhere in the
source that sometimes mixed up the IROp member `Size` and `Elements` as
sometimes meaning `Size` elements and `Elements` number of elements.
Other times there was an assumption that `Size` was the full register
size and `Elements` was the number of elements inside that size.
ex: `Size`: 16, `Elements` 8 would sometimes be interpreted as i8v16 OR i128v8
These assumptions are now removed and we also save on average 16bits per
vector operation. This is a necessary evil first step for upcoming IR
considerations.
This should have zero change on runtime behaviour and unit tests confirm
that.
Changes the IR register class definition to exist in the JSON file.
Removes a couple of IR ops that were unused and weren't necessary.
Changes the CPUID IR op to the new paired op which improves perf ever so
slightly.
Changes RA class handling in the RA pass to pull directly from the new
generated helper routine until it hits a complex op
Still need RA constraints to remove extraneous moves that would crop up
Both AArch64 and x86 don't have optimal paths to move <64bit FPRs to
another with ZEXT.
So this is optimal for 128bit and 64bit while smaller ops have have the
expected overhead when using it
vector pairwise add
vector unsigned shift right with narrowing
vector unsigned and signed extend with lengthening from upper bits
vector unsigned and signed multiply with lengthening from upper bits
These are fairly popular so not having them around is causing headaches.
We will really want these in the future to use the host register, btu
that is more time consuming than I want to dedicate to at the moment.
So the FCMP instruction must be told which flags to generate up front,
then it generates the flags in to a GPR which are then tracked and
pulled out with a specific IR op.
This can be augmented in the future to more easily RA the host flag
register