This provides and, ior, xor, com, zer, set, cms when defined($1) and
ior, set when !defined($1). I don't provide the other operations
!defined($1) because our Modula-2 compiler hasn't used them.
I wrote a Modula-2 example in
https://gist.github.com/kernigh/add79662bb3c63ffb7c46d01dc8ae788
Put a dummy comment in mach/powerpc/libem/build.lua so git checkout
will touch that file. Without the touch, the build system doesn't see
the new *.s files.
We only implement 'los 4', 'sts 4', 'cmi 4', 'cmu 4', not for sizes
other than 4. Add clause $1==4.
We only implement inn when defined($1).
The rule for aar needs 'kills ALL' because it kills many registers,
like other rules that call libem.
This allows 'move {CONST, $1}, R3' with a small enough $1 to emit one
instruction (addi) instead of two instructions (addis, ori). The
CONST token confusingly isn't in the CONST_ALL set.
The spec says, "ASS w: Adjust the stack pointer by w-byte integer".
The w argument "can either be given as argument or on top of the
stack." Therefore, 'ass 4' would pop the 4-byte integer from the
stack, but 'ass' would pop the size w from the stack, then pop the
w-byte integer.
PowerPC ncg wrongly implemented 'ass' as if it was 'ass 4'. Fix it to
accept only 'ass 4'.
These instructions would load or store the EM heap pointer. They
don't work. Programs must use brk() or sbrk() in libsys.
The last file to use 'lor 2' and 'str 2' was lang/pc/libpc/sav.e in
the Pascal library. Commit c084f9f deleted the file, so we no longer
need rules 'lor 2' or 'str 2' to build the ACK.
PowerPC has a few hundred special-purpose registers. The assembler
had only accepted the names "xer", "lr", "ctr". Most programs use
only those three SPRs. If I add more names, they would almost never
get used, and they might conflict with labels.
I want to use "mfspr r3, 0x3f0" and "mtspr 0x3f0, r3" in
plat/qemu/boot.s to access register hid0 from supervisor mode.
corresponding invocation in the ncg table so the same helpers can be used for
both mcg and ncg. Add a new IR opcode, FARJUMP, which jumps to a helper
function but saves volatile registers.
occasionally the first hop of a block would try to rearrange its registers (due
to evicted throughs), resulting in the phi moves copying values into the wrong
registers.
register 'type'; now use int/float/long/double throughout to identify
registers. Lots of register allocator tweaks and table bugfixes --- we now get
through the dreading Mathlib.mod!
This would have happened later, if f14 to f31 became regvar (like r13
to r31 are now). I am doing it now because ncg is too slow for rules
"with FREG FREG uses FREG". We use such rules for adf 8 and other EM
instructions that operate on 2 floats. Like my last commit cfbc537,
this commit speeds ncg by removing choices for register allocation.
ncg is too slow with this many registers. A stack pattern "with GPR
GPR GPR" or "with REG REG REG" takes too long to pick registers,
causing ncg 8 to take about 2 seconds on each sti 8. I introduce
REG_PAIR and there are only 4 such pairs.
For programs that use sti 8 (including C programs that copy 8-byte
structs), this speed hack improves the ncg run from several seconds to
almost instantaneous.
Also add a few COMMENT(...) lines in stacking rules.
This fixes the SIGILL (illegal instruction) in startrek when firing
phasers. The 32-bit processors in my PowerPC Mac and in QEMU don't
have fctid, a 64-bit instruction.
I got the idea from mach/proto/fp/fif8.c to extract the exponent,
clear some bits to get an integer, then subtract the integer from
the original value to get the fraction.
Adjust some of the loi rules (and associated moves) so we can identify
the tokens that must be in MEMORY.
With this commit, I can navigate the Enterprise even if I comment out
my work-around from e22c888.
Because li32 always loads a label into a GPR, it is sufficient to
coerce LABEL to REG, then use IND_RC_W or IND_RC_D for indirection
through the label.
Now that SUM_RC always has a signed 16-bit constant, it happens that
the various IND_RC_* tokens also have a signed 16-bit constant, so
we no longer need to touch the scratch register.
When loc (load constant) pushes a constant, it now checks the value of
the constant and pushes any of 7 tokens. These tokens allow stack
patterns to recognize 16-bit signed integers (CONST2), 16-bit unsigned
integers (UCONST2), multiples of 0x10000 (CONST_HZ), and other
interesting forms of constants.
Use the new constant tokens in the rules for adi, sbi, and, ior, xor.
Adjust a few other rules to understand the new tokens.
Require that SUM_RC has a signed 16-bit constant, and OR_RC and XOR_RC
each have an unsigned 16-bit constant. The moves from SUM_RC, OR_RC,
XOR_RC to GPR no longer touch the scratch register, because the
constant is not too big.
and epilogues. mcgg now exports some useful data as headers. Start factoring
out some of the architecture-specific bits into an architecture-specific file.
Change the operator in his() from a - minus to a + plus. When los(n)
becomes negative, then his(n) needs to add 0x10000, not subtract it.
Also change los(n) to do the sign extension, because smalls(los(n))
should be true, not false.
Also change hi(n) and lo(n) to wrap n in parentheses, as (n), because
these are macros and n might still contain operators.
attributes when allocating. Unfortunately, backward edges don't work (because
the limited def-use chain stuff doesn't work across basic blocks). Needs more
thought.
turned into generic ones (as they'll be useful everywhere). Node arguments for
predicates require the '%' prefix for consistency. Hex numbers are permitted.
This feature has never been used since its introduction, more than 3
years ago, in David Given's commit c93cb69 of May 8, 2013. The commit
was for "PowerPC and M68K work". I am not undoing the entire commit.
I am only removing the stackadjust and stackoffset() feature.
This commit removes the feature from my branch kernigh-linuxppc. This
removal includes the mach/proto/ncg parts. The default branch already
removed most of the feature, but kept the mach/proto/ncg parts. That
removal happened in commit 81778b6 of May 13, 2013 (which was a merge;
git diff af0dede81778b6). The branch dtrg-experimental-powerpc
merged the default branch but without the removal. That merge was
commit 4703db0f of Sep 15, 2016 (git diff 8c94b134703db0). My branch
kernigh-linuxppc is off branch dtrg-experimental-powerpc, so I can no
longer get the removal by merging default.
David Given described the stackadjust feature in
https://sourceforge.net/p/tack/mailman/message/30814691/
The instruction stackadjust would add a value to the offset, and the
function stackoffset() would return this offset. One would use this
to track sp - fp, then omit the frame pointer by not keeping fp in a
register.
We only need GPRE in a few places where we write {GPRE, regvar(...)}
because ncgg can't parse plain regvar(...). In all other places, a
plain GPR works.
Also remove gpr_gpr_gpr and a few other unused and fake instructions
from the list of instructions.
Rename the scratch gpr (currently r11) from SCRATCH to RSCRATCH so I
can search for RSCRATCH without finding FSCRATCH. I also want to
avoid confusion with the SCRATCH keyword of the old code generator (cg
which came before ncg).
Change the stacking rules to prevent stacking of RSCRATCH or FSCRATCH
or any other GPR or FPR that isn't an allocatable REG or FREG. Then
ncgg rejects any rule that tries to stack a GPR or FPR, so change such
rules to stack a REG or FREG.
order. Since the dominance tree has changed when I fiddled with the graph, I
need to recompute it, so factor it out of the SSA pass. Code is uglier than I'd
like but at least the RET statement goes last in the generated code now.
mcg can track individual hop inputs and outputs (needed for live range
analysis!); the register allocator now puts the basic blocks into the right
order in preparation for live range analysis.
to make special nodes like NOP work properly). Realise that the way I'm dealing
with the instruction selector is all wrong; I need to physically copy chunks of
tree to give to burg (so I can terminate them correctly).
inasmuch as it looks better before register allocation. Basic blocks now know
their own successors and predecessors (after a certain point in the IR
processing).
functions. Not convinced that semantic types are actually working --- there are
still problems with earlier statements leaving things in the wrong registers.
In our powerpc table, sdl fails to kill the old value of the local.
This is a bug, because a later ldl can load the old value instead of
the newly stored value. By rewriting "sdl 0" "ldl 0" as "dup 8" "sdl
0", the newly added rule works around the bug, but only when the ldl
is immediately after the sdl.
This rule improves code that uses double-precision floating point.
The output of printf("%f", 6.0) in C changes from all zero digits to
"6000000" but still doesn't print the decimal point. The result of
atof("-123.456") becomes correct. In startrek, I can now move the
Enterprise, but I still can't fire phasers without crashing the game.
We already have a rule for stl lol $1==$2. We had two copies of the
rule, so I am deleting the second copy.
In EM, fef splits a float into exponent and fraction. The old C code,
given an infinite float, got stuck in an infinite loop. The new
assembly code doesn't loop; it extracts the IEEE exponent.
This fixes code that tried to "addi SP, SP, 4" to drop a value that
was in a register, not on the real stack.
Add a rule to optimize "asp 4" (which becomes "loc 4" "ass") when
the value being dropped is already in a GPR.
When ncg fell back on this rule, it did emit the string "invalid" in
the assembly code and caused a syntax error in the assembler.
Adjust the stacking rules so we can stack LOCAL, CONST, and LABEL
without falling back on the "invalid" rule, and so we can stack them
when we have no free register except the scratch register.
jumps to blocks which contain only a jump). Don't bother storing the bb graph
in the ir nodes; we can find it on demand by walking the tree instead ---
slower, but much easier to understand and more robust. Added a terrible map
library.
instructions can be turned on and off based on their parameters. New lexer
using a lexer. Now quite a lot of the way towards being a real instruction
selector.
GNU as has "la %r4,8(%r3)" as an alias for "addi %r4,%r3,8", meaning
to load the address of the thing at 8(%r3). Our 'la', now 'li32',
makes an addis/ori pair to load an immediate 32-bit value. For
example, "li32 r4,23456789" loads a big number.