Commit graph

2506 commits

Author SHA1 Message Date
George Koehler a60738a50d Don't use '-' in option string to getopt().
Using '-' might fail on platforms like FreeBSD.  Commit 50a7031
stopped using '-' in the B compiler and ego.  I now stop using '-' in
mcg, because I can now check that mcg still works.
2018-02-05 14:55:10 -05:00
George Koehler 04ac91889c Only lower "addi sp, sp, X" if X > 0.
If X < 0, then lowering the addi might cause the code to use the stack
space before allocating it.  This is a bug because an asynchronous
signal handler can overwrite the unallocated stack space.
2018-02-01 12:20:31 -05:00
George Koehler 9077b3a5ab Teach mcg to pass our tests.
Tests pass if one edits the top build.lua to uncomment "qemuppc" from
both vars.plats and vars.plats_with_tests, and one leaves mcg in
plat/qemuppc/descr.

Add or correct some EM instructions in treebuilder.c:
 - "lof", "stf": handle negative offsets in load() and store().
 - "cuu": add using IR_FROMUI.
 - "lim", "sim": keep an entire word in ".ignmask", to be compatible
   with mach/powerpc/libem/trp.s and ncg.  We also keep a word in
   ".ignmask" in ncg for both i386 and m68020.
 - "trp": pass trap number in register.  See comment in
   helper_function_with_arg().
 - "sig": push the old value of .trppc on the stack.
 - "and ?", "ior ?", "xor ?", "com ?", "cms ?", "set ?", "inn ?":
   connect to helper functions in libem.
 - "blm", "bls": drop call to memmove() and use new helper ".bls4",
   because tests/plat/structcopy_e.c can't call memmove().
 - "xor s", "cms s": if s is large, fall back on helper function.
 - "rol", "ror": add by decomposing each rotate into 4 IR ops.
 - "rck s", "bls s": make fatal unless s is word size.
 - "loi": push multiple loads in the correct order.
 - "dup s", "exg s": if s is large, fall back on helper.
 - "dus": add using new helper ".dus4".
 - "lxl", "lxa": follow the static chain, not the dynamic chain.
 - "lor 1": materialise the stack before pushing the stack pointer.
 - "lor 2", "str 2": make fatal.
 - "los", "sts": drop calls to memcpy() and use helpers ".los4" and
   and ".sts4", so lang/m2/libm2/LtoUset.e starts working.
 - "gto": correctly read descriptor.

Change mach/powerpc/mcg/table:
 - ANY.L: add for "asp -8".
 - LOAD.L: work around register corruption.
 - COMPAREUL.I: add for "cms 8".
2018-01-31 21:05:40 -05:00
George Koehler 3dae9e49cc Use subfic (val - reg) and mulli (reg * val).
In the instruction list, put /* kills xer */ for sraw, srawi, subfic;
and correct the (now unused) "addi." and "lfdu".

Change MACHOPT_F from -m3 to -m2.  This changes the code for 15 * i
from

    slwi r3,r4,4
    subfic r5,r4,0
    add r3,r3,r5

to

    mulli r3,r4,15

If the sequence "slwi subfic addi" takes 3 cycles and 12 bytes, and
mulli takes 3 cycles and 4 bytes, then mulli is better.
2018-01-27 15:53:05 -05:00
George Koehler 7c9c4f82fd Get ack -mosxppc -g to partly work with gdb.
Copy and adapt code from mach/{i386,m68020}/ncg/mach.c to pass the
debugging stabs from EM to assembly.  The next tools (as, led, cv)
already know how to put the stabs in the Mach-o executable.

Modify the function prolog/prologue so gdb uses fp, not sp, for N_LSYM
and N_PSYM stabs.  Simplify prolog() by reducing differences between
stabs and no stabs, and zero and nonzero framesize.  For files without
stabs, the new prolog has the same number of instructions and memory
accesses as the old prolog, and to run at about the same speed on my
PowerPC Mac.

This is enough to see some info for global and local variables in gdb
for Mac OS X.  I still can't get a backtrace; gdb gets confused
because EM and ncg don't link 0(sp) to the previous stack frame.

I don't expect `ack -mlinuxppc -g` to work with gdb for Linux, because
we prepend underscores to the symbol table, which is correct for
Mach-o but wrong for ELF.
2018-01-26 20:19:38 -05:00
George Koehler e83aaca3ec Add some comments before I forget how this stuff works. 2018-01-24 15:17:32 -05:00
George Koehler e3672bd66e Allow sp and fp on the fake stack.
This simplifies parts of the PowerPC table and causes ncg to better
decide whether to push sp or fp to the real stack, or coerce it to
REG3, or coerce it to REG-REG3, or move it to a regvar.  These better
decisions remove extra _mr_ instructions.

The idea comes from mach/powerpc/arm/table, where SP has a property
STACKPOINTER and LB has LOCALBASE.  I don't need two properties, so I
make one property SPFP for both registers.
2018-01-23 18:18:40 -05:00
George Koehler 66f93f08c5 Add fef 4, fif 4. Improve fef 8, fif 8. Other float changes.
When I wrote fef 8, I forgot to test denormalized numbers.  Oops.  Now
fix two of my mistakes:

 - When checking for zero, `extrwi r6, r3, 22, 12` needs to be
   `extrwi r6, r3, 20, 12`.  There are only 20 bits to extract.

 - After the multiplication by 2**64, I forgot to put the fraction in
   [0.5, 1) or (-1, 0.5] by setting IEEE exponent = 1022.

Teach fif 8 about signed zero and NaN.

In ncg/table, change cmf so NaN is not equal to any value, and comment
why ordered comparisons don't work with NaN.  Also add cost for
fctwiz, remove extra `uses REG`.

Edit comment in cfu8.s because the conditional branch might be before
or after fctwiz.
2018-01-22 14:04:15 -05:00
George Koehler 64b50b3a45 Shrink .cfu8
With my PowerBook G4, a program that converts values from 1.0 to
4000000.0 runs in about 0.32s with the old .cfu8 and 0.29s with this
shrunken .cfu8

Leave a comment about other ways to implement .cfu8
2018-01-07 16:03:55 -05:00
George Koehler b90c97b00b Teach top to merge or delete "addi sp, sp, X".
This reduces code size, because ncg emits too many "addi sp, sp, X"
instructions when unstacking things.  Now top lowers "addi sp, sp, X"
by lifting other instructions.  This sometimes creates chances to
merge or delete _addi_ instructions.  If no such chance is found, the
_addi_ remains uselessly lowered.

Edit ncg/table to remove something that top now does.

Edit ncg/mach.c to remove some spaces after commas.  This removes a
whitespace difference between *.s and *.so files, because top removes
the space.
2018-01-05 17:55:50 -05:00
George Koehler 720af48d8a Fix lim. Improve lxl, lxa, lor, str, procs with no locals.
_lim_ must use _loe_ (load word external), not _lde_ (load double-word
external).

The new patterns for _lxl_, _lxa_, _lor_, _str_ emit shorter code in
some cases.  The change from GPR_EXPR to REG_EXPR allows moving
LXFRAME to a register variable.

Add more "reusing" clauses.  We have enough registers that ncg almost
never reuses a register, but sometimes it can reuse r3.

In mach.c, emit one fewer instruction in procedures with no locals.
2018-01-04 20:40:35 -05:00
George Koehler d6938108a6 Add tests for C <setjmp.h> and Modula-2 Semaphores.
Fix PowerPC ncg so setjmp() returns the correct value.  I got unlucky
when ncg picked r3 for "uses REG"; this destroyed the return value in
r3 and caused the new test to fail.
2018-01-03 14:51:14 -05:00
George Koehler 26de4c1ab1 Add test for EM _rck_. Fix traps in PowerPC ncg.
The new test rck_e.e segfaults on PowerPC unless I make some changes.
The inline code for _rck_ was wrong because it didn't allow the trap
handler to return.  _sig_ forgot to push the old trap handler.

Move plat/linuxppc/libsys/trap.s to mach/powerpc/libem/trp.s and
rewrite it with simplified/extended mnemonics.  Remove .trap alias for
.trp procedure.  Add a missing `mtspr lr, r0` so we can return from
the trap handler.  Call write() and _exit() so trp.s works with both
linuxppc and osxppc.  Before, Mac OS X was wrongly using the trap.s
for Linux.

In powerpc/libem, simplify .aar4; teach .csa and .csb to raise the
trap if the default target is zero.

C programs don't need these changes.  You may relink your C programs
with the changed .csa and .csb, but C code doesn't raise the trap.
Modula-2 code can raise traps, so you may want to relink your Modula-2
programs with the changed libem, but you might keep your old .o files
from Modula-2.  You may need to recompile your Pascal programs (delete
old .o files from Pascal) because the Pascal compiler might use _rck_.
2017-12-24 22:37:52 -05:00
George Koehler 5f2a7b260f Optimize mr. X, X after some instructions.
For example, when ncg emits
    slw r9,r8,r5
    mr. r9,r9
then top simplifies the code to
    slw. r9,r8,r5
2017-12-22 22:32:16 -05:00
George Koehler c964eeddba Remove INT32 and such. Adjust indentation.
I understand `loi 4` more easily than `loi INT32`, because `loi 4`
appears in .e files.  So remove INT8, INT16, INT32, INT64.

Add a comment to explain r3 during unconditional jumps.
2017-12-22 21:18:58 -05:00
George Koehler f96f918a29 Generate shorter code for ret 4 and ret 8. 2017-12-22 20:37:39 -05:00
George Koehler 5867ca2f2c Remove two obsolete patterns.
These patterns seem to have no effect on the generated code.
2017-12-22 19:57:42 -05:00
George Koehler 2eeee36f78 Add FRAME_V tokens for local variables.
When storing to a local, stop killing the tokens of other locals,
unless they might overlap with the stored local.  This helps some
procedures that juggle locals when the locals aren't in registers.

Also use FRAME_V tokens for locals in statically enclosing procedures.
Rewrite _lxa_ as _lxl_, to skip the `addi ?,?,8` if we can add 8 to
the next constant.  The PowerPC code from _lxl_ is now sometimes
better, sometimes worse than before.

The i386 table provided the idea to use %size to find overlapping
locals.
2017-12-22 17:04:16 -05:00
George Koehler ad47fa5fe3 Add splitting coercions for IND_ALL_D.
Delete my wrong comment (from commits cfbc537, a8f62f4, 5432bd0) which
claimed that such coercions are not possible.
2017-12-18 20:59:04 -05:00
George Koehler 24abaf6a25 Enable conditional expressions in splitting coercions.
ncgg has parsed the optional conditional expression (optexpr) of each
splitting coercion since commit 72b83cc in 1985; but for almost 33
years, ncg has ignored the expression in c2_expr.

Few tables had conditional coercions (I only found them in arm and
m68020), and no tables had conditional splitting coercions, so this
only becomes a problem now as I try to add a conditional splitting
coercion to powerpc.
2017-12-18 20:39:56 -05:00
George Koehler 5e99baabdf Rename two tokens. CONST_HZ was not hertz (Hz). 2017-12-18 12:36:10 -05:00
George Koehler d8fa9d1b2a In coercions, try to reuse a register with the same token.
This reduces code size.
2017-12-17 12:45:27 -05:00
George Koehler b0d75fed37 Rename ANY_BHW to INT_W; add FLOAT_W, FLOAT_D.
INT_W, the integer set, continues to exclude FSREG, because we can't
easily move FSREG to GPR.

ANY4 becomes ISET+FLOAT_W and ANY8 becomes FLOAT_D.
2017-12-17 11:56:02 -05:00
George Koehler 5ba83100d6 Delete rules for sti 8 with REG IND_RC_D, with REG IND_RR_D.
Prefer the rule with REG FREG, by coercing IND_RC_D or IND_RR_D to
FREG.  This rule looks better to ncg.  When ncg chose between coercion
to REG IND_RC_D or coercion to REG FREG, it chose REG FREG.  It only
chose REG IND_RC_D if the stack had exact REG IND_RC_D.
2017-12-12 13:36:43 -05:00
George Koehler 11a54e0a7c These instructions write to the CR. 2017-12-10 14:01:14 -05:00
George Koehler 504d2aa34e Revise stack shuffles and integer conversions in PowerPC ncg.
Allow asp 4, exg 4 to shuffle tokens without coercing them into
registers; but comment why dup 4, dup 8 coerce tokens into registers.

Allow dup, dus, exg with larger sizes; and add tests dup_e.e and
exg_e.e to check that dup 20, dus, exg 20 work as well in powerpc as
in i80 and i86.

Then powerpc failed to compile loc 2 loc 4 cuu in dup_e.e.  Revise the
integer conversions, so powerpc can compile and pass the test.
2017-12-09 18:57:10 -05:00
George Koehler 48788287b8 Add more chances to put results in register variables.
When a rule `uses REG ... yields %a`, the result %a is always a
temporary, never a regvar.  If the EM code uses _stl_ to put the
result in a regvar, then ncg emits _mr_ to move %a to the regvar.

