Skip to content

Instantly share code, notes, and snippets.

@eira-fransham
Last active October 16, 2019 09:18
Show Gist options
  • Save eira-fransham/7c8d80ca6ed7c5289b7481056097c81e to your computer and use it in GitHub Desktop.
Save eira-fransham/7c8d80ca6ed7c5289b7481056097c81e to your computer and use it in GitHub Desktop.
-- Unless otherwise specified, all the different input/output bit sizes are needed. You might be able to write helpers to
-- make this easier.
adc
add
-- I'm sure you know this but just to make 100% certain: all of the `***ss`/`***sd` instructions operate on IEEE754
-- floats and so need to use separate Low IR actions to the integer operations. Futhermore, `div` has signed and unsigned
-- integer variants, plus single- and double-precision float variants. So that might look like `DivIntS(NumBits)`,
-- `DivIntU(NumBits)` and `DivFloat(FloatSize)` where `FloatSize` is an enum of `Single`,`Double`.
addsd
addss
and
andpd
andps
-- These two might not need their own instruction definitions, we could just have a fallback encoding for `lzcnt`/`tzcnt`
-- that emits a stream of instructions using them.
bsf
bsr
-- TODO: To start with we can just have unique "call" and "ret" actions, but we might find it useful in the future to
-- explicitly write out that `call` writes `rip` to stack, increases the stack pointer and then does the jump.
-- F.E., we could imagine that TCE could be implemented by the backend simply noticing that the pushed RIP isn't
-- needed after the call and so realising that it can just emit a `jmp` (although Lightbeam currently isn't
-- sophisticated enough to have any way of knowing if the pushed RIP is used after the call)
call
-- You want to have an action `MovIf`, then one instruction definition per size that takes the condition code as a parameter
cmovcc
-- This should be defined exactly the same as `sub`, just without access to the result of the subtraction, since that's what
-- it does and defining it this way allows us to be smarter WRT DCE
cmp
comisd
comiss
-- These should all be their own unique actions
cvtsd2ss
cvtss2sd
cvttsd2si
cvttss2si
-- TODO: Make this its own action for now, although if we ever support storing values across multiple registers this could
-- be modelled as a signed `mov` from a single-register 32-bit value to a 64-bit value stored in 2 32-bit registers.
-- This has upsides w.r.t. making dealing with instructions that split their input across registers simpler (x64 only
-- has a couple but other architectures have way, way more). I don't want to try implementing this now just because it
-- might mean that we have to work out some way to encode the fact that an unsigned single-register->register-pair
-- mov is the same as zeroing one of the pair of registers - either by adding dummy synonym instruction definitions
-- or by adding special code to LIRC.
cdq
-- Don't try to model this as "2-argument div but one of the arguments is stored in multiple registers" - just give it 3
-- params, 2 of which are specific registers,
div
divss
divsd
idiv
-- For 32-bit inputs this produces a 64-bit value across 2 registers, for 64-bit inputs it produces a 128-bit value across
-- 2 registers, etc. Just have two actions, `Mul32Low` and `Mul32Hi`, and have this instruction do both.
imul
-- With the jump instructions we have to deal with the fact that we don't know the distance of the label when emitting the
-- instruction, since it's emitted with a dummy parameter which is later overwritten using relocations. While `asmquery`
-- doesn't need to deal with relocations at all, it _does_ need to have some way to specify whether the jump is a `rel8`, a
-- `rel16` or a `rel32`.
-- Additionally, we don't have types in `asmquery`, but it's useful to at least keep input/output bit sizes consistent for
-- instructions, and so for `jcxz`/`jecxz` we would want to model it as an `IsZero` against `cx`/`ecx` followed by `JumpIf`
-- using the result of the `IsZero`, instead of `JumpIf` with a `cx`/`ecx` param.
jcc
jmp
lea
maxsd
maxss
minsd
minss
-- This will map to different actions depending on whether it's reg-reg or reg-mem/mem-reg. The memory variants will use
-- `Load`/`Store` whereas `reg-reg` will use `Move`.
mov
movapd
movaps
movd
movq
movsx
movzx
mul
mulsd
mulss
not
or
orpd
orps
-- This should be modelled as two separate actions, `Store` to `rsp` and `rsp += 1`, instead of a single `Pop` action
pop
push
ret
sal/sar/shl/shr
setcc
sqrtsd
sqrtss
sub
subsd
subss
-- As with `cmp`, this should be exactly the same as `and` but with the result of the `and` being internal
test
ud2
xor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment