This turns EM `con 5000000000I8` into assembly `.data8 5000000000` for
machines i386, i80, i86, m68020, powerpc, vc4. These are the only ncg
machines in our build.
i80 and i86 get con_mult(sz) for sz == 4 and sz == 8. The other
machines only get sz == 8, because they have 4-byte words, and ncg
only calls con_mult(sz) when sz is greater than the word size. The
tab "\t" after .data4 or .data8 is like the tabs in the con_*() macros
of mach/*/ncg/mach.h.
i86 now uses .data4, like i80. Also, i86 and i386 now use the numeric
string without converting it to an integer and back to a string.
unsigned comparisons is surprisingly not that useful due to marshalling
overhead; it's only four bytes to do inline (plus jc), or six for a constant.
Also add some useful top optimisations. Star Trek goes from 39890 to 39450
bytes.
Old .o files stop working if they use floating point. One must
recompile those files. Old files don't call libfp in the correct way,
and may use symbols that I removed from libem. I don't keep old
symbols in libem/flp.s, because a program that pulls both libfp and
flp.s would get "multiply defined" errors in the linker.
I teach mach/i80/ncg/table to use libfp by copying or adapting the
patterns from mach/i86/ncg/table. I did not test all the patterns,
but I did use `ack -mcpm -fp -O4` to compile examples/mandelbrot.c,
then I ran it in the emulator YAZE-AG. It worked, but it was slow.
EM instructions _rol_ and _ror_ do rotate an integer left or right.
Our compilers and optimizers never emit _rol_ nor _ror_, but I might
want to use them in the future.
Add _rol_ and _ror_ to powerpc. Fix `rol 4` and `ror 4` in both i80
and i86, where the rules for `rol 4` and `ror 4` seem to have never
been tested until now.
The code used `sphl` to set the stack pointer, but the correct value
was in de, not hl. Fix by swapping the values of de and hl, so `sphl`
is now correct. When we shrink an integer from 4 to 2 bytes, both
registers de and hl point to copies of the result, but only one
register preserves the stack below the result.
This fixes writehex() in tests/plat/lib/test.c, when I compile it with
ack -mcpm, so it preserves the pointer to "0123456789abcdef", so it
writes hexadecimal digits and not garbage.
This bug goes back to commit 157b243 of Mar 18, 1985, so the bug is
32 years old, and probably the oldest bug that I ever fixed.
I compiled tests/plat/lib/test.c with ack -mcpm, but i80 ncg did emit
wrong code in writehex(uint32_t) for
"0123456789abcdef"[code & 0xf]
The code called '.and' to evaluate `code & 0xf`, then tried to call
'.cii' to narrow the result from 4 to 2 bytes, but it passed garbage
instead of 4 to '.cii'. The rule for '.and' was
pat and defined($1)
kills ALL
uses dereg={const2,$1}
gen Call {label,".and"}
This failed to kill register de={const2,4}, so ncg pushed de,
expecting to push 4, but actually pushing garbage.
Fix such rules using `mvi a,...` or `lxi de,...` so ncg doesn't track
the token in the register. This is like the i86 table. A different
fix would use a dummy instruction `killreg a` or `killreg de` like the
m68020 table.
Also correct 1 to $1 when calling '.exg'.
This breaks all machines because the declared return type void
disagrees with the implicit return type int (when I compile mach.c
with clang). Unbreak i386, i80, i86, m68020, powerpc, vc4 by adding
the return types to mach.c. We don't build any other machines; they
are broken since commit a46ee91 (May 19, 2013) declared void prolog()
and commit fd91851 (Nov 10, 2016) declared void mes(), with both
declarations in mach/proto/ncg/fillem.c.
Also fix mach/vc4/ncg/mach.c where type full is long, so fprintf()
must use "%ld" not "%d" to print full nlocals.