There are two ways to put the result in the regvar without %a:

  1. Yield a token, as in `yields {MUL_RR, %2, %1}`, so that _stl_
     can move the token to the regvar without using %a.

  2. Provide a pattern, like `sli stl`, that just puts the result
     in `{LOCAL, $2}` and not %a.

Allow some tokens, like SUM_RIS and XEQ, onto the stack; and add
tokens like MUL_RR, and patterns like `sli stl`.

Delete patterns for `stl lol` and `sdl ldl` to avoid an extra
temporary %a when the local is a regvar.  Delete `lal sti lal loi`
because it would emit wrong code.
2017-12-08 17:19:26 -05:00
George Koehler 6b933db90b Split C from CONST.
Rename token CONST to C.  Define set CONST = C + CONST_STACK.  The
instructions with CONST operands can now accept CONST_STACK tokens;
some cases of {CONST, %1.val} become %1.

Also simplify two of _rlwinm_ into _slwi_ and _srwi_.
2017-12-07 19:24:09 -05:00
George Koehler a1d1f38691 Add test for EM rol, ror. Fix i80, i86, powerpc.
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.
2017-12-07 17:16:21 -05:00
George Koehler c95bcac91d Correct the stack pointer when i80 shrinks an integer.
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.
2017-12-07 15:39:41 -05:00
George Koehler 34cf0c8b63 Kill registers a, de, when i80 ncg does Call libem.
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'.
2017-12-06 22:14:00 -05:00
George Koehler 760da1f421 Fix build with gcc.
gcc gave an error because the `char *` parameter doesn't match the
`const char *` in the prototype of regsave().  clang didn't give an
error.  I added the prototype in commit 5301cce.
2017-11-17 17:52:37 -05:00
George Koehler 5301cceee3 Declare machine-dependent functions in mach/proto/ncg
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.
2017-11-13 14:23:44 -05:00
George Koehler e04166b85d More prototypes, less register in mach/proto/ncg
Files that #include "equiv.h" must do so after including "data.h", now
that a function prototype in equiv.h uses type rl_p from data.h.

Adjust style, changing some `for(...)` to `for (...)`.  The style in
mach/proto/ncg is less than consistent; the big annoyance now is that
some files want tabs at 4 spaces, others want tabs at 8 spaces.
2017-11-13 12:44:17 -05:00
George Koehler 909b0d5bf3 Add prototypes to functions in subr.c
Put the declarations in "data.h", because that header declares the
types cost_t and token_p.  Also #include <cgg_cg.h> from "data.h" to
get types c3_p and set_p, and guard <cgg_cg.h> against multiple
inclusion.
2017-11-12 16:11:05 -05:00
George Koehler ba2a45180c Prototypes for string functions. More static. 2017-11-12 11:25:18 -05:00
George Koehler 98b27dd505 Remove old "assert.h" in mach/proto/ncg
*Important:*  You must "make clean" after checking out this commit,
because the build had copied the old "assert.h" to several places in
obj/.  If you don't "make clean", then the compiler finds the old
"assert.h" before libc <assert.h>, and the build fails because this
commit removes badassertion() in subr.c.  After "make clean", the
compiler finds libc <assert.h> and the build succeeds.
2017-11-11 19:35:48 -05:00
George Koehler ac4cbd735e Use libc assert(); fix dependencies; unbreak isduo().
Switch from custom assert() to libc assert() in mach/proto/as.
Continue to disable asserts if DEBUG == 0.

This change found a problem in the build system; comm2.y was missing
depedencies on comm0.h and comm1.h.  Add the missing dependencies to
the cppfile rule.  Allow the dependencies by modifying cppfile in
first/build.lua to act like cfile if t.dir is false.

Now that comm2.y gets rebuilt, I must fix the wrong prototype of
yyparse() in comm1.h.

I got unlucky as induo() in comm5.c was reading beyond the end of the
array.  It found an operator "= " ('=' then space) in the garbage, so
it returned a garbage token number, and "VAR = 123" became a syntax
error.  Unbreak induo() by terminating the array.
2017-11-11 16:09:05 -05:00
George Koehler d347207e60 Add more prototypes in mach/proto/as
Change "register i;" to "int i;" to so clang stops warning about
implicit int.  Use function prototypes so clang stops warning about
implicitly declared functions.
2017-11-10 23:30:46 -05:00
George Koehler 0102cc8934 lwzu writes to the register in the token. 2017-10-19 12:44:46 -04:00
George Koehler 2a92f9bf4d Add a few more error checks and adjustments to reglap.
In util/ncgg, add two more errors for tables using reglap:
 - "Two sizes of reg_float can't be same size"
 - "Missing reg_float of size %d to contain %s"

