modrm calculation still done inline on each opcode, but later op
directives don't branch from each modrm outcome anymore. Speeds
compilation by about 30%, and decreases release binary size by about
300K currently (and presumably more when the rest of the opcodes are done)
Gearing up to change modrm code to no longer push its directives onto
the main processing stack. This also necessitates making the
function's $form/width/tyargs-thingy a child of $name.
It might be nice to revisit this at some point if we want to merge all
the different form=word[0,1,2,3] arities together. I had hoped that
FarPtr could become parameterized on its pointee width (u8 or u16) and
that would obviate the need for turbofishing the op function
directly. Unfortunately, the string operations need disambiguation
regardless as they construct their pointers internally. But perhaps
that could've been solved with some PhantomData. Regardless, this kind
of approach becomes more difficult after this commit as the width is
now tied to the function name.
Keeps the macro recursion from branching. In effect this just moves a
conditional from @r8's output to the RegHalf wrapper, so this is
usually a wash except with less code generated.
Avoids O(M*N) codegen blowup when paired with a modrm arg.
Probably want to do the same thing to the modrm op directives but
those cases are little more tricky and this alone gets rid of much of
the pain.
I think this was from when registers were passed by mut ref and this
could update them in place. Now they are wrapped and those wrappers
are LValues instead.
I think this made sense originally because registers were being passed
as borrows directly out of the cpu struct. Now they have wrappers
around Cell refs, and those wrappers can be passed directly.
Also made all LValues also RValues for brevity (so INC/DEC don't have
to bound their destination arguments by both, but this is not required
if it causes problems for some reason down the road).
This also promotes CALL/RET to actually using the bus for
addressing (because it goes through the generic PUSH/POP code), which
is probably more correct anyway.
Likely to be a bugfest.
There's a flags macro for now but unclear how useful it will turn out
to be in practice. Flags in particular need testing.
Also disappointing that I couldn't make instructions generic across
u8/u16, especially for ordinary, non-string CMP. Need to look into
this more to see if it can be done with num-traits or some other
trickery.
r16 + modrm16 allowed cpu regs to alias. Wrap them in Cell to allow
this. We also create a Reg wrapper when passing regs so that we can
pass as &mut while simultaneously having other references to the same
reg.