In mach/proto/ncg, rename macro isregvar_size() to PICK_REGVAR(), so
the macro doesn't look like a function.  This macro sometimes doesn't
evaluate its second argument.

In mach/powerpc/ncg/mach.c, change type of lfs_set to uint32_t, and
change the left shifts from 1U<<regno to (uint32_t)1<<regno, because
1U would be too small for machines with 16-bit int.
2017-10-18 22:00:12 -04:00
George Koehler 73ad5a227d Rename RELOLIS to RELOPPC_LIS.
This relocation is specific to PowerPC.  @davidgiven suggested the
name RELOPPC_LIS in
https://github.com/davidgiven/ack/pull/52#issuecomment-279856501

Reindent the list in h/out.h and util/led/ack.out.5 because
RELOLIS_PPC is a long name.  I use spaces and no tabs because the tabs
looked bad in the manual page.
2017-10-18 15:39:31 -04:00
George Koehler 459a9b5949 Use lwzu, stwu to tighten more loops.
Because lwzu or stwu moves the pointer, I can remove an addi
instruction from the loop, so the loop is slightly faster.

I wrote a benchmark in Modula-2 that exercises some of these loops.  I
measured its time on my old PowerPC Mac.  Its user time decreases from
8.401s to 8.217s with the tighter loops.
2017-10-18 12:12:42 -04:00
George Koehler ac2b0710c8 Add more rules for single-precision reg_float.
The result of single-precision fadds, fsubs, and such can go into a
register variable, like we already do with double precision.  This
avoids an extra fmr from a temporary register to the regvar.
2017-10-17 17:53:03 -04:00
George Koehler 47bd0ef7a7 Stop inlining code to convert integers to floats.
Do the conversion by calling .cif8 or .cuf8 in libem, as it was done
before my commit 1de1e8f.  I used the inline conversion to experiment
with the register allocator, which was too slow until c5bb3be.

Now that libem has the only copy of the code, move some comments and
code changes there.
2017-10-17 17:00:28 -04:00
George Koehler 893e170015 Use my new regvar_w() and regvar_d() in PowerPC ncg.
Rename GPRE to GPR_EXPR, then define FPR_EXPR and FSREG_EXPR.  Use
them for moves to register variables.

Keep "kills regvar($1)", because deleting it and recompiling libc
would cause many failures in my test programs.  Add comment to warn,
  /* ncg fails to infer that regvar($1) is dead! */

Remove "kills LOCAL %off==$1" because it seems to have no effect.
2017-10-17 14:15:33 -04:00
George Koehler 307a8b996e Add regvar_w() and regvar_d() for use with reglap.
If the ncg table uses reglap, then regvar($1, reg_float) would have
two sizes of registers.  An error from ncgg would happen if regvar()
was in a token that allows only one size.  Now one can pick a size
with regvar_w() for word size or regvar_d() for double-word size.

Add regvar_d and regvar_w as keywords in ncgg.  Modify EX_REGVAR to
include the register size.  In ncg, add some checks for the register
size.  In tables without reglap, regvar() works as before, and ncg
ignores the register size in EX_REGVAR.
2017-10-17 12:05:41 -04:00
George Koehler 5432bd03d6 Do a move when coercing FREG to FREG or FSREG to FSREG. 2017-10-16 12:07:55 -04:00
George Koehler f0619ea4ae PowerPC ncg never uses the rules to stack LOCAL or DLOCAL. 2017-10-15 15:22:52 -04:00
George Koehler aa876ff4c2 Fix reglap for procedures that use both sizes of reg_float.
After the RA phase of ego, a procedure may put single-word and
double-word values in the same reg_float.  Then ncg will use both
LOCAL and DLOCAL tokens at the same offset.

I add isregvar_size() to ncg.  It receives the size of the LOCAL or
DLOCAL token, and picks the register of the correct size.  This fixes
a problem where ncg got the wrong-size register and corrupted the
stack.  This problem caused one of my test programs to segfault from
stack underflow.

Also adjust how fixregvars() handles both sizes.
2017-10-15 13:15:03 -04:00