Compare commits

...

141 Commits

Author SHA1 Message Date
Austin Clements
7904e951d4 [dev.power64] liblink: fix Solaris build
a->class is a char.  Boo hoo.

LGTM=minux
R=rsc, minux
CC=golang-codereviews
https://golang.org/cl/169630043
2014-11-14 15:53:15 -05:00
Austin Clements
1222cc4682 [dev.power64] 6g,9g: formatters for Prog and Addr details
The pretty printers for these make it hard to understand
what's actually in the fields of these structures.  These
"ugly printers" show exactly what's in each field, which can
be useful for understanding and debugging code.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/175780043
2014-11-14 13:58:31 -05:00
Austin Clements
a11f256436 [dev.power64] liblink: generate dnames[5689] for D_* constants
This is more complicated than the other enums because the D_*
enums are full of explicit initializers and repeated values.
This tries its best.  (This will get much cleaner once we
tease these constants apart better.)

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/166700043
2014-11-14 12:08:46 -05:00
Austin Clements
5b38501a4f [dev.power64] 5g,6g,8g,9g: debug prints for regopt pass 6 and paint2
Theses were very helpful in understanding the regions and
register selection when porting regopt to 9g.  Add them to the
other compilers (and improve 9g's successor debug print).

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/174130043
2014-11-14 11:56:31 -05:00
Austin Clements
9e7bed88cd [dev.power64] 5g,6g,8g: synchronize documentation for regopt structures
I added several comments to the regopt-related structures when
porting it to 9g.  Synchronize those comments back in to the
other compilers.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/175720043
2014-11-14 11:07:33 -05:00
Austin Clements
743bdf612a [dev.power64] 9g: implement regopt
This adds registerization support to 9g equivalent to what the
other compilers have.

LGTM=rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/174980043
2014-11-13 13:51:44 -05:00
Austin Clements
231b8d61e9 [dev.power64] 9l: remove enum as's tag for c2go
None of the other compilers have a tag for this enum.
Cleaning all of this up to use proper types will happen after
the conversion.

LGTM=minux, rsc
R=rsc, minux
CC=golang-codereviews
https://golang.org/cl/166690043
2014-11-13 13:48:59 -05:00
Austin Clements
c3dadb3d19 [dev.power64] 6g,8g: remove unnecessary and incorrect reg use scanning
Previously, the 6g and 8g registerizers scanned for used
registers beyond the end of a region being considered for
registerization.  This ancient artifact was copied from the C
compilers, where it was probably necessary to track implicitly
used registers.  In the Go compilers it's harmless (because it
can only over-restrict the set of available registers), but no
longer necessary because the Go compilers correctly track
register use/set information.  The consequences of this extra
scan were (at least) that 1) we would not consider allocating
the AX register if there was a deferproc call in the future
because deferproc uses AX as a return register, so we see the
use of AX, but don't track that AX is set by the CALL, and 2)
we could not consider allocating the DX register if there was
a MUL in the future because MUL implicitly sets DX and (thanks
to an abuse of copyu in this code) we would also consider DX
used.

This commit fixes these problems by nuking this code.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/174110043
2014-11-13 13:34:20 -05:00
Austin Clements
8c060d9392 [dev.power64] liblink: improve documentation of struct Prog
LGTM=dave, rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/169460043
2014-11-12 17:19:02 -05:00
Austin Clements
60f66aa817 [dev.power64] 9g: proginfo fixes
For D_OREG addresses, store the used registers in regindex
instead of reguse because they're really part of addressing.

Add implicit register use/set for DUFFZERO/DUFFCOPY.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/174050044
2014-11-12 14:58:43 -05:00
Austin Clements
c1e8c57c3d [dev.power64] 9g: fix width check and width calculation for OADDR
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/174970043
2014-11-12 14:16:49 -05:00
Austin Clements
7739533f61 [dev.power64] 5g: fix mistaken bit-wise AND in regopt
Replace a bit-wise AND with a logical one.  This happened to
work before because bany returns 0 or 1, but the intent here
is clearly logical (and this makes 5g match with 6g and 8g).

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/172850043
2014-11-07 10:43:55 -05:00
Austin Clements
e156f0e997 [dev.power64] 5g: fix etype and width of itable Addrs
For OITAB nodes, 5g's naddr was setting the wrong etype and
failing to set the width of the resulting Addr.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/171220043
2014-11-06 15:35:53 -05:00
Austin Clements
22c929f538 [dev.power64] 9g: fix addr width calculation; enable MOV* width check
9g's naddr was missing assignments to a->width in several
cases, so the optimizer was getting bogus width information.
Add them.

This correct width information also lets us enable the width
check in gins for MOV*.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/167310043
2014-11-06 14:41:44 -05:00
Austin Clements
f45fd5753c [dev.power64] gc: fix etype of strings
The etype of references to strings was being incorrectly set
to TINT32 on all platforms.  Change it to TSTRING.  It seems
this doesn't matter for compilation, since x86 uses LEA
instructions to load string addresses and arm and power64
disassemble the string into its constituent pieces (with the
correct types), but it helps when debugging.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/170100043
2014-11-06 14:37:39 -05:00
Austin Clements
4f81684f86 [dev.power64] 6g: don't create variables for indirect addresses
Previously, mkvar treated, for example, 0(AX) the same as AX.
As a result, a move to an indirect address would be marked as
*setting* the register, rather than just using it, resulting
in unnecessary register moves.  Fix this by not producing
variables for indirect addresses.

LGTM=rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/164610043
2014-11-05 15:36:47 -05:00
Austin Clements
fa32e922d5 [dev.power64] gc: convert Bits to a uint64 array
So far all of our architectures have had at most 32 registers,
so we've been able to use entry 0 in the Bits uint32 array
directly as a register mask.  Power64 has 64 registers, so
this converts Bits to a uint64 array so we can continue to use
entry 0 directly as a register mask on Power64.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/169060043
2014-11-04 16:34:56 -05:00
Austin Clements
a5e1e1599c [dev.power64] test: "fix" live.go test on power64x
On power64x, this one line in live.go reports that t is live
because of missing optimization passes.  This isn't what this
test is trying to test, so shuffle bad40 so that it still
accomplishes the intent of the test without also depending on
optimization.

LGTM=rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/167110043
2014-11-03 17:25:36 -05:00
Austin Clements
d10a115ef9 [dev.power64] test: disable nilptr3 test on power64x
The remaining failures in this test are because of incomplete
optimization support on power64x.  Tracked in issue 9058.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/168130043
2014-11-03 17:25:03 -05:00
Austin Clements
473bfae5ae [dev.power64] liblink: fix printing of branch targets
Print PC stored in target Prog* of branch instructions when
available instead of the offset stored in the branch
instruction.  The offset tends to be wrong after code
transformations, so previously this led to confusing listings.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/168980043
2014-11-03 17:24:13 -05:00
Austin Clements
810019286f [dev.power64] 9g: fix nilopt
Previously, nilopt was disabled on power64x because it threw
away "seemly random segments of code."  Indeed, excise on
power64x failed to preserve the link field, so it excised not
only the requested instruction but all following instructions
in the function.  Fix excise to retain the link field while
otherwise zeroing the instruction.

This makes nilopt safe on power64x.  It still fails
nilptr3.go's tests for removal of repeated nil checks because
those depend on also optimizing away repeated loads, which
doesn't currently happen on power64x.

LGTM=dave, rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/168120043
2014-11-03 15:48:51 -05:00
Austin Clements
31b1207fde [dev.power64] all: merge default into dev.power64
Trivial merge except for src/runtime/asm_power64x.s and
src/runtime/signal_power64x.c

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/168950044
2014-11-03 10:53:11 -05:00
Dave Cheney
84f7ac98f7 [dev.power64] cmd/objdump: disable tests on power64/power64le
LGTM=rsc, austin
R=austin, rsc, bradfitz
CC=golang-codereviews
https://golang.org/cl/164300043
2014-11-02 11:23:41 +11:00
Austin Clements
e1db508ffd [dev.power64] runtime: fix gcinfo_test on power64x
The GC info masks for slices and strings were changed in
commit caab29a25f68, but the reference masks used by
gcinfo_test for power64x hadn't caught up.  Now they're
identical to amd64, so this CL fixes this test by combining
the reference masks for these platforms.

LGTM=rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/162620044
2014-10-31 16:58:12 -04:00
Austin Clements
700ab16daf [dev.power64] reflect: fix asm on power64x
reflect/asm_power64x.s was missing changes made to other
platforms for stack maps.  This CL ports those changes.  With
this fix, the reflect test passes on power64x.

LGTM=rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/170870043
2014-10-31 15:29:03 -04:00
Austin Clements
40a5b3ecb1 [dev.power64] runtime: fix fastrand1 on power64x
fastrand1 depends on testing the high bit of its uint32 state.
For efficiency, all of the architectures implement this as a
sign bit test.  However, on power64, fastrand1 was using a
64-bit sign test on the zero-extended 32-bit state.  This
always failed, causing fastrand1 to have very short periods
and often decay to 0 and get stuck.

Fix this by using a 32-bit signed compare instead of a 64-bit
compare.  This fixes various tests for the randomization of
select of map iteration.

LGTM=rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/166990043
2014-10-31 13:39:36 -04:00
Austin Clements
6e86003651 [dev.power64] 9g: fix under-zeroing in clearfat
All three cases of clearfat were wrong on power64x.

The cases that handle 1032 bytes and up and 32 bytes and up
both use MOVDU (one directly generated in a loop and the other
via duffzero), which leaves the pointer register pointing at
the *last written* address.  The generated code was not
accounting for this, so the byte fill loop was re-zeroing the
last zeroed dword, rather than the bytes following the last
zeroed dword.  Fix this by simply adding an additional 8 byte
offset to the byte zeroing loop.

The case that handled under 32 bytes was also wrong.  It
didn't update the pointer register at all, so the byte zeroing
loop was simply re-zeroing the beginning of region.  Again,
the fix is to add an offset to the byte zeroing loop to
account for this.

LGTM=dave, bradfitz
R=rsc, dave, bradfitz
CC=golang-codereviews
https://golang.org/cl/168870043
2014-10-31 11:08:27 -04:00
Austin Clements
c24156bafe [dev.power64] runtime: fix a syntax error that slipped in to asm_power64x.s
Apparently I had already moved on to fixing another problem
when I submitted CL 169790043.

LGTM=dave
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/165210043
2014-10-30 16:44:42 -04:00
Austin Clements
8a09639ae8 [dev.power64] runtime: make asm_power64x.s go vet-clean
No real problems found.  Just lots of argument names that
didn't quite match up.

LGTM=rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/169790043
2014-10-30 15:58:30 -04:00
Austin Clements
4cf28a11e3 [dev.power64] runtime: fix out-of-date comment in panic
LGTM=bradfitz
R=rsc, bradfitz
CC=golang-codereviews
https://golang.org/cl/162500043
2014-10-30 12:08:21 -04:00
Austin Clements
36d417c0e3 [dev.power64] runtime: test CAS on large unsigned 32-bit numbers
This adds a test to runtime·check to ensure CAS of large
unsigned 32-bit numbers does not accidentally sign-extend its
arguments.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/162490044
2014-10-30 11:17:26 -04:00
Austin Clements
097362fd2e [dev.power64] runtime: match argument/return type signedness in power64x assembly
Previously, the power64x runtime assembly was sloppy about
using sign-extending versus zero-extending moves of arguments
and return values.  I think all of the cases that actually
mattered have been fixed in recent CLs; this CL fixes up the
few remaining mismatches.

LGTM=rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/162480043
2014-10-30 10:45:41 -04:00
Russ Cox
599199fd9f [dev.power64] all: merge default (dd5014ed9b01) into dev.power64
Still passes on amd64.

LGTM=austin
R=austin
CC=golang-codereviews
https://golang.org/cl/165110043
2014-10-29 11:45:01 -04:00
Russ Cox
b55791e200 [dev.power64] cmd/5a, cmd/6a, cmd/8a, cmd/9a: make labels function-scoped
I removed support for jumping between functions years ago,
as part of doing the instruction layout for each function separately.

Given that, it makes sense to treat labels as function-scoped.
This lets each function have its own 'loop' label, for example.

Makes the assembly much cleaner and removes the last
reason anyone would reach for the 123(PC) form instead.

Note that this is on the dev.power64 branch, but it changes all
the assemblers. The change will ship in Go 1.5 (perhaps after
being ported into the new assembler).

Came up as part of CL 167730043.

LGTM=r
R=r
CC=austin, dave, golang-codereviews, minux
https://golang.org/cl/159670043
2014-10-28 21:50:16 -04:00
Austin Clements
87b4149b22 [dev.power64] runtime: fix atomicor8 for power64x
Power64 servers do not currently support sub-word size atomic
memory access, so atomicor8 uses word size atomic access.
However, previously atomicor8 made no attempt to align this
access, resulting in errors.  Fix this by aligning the pointer
to a word boundary and shifting the value appropriately.
Since atomicor8 is used in GC, add a test to runtime·check to
make sure this doesn't break in the future.

This also fixes an incorrect branch label, an incorrectly
sized argument move, and adds argument names to help go vet.

LGTM=rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/165820043
2014-10-28 15:57:33 -04:00
Austin Clements
c8f50b298c [dev.power64] 9a: correct generation of four argument ops
The "to" field was the penultimate argument to outgcode,
instead of the last argument, which swapped the third and
fourth operands.  The argument order was correct in a.y, so
just swap the meaning of the arguments in outgcode.  This
hadn't come up because we hadn't used these more obscure
operations in any hand-written assembly until now.

LGTM=rsc, dave
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/160690043
2014-10-28 15:08:09 -04:00
Austin Clements
c2364b58cc [dev.power64] liblink: emit wrapper code in correct place
The wrapper code was being emitted before the stack
reservation, rather than after.

LGTM=rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/161540043
2014-10-28 10:14:19 -04:00
Dave Cheney
cb4f5e1970 [dev.power64] runtime: fix cas64 on power64x
cas64 was jumping to the wrong offset.

LGTM=minux, rsc
R=rsc, austin, minux
CC=golang-codereviews
https://golang.org/cl/158710043
2014-10-28 11:15:48 +11:00
Dave Cheney
1b130a08d8 [dev.power64] runtime: fix power64le build
Brings defs_linux_power64le.h up to date with the big endian version.

LGTM=rsc
R=rsc, austin
CC=golang-codereviews
https://golang.org/cl/161470043
2014-10-28 09:56:33 +11:00
Austin Clements
062e354c84 [dev.power64] runtime: power64 fixes and ports of changes
Fix include paths that got moved in the great pkg/ rename.  Add
missing runtime/arch_* files for power64.  Port changes that
happened on default since branching to
runtime/{asm,atomic,sys_linux}_power64x.s (precise stacks,
calling convention change, various new and deleted functions.
Port struct renaming and fix some bugs in
runtime/defs_linux_power64.h.

LGTM=rsc
R=rsc, dave
CC=golang-codereviews
https://golang.org/cl/161450043
2014-10-27 17:27:03 -04:00
Austin Clements
6be0c8a566 [dev.power64] liblink: fix lost branch target
A recent commit lost the branch target in the really-big-stack
case of splitstack, causing an infinite loop stack preempt
case.  Revive the branch target.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/157790044
2014-10-27 17:19:41 -04:00
Austin Clements
5a653089ef [dev.power64] all: merge default into dev.power64
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/164110043
2014-10-27 17:17:06 -04:00
Austin Clements
32c75a2d3d [dev.power64] liblink: power64 fixes and ports of changes
Ports of platform-specific changes that happened on default
after dev.power64 forked (fixes for c2go, wrapper math fixes,
moved stackguard field, stackguard1 support, precise stacks).
Bug fixes (missing AMOVW in instruction table, correct
unsigned 32-bit remainder).

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/164920044
2014-10-27 15:25:40 -04:00
Austin Clements
93341e8664 [dev.power64] cc: 8-byte align argument size on power64
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/163370043
2014-10-27 15:10:54 -04:00
Austin Clements
11ec8ab5cb [dev.power64] liblink: print line numbers in disassembly on power64
Matching other platforms.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/161320043
2014-10-24 11:39:01 -04:00
Dave Cheney
a08783f078 [dev.power64] runtime: fix SigaltstackT definition for power64le
Also updated defs3_linux.go but had to manually edit defs_linux_power64le.h. Will regenerate the file when cgo is working natively on ppc64.

LGTM=austin
R=rsc, austin
CC=golang-codereviews
https://golang.org/cl/158360043
2014-10-23 08:58:10 +11:00
Austin Clements
a9b9ecc9ef [dev.power64] runtime: fix early GC of Defer objects
go_bootstrap was panicking during runtime initialization
(under runtime.main) because Defer objects were being
prematurely GC'd.  This happened because of an incorrect
change to runtime·unrollgcprog_m to make it endian-agnostic
during the conversion of runtime bitmaps to byte arrays.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/161960044
2014-10-22 16:39:31 -04:00
Austin Clements
f0bd539c59 [dev.power64] all: merge default into dev.power64
This brings dev.power64 up-to-date with the current tip of
default.  go_bootstrap is still panicking with a bad defer
when initializing the runtime (even on amd64).

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/152570049
2014-10-22 15:51:54 -04:00
Austin Clements
977fba763a [dev.power64] runtime: Fix broken merge of noasm.go
The earlier dev.power64 merge missed the port of
runtime/noasm.goc to runtime/noasm_arm.go.  This CL fixes this
by moving noasm_arm.go to noasm.go and adding a +build to
share the file between arm and power64.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/158350043
2014-10-22 14:02:04 -04:00
Austin Clements
2bd616b1a7 build: merge the great pkg/ rename into dev.power64
This also removes pkg/runtime/traceback_lr.c, which was ported
to Go in an earlier commit and then moved to
runtime/traceback.go.

Reviewer: rsc@golang.org
          rsc: LGTM
2014-10-22 13:25:37 -04:00
Austin Clements
3208250185 [dev.power64] build: merge default into dev.power64
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/160200044
2014-10-22 11:21:16 -04:00
Russ Cox
04d5796b29 [dev.power64] liblink: recognize add instruction as adjusting SP
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/128360043
2014-08-18 22:24:15 -04:00
Shenghou Ma
d0be55a662 [dev.power64] liblink: fix g->panicwrap update code generation
LGTM=rsc
R=golang-codereviews, rsc
CC=golang-codereviews
https://golang.org/cl/123400043
2014-08-15 15:31:54 -04:00
Russ Cox
e445f75dbc [dev.power64] runtime: fix usleep not to smash saved LR
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/130760043
2014-08-15 15:28:08 -04:00
Russ Cox
fd21b9f8b5 [dev.power64] runtime: make all bitmaps arrays of bytes
The "simpler faster garbage collector" is full of little-endian assumptions.
Instead of trying to correct all the mistakes, just give in and make
everything use bytes.

LGTM=minux
R=minux
CC=dvyukov, golang-codereviews
https://golang.org/cl/124400043
2014-08-15 15:22:33 -04:00
Dave Cheney
f9fdc887ae [dev.power64] runtime: define page size on power64le systems to be 64k
Fixes #8495.

CL 128260043 updated the definition of syscall.GetPageSize to report 64k for power64 and power64le. This CL cleans up the last place where the page size was defined as 4k.

LGTM=minux
R=rsc, minux
CC=golang-codereviews
https://golang.org/cl/123520043
2014-08-15 13:15:24 +10:00
Russ Cox
249e8f700a [dev.power64] runtime: fix RuntimeGogoBytes on power64
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/130030043
2014-08-14 16:34:28 -04:00
Russ Cox
ed68c7df55 [dev.power64] cmd/ld, runtime: detect, fix nosplit overflows
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/121690043
2014-08-14 15:29:37 -04:00
Russ Cox
6edd1c6d1a [dev.power64] syscall: fix power64 page size
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/128260043
2014-08-14 15:29:05 -04:00
Russ Cox
0bee7f3a17 [dev.power64] reflect: fix test not to hang even if TrySend lies
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/124360043
2014-08-14 14:35:00 -04:00
Russ Cox
25d4d75376 [dev.power64] cmd/dist: tell goc2c that power64 is 64-bit system
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/125300043
2014-08-14 14:34:48 -04:00
Russ Cox
aa739b8d03 [dev.power64] cmd/9g: correct floating point comparison
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/129210043
2014-08-14 14:34:37 -04:00
Russ Cox
ecbe6b9f7f [dev.power64] runtime: replace getproccount with simpler code
This runs once. There is no need for inscrutable algorithms.
Also it doesn't compile correctly with 9c.

LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/130000043
2014-08-14 14:34:25 -04:00
Russ Cox
25bde37af4 [dev.power64] cmd/9c: fix constant truncation in optimizer
This is what broke getpopcount, but that code had it coming.

LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/130000044
2014-08-14 14:34:14 -04:00
Shenghou Ma
80e76e272a [dev.power64] test/nosplit.go: add power64 support
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/125210043
2014-08-14 13:59:58 -04:00
Shenghou Ma
b3375771fc [dev.power64] runtime: don't fault on runtime.procyield, just return
LGTM=dave, rsc
R=rsc, iant, dave
CC=golang-codereviews
https://golang.org/cl/128230044
2014-08-14 12:01:27 -04:00
Shenghou Ma
7776b0a1cc [dev.power64] syscall: re-generate using cgo compiled by gc, fix test failures
LGTM=dave, rsc
R=rsc, iant, dave
CC=golang-codereviews
https://golang.org/cl/127320043
2014-08-14 12:01:21 -04:00
Shenghou Ma
f464573c70 [dev.power64] runtime: add power64/power64le as supported arch to gcinfo_test.go
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/122560043
2014-08-14 12:01:14 -04:00
Shenghou Ma
5f02073ded [dev.power64] runtime: fix time.now
Was reading a uint64 field with a MOVW, which has endian issues.

LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/122550043
2014-08-14 11:59:58 -04:00
Shenghou Ma
b697c120f6 [dev.power64] reflect: now we find one big endian machine
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/124350043
2014-08-14 11:59:52 -04:00
Russ Cox
4f557008e8 [dev.power64] liblink: fix $large(SP) for floating point load/store
Fixes test/cmplxdivide.

LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/128190045
2014-08-14 11:57:10 -04:00
Russ Cox
76b1ddbb96 [dev.power64] liblink: fix handling of $nnn(reg)
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/126180043
2014-08-13 18:32:54 -04:00
Russ Cox
ba9a11e557 [dev.power64] liblink: fix handling of MOVD with large constants
LGTM=minux
R=golang-codereviews, minux
CC=golang-codereviews
https://golang.org/cl/122540043
2014-08-13 18:14:13 -04:00
Russ Cox
b7a6fd28db [dev.power64] runtime: fix reflect.call
The code to copy out the results was incorrect.

LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/122530043
2014-08-13 16:26:43 -04:00
Russ Cox
404472e50b [dev.power64] runtime: fix C prototype for cmallocgc
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/122520043
2014-08-13 15:50:06 -04:00
Russ Cox
27e657ef68 [dev.power64] cmd/9g: fix floating-point comparison for NaN
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/127300043
2014-08-13 15:49:19 -04:00
Shenghou Ma
f3f332851f [dev.power64] cmd/9g: add missing break
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/125260043
2014-08-13 15:49:07 -04:00
Shenghou Ma
856124a1cd [dev.power64] runtime: fix build
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/128180044
2014-08-13 14:52:11 -04:00
Russ Cox
ebf42035b7 [dev.power64] runtime: fix newstackcall
moreframesize is a uint32, not a uint64.

LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/124310043
2014-08-13 14:52:01 -04:00
Russ Cox
6e73ae88b5 [dev.power64] cmd/9l, math/big, runtime, syscall: fixes for power64
On the machine I'm using, the hardware page size seems to be 64 kB.
Make ELF rounding and mmap quantum 64 kB to match.

Error numbers returned from kernel are positive; do not negate.

Implement stubs for math/big.

LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/124300043
2014-08-13 14:36:29 -04:00
Shenghou Ma
f285537b7f [dev.power64] cmd/9g: do not ignore move instructions even if from and to are samaddr()
Those moves might be significant (e.g. narrowing or widening): on Power64,
we don't distinguish between MOVWD and MOVW.

This fixes divmode.go and bug447.go.

LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/125200043
2014-08-13 11:39:07 -04:00
Shenghou Ma
b6d6eb21ec [dev.power64] runtime: switch back to old initial stack size, and disable debugging messages for rewindmorestack
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/129850044
2014-08-13 01:23:00 -04:00
Shenghou Ma
f375c0eb0d [dev.power64] liblink: rewrite MOVD $con(Ra), Rb into ADD $con, Ra, Rb; fix stack split prologue
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/129050043
2014-08-13 01:22:47 -04:00
Shenghou Ma
372b5cebe7 [dev.power64] cmd/9g: use loops to do memmove in sgen()
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/128130044
2014-08-13 01:22:34 -04:00
Shenghou Ma
bc8d35a9cf [dev.power64] cmd/cc: round argsize to multiples of wordsize on power64
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/121640043
2014-08-13 01:22:21 -04:00
Shenghou Ma
268d901199 [dev.power64] runtime: fix morestack
Must not save LR.

LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/129040044
2014-08-12 23:57:42 -04:00
Shenghou Ma
893f28ca16 [dev.power64] cmd/9g: introduce ginscon2 for CMP/CMPU, use ginscon to ADD constants
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/125170043
2014-08-12 23:57:02 -04:00
Shenghou Ma
9b88857f75 [dev.power64] runtime: disable GC and use a larger default stack
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/128120043
2014-08-12 22:28:25 -04:00
Shenghou Ma
f0393221a7 [dev.power64] cmd/9g: clear p->reg for ATEXT
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/125150043
2014-08-12 22:25:43 -04:00
Shenghou Ma
dbf406a9d8 [dev.power64] cmd/gc: disable magic multiply optimizations for now
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/126110043
2014-08-12 22:07:15 -04:00
Shenghou Ma
05d670f757 [dev.power64] liblink: disable stack split for now
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/122460043
2014-08-12 21:56:20 -04:00
Shenghou Ma
c229cec23a [dev.power64] runtime: implemnt runtime.switchtoM and runtime.onM
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/129860043
2014-08-12 21:55:43 -04:00
Shenghou Ma
ca7f2c796f [dev.power64] reflect: add assembly stubs
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/126090043
2014-08-12 21:43:31 -04:00
Russ Cox
53b78c84bc [dev.power64] cmd/9a: use new flag parser
Copy main from 6a. Fixes various things, but the
main thing is the use of the new flag parser.
The go command expects to be able to use -trimpath
and not have it be interpreted as -t rimpath.

LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/126100043
2014-08-12 21:41:42 -04:00
Russ Cox
27627fd8ed [dev.power64] hash/crc32: use portable castagnoli on power64
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/128110044
2014-08-12 21:38:50 -04:00
Shenghou Ma
3e4dfdad34 [dev.power64] cmd/9g, cmd/gc, cmd/ld: fix build.
1. disable nonsplit stack overflow check
2. disable OLROT recognition
3. emit correct instructions for adding offsets to an address

LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/123310043
2014-08-12 21:22:27 -04:00
Shenghou Ma
860f941e7f [dev.power64] cmd/9c: fix endian issue in integer to floating point conversion
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/129850043
2014-08-12 20:58:05 -04:00
Shenghou Ma
560cf4c6de [dev.power64] cmd/9l: remove MAXIO (fix build)
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/124270043
2014-08-12 20:57:54 -04:00
Shenghou Ma
f4529adabe [dev.power64] liblink: support stack split, long conditional branches
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/123300043
2014-08-12 20:57:45 -04:00
Shenghou Ma
5e4989cf0a [dev.power64] cmd/gc: handle thechar=='9', disable nilopt() for now
LGTM=rsc
R=rsc, iant, dave
CC=golang-codereviews
https://golang.org/cl/121630043
2014-08-12 20:57:32 -04:00
Shenghou Ma
b1c9a8bce3 [dev.power64] cmd/9g: implement zerorange
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/121540043
2014-08-12 19:51:01 -04:00
Shenghou Ma
56949d33d8 [dev.power64] sync/atomic: implement for asm_power64x.s
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/124220043
2014-08-12 19:50:51 -04:00
Shenghou Ma
e7e668d717 [dev.power64] math: implement Abs, add power64/power64le forwarding assembly functions
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/119670043
2014-08-12 19:50:40 -04:00
Shenghou Ma
ab29d5b4ae [dev.power64] runtime: add defs3_linux.go to generate defs_linux_power64{,le}.h
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/128070043
2014-08-12 19:50:30 -04:00
Shenghou Ma
91447ab502 [dev.power64] runtime: auto-generated headers for linux/power64 and linux/power64le
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/123280043
2014-08-12 19:50:18 -04:00
Shenghou Ma
fb57459b48 [dev.power64] runtime: move noasm_arm.goc to noasm.goc
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/121590043
2014-08-12 19:50:03 -04:00
Shenghou Ma
2abf3c5583 [dev.power64] runtime: changes to the portable part for linux/power64 and linux/power64le
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/121580044
2014-08-12 19:49:52 -04:00
Shenghou Ma
f2d43ec7cd [dev.power64] os/signal: support for linux/power64 and linux/power64le
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/121580043
2014-08-12 19:49:41 -04:00
Shenghou Ma
c74a4d4add [dev.power64] syscall: script changes for power64
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/123290043
2014-08-12 19:49:31 -04:00
Shenghou Ma
e0aaf2b2db [dev.power64] syscall: auto-generated source for linux/power64 and linux/power64le.
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/127170043
2014-08-12 19:49:18 -04:00
Shenghou Ma
f3e2023764 [dev.power64] syscall: the manually written parts for linux/power64 and linux/power64le
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/129800043
2014-08-12 19:49:03 -04:00
Shenghou Ma
5f691cfaf1 [dev.power64] runtime: manually written parts for linux/power64 and linux/power64le, checkpoint
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/122430043
2014-08-12 19:48:49 -04:00
Shenghou Ma
4928b2074b [dev.power64] cmd/9g: first check point
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/123170043
2014-08-11 23:44:55 -04:00
Shenghou Ma
552d8b79dd [dev.power64] cmd/9l/9.out.h: introduce NFREG, REGG, REGRT1 and REGRT2
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/125990043
2014-08-11 23:44:38 -04:00
Shenghou Ma
1a1d450712 [dev.power64] cmd/9l: introduce the power64 linker, based loosely on 5l
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/123940043
2014-08-11 23:44:23 -04:00
Shenghou Ma
6e692b35bb [dev.power64] cmd/cgo: add {ppc,power}64{,le} to pointer and int size maps
LGTM=rsc
R=rsc, iant, dave
CC=golang-codereviews
https://golang.org/cl/119640043
2014-08-11 23:43:51 -04:00
Shenghou Ma
059d089fc0 [dev.power64] debug/elf: add power64 support along with relocation test
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/125910043
2014-08-11 23:43:34 -04:00
Shenghou Ma
5cb7da7547 [dev.power64] syscall: remove duplicated constants
Without this CL, simply running mkall.sh for Linux will generate duplicated constants
for termios. I verified that after this CL, mkall.sh will generate almost identical
z* files for linux/amd64.

LGTM=rsc
R=rsc, iant, r
CC=golang-codereviews
https://golang.org/cl/124990043
2014-08-11 23:43:15 -04:00
Shenghou Ma
8881e032d4 [dev.power64] runtime: ignore rt_sigaction error if it's for SIGRTMAX.
Workaround a qemu linux user space emulation bug.
ref: http://git.qemu.org/?p=qemu.git;a=blob;f=linux-user/signal.c;h=1141054be2170128d6f7a340b41484b49a255936;hb=HEAD#l82

LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/124900043
2014-08-11 23:32:33 -04:00
Shenghou Ma
26c9bbf736 [dev.power64] runtime: rename traceback_arm.c to traceback_lr.c
Also make it more portable by not hardcoding pointer sizes.

LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/127780043
2014-08-11 23:32:08 -04:00
Shenghou Ma
40d7a6d582 [dev.power64] cmd/ld: add MAXIO back in lib.h
It was accidentally removed.

LGTM=dave
R=rsc, iant, dave
CC=golang-codereviews
https://golang.org/cl/124880043
2014-08-11 23:31:28 -04:00
Shenghou Ma
05d72029db [dev.power64] cmd/9c: add Makefile
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/121370043
2014-08-07 18:41:37 -04:00
Shenghou Ma
5b0ac5f76e [dev.power64] liblink: handle $i64. symbols, add debug output for -S -v, show rel addend in hex for RISC arches
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/127770043
2014-08-07 18:41:09 -04:00
Shenghou Ma
6e02e1cfc2 [dev.power64] cmd/ld: update for power64
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/121380043
2014-08-07 18:36:42 -04:00
Shenghou Ma
95e8a3a1da [dev.power64] cmd/9c: fix switch bug
The cmd/cc bundled with 9c has additional code compared to our cmd/cc, and
without those code, 9c couldn't handle switch statement where the expression
is not just a simple int32 or int64 variable (e.g. g->status or int8 variable).

All credit goes to rsc.

LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/125840043
2014-08-07 18:34:25 -04:00
Shenghou Ma
4be75c8f26 [dev.power64] include/link.h, liblink: convert 9l functions to liblink
This replaces CL 122990043.

LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/123010043
2014-08-07 15:13:25 -04:00
Shenghou Ma
7c33e5078f [dev.power64] cmd/9l: update header files for liblink
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/128720044
2014-08-07 14:56:59 -04:00
Shenghou Ma
bcf7f61f83 [dev.power64] cmd/9a: use liblink, add required additional instructions.
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/127730043
2014-08-07 14:49:41 -04:00
Shenghou Ma
fcb842c645 [dev.power64] .hgignore: update for the 9 toolchain
LGTM=dave, rsc
R=rsc, iant, dave
CC=golang-codereviews
https://golang.org/cl/124840043
2014-08-07 14:37:00 -04:00
Shenghou Ma
83f6aadf16 [dev.power64] cmd/9c: use liblink, use Go argument passing rules, support both endians
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/126800043
2014-08-07 14:36:34 -04:00
Shenghou Ma
2358603f0c [dev.power64] liblink: move span and asmout related function from obj9.c to asm9.c
To reduce delta for the upcoming liblink CL.
Just code movement, no semantic changes.

LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/124830043
2014-08-07 12:02:36 -04:00
Shenghou Ma
c689eb9b21 [dev.power64] cmd/dist: power64/power64le support.
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/117670045
2014-08-06 23:59:14 -04:00
Shenghou Ma
7582ecc996 [dev.power64] cmd/9g: add doc.go to prevent build failures.
After CL 117670045, cmd/dist will expect to have a cmd/9g directory.

LGTM=rsc, dave
R=rsc, iant, dave
CC=golang-codereviews
https://golang.org/cl/126780043
2014-08-06 23:43:36 -04:00
Shenghou Ma
117b1d4685 [dev.power64] cmd/9a, cmd/9c, cmd/9l, liblink: import code from Vita Nuova.
No modifications other than adding copyright header to each file, and
concatenating several cmd/9l files together to form the liblink files.

LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/123840043
2014-08-06 23:41:29 -04:00
Shenghou Ma
9512e470e1 [dev.power64] cmd/dist: recognize power64 and power64le as GOHOSTARCH
LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/125760043
2014-08-06 16:16:28 -04:00
Russ Cox
ffb07c0e6c [dev.power64] all: merge default, for codereview update
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/124820043
2014-08-06 16:15:22 -04:00
Russ Cox
245ed93c20 all: merge default, for codereview fixes
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/124810043
2014-08-06 15:36:24 -04:00
Russ Cox
bd69b4479a cmd/dist: generate anames9.c
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/120690043
2014-08-06 15:12:08 -04:00
Russ Cox
ccd880f290 cmd/dist, go/build: add power64, power64le to known GOARCH lists
LGTM=dave, minux, aram
R=minux, dave, bradfitz, aram
CC=golang-codereviews
https://golang.org/cl/119470043
2014-08-06 14:58:17 -04:00
Russ Cox
8ad746d226 [dev.power64] remove dummy file 2014-08-06 14:57:34 -04:00
Russ Cox
dc2bb6d061 [dev.power64] create dev branch 2014-08-06 14:56:58 -04:00
177 changed files with 41196 additions and 3103 deletions

View File

@@ -2,13 +2,13 @@ syntax:glob
.DS_Store
.git
.gitignore
*.[568ao]
*.a[568o]
*.[5689ao]
*.a[5689o]
*.so
*.pyc
._*
.nfs.*
[568a].out
[5689a].out
*~
*.orig
*.rej

View File

@@ -54,7 +54,7 @@ struct Addr
{
char sval[8];
float64 dval;
Prog* branch; // for 5g, 6g, 8g
Prog* branch; // for 5g, 6g, 8g, 9g
} u;
LSym* sym;
@@ -62,9 +62,9 @@ struct Addr
short type;
uint8 index;
int8 scale;
int8 reg; // for 5l
int8 name; // for 5l
int8 class; // for 5l
int8 reg; // for 5l, 9l
int8 name; // for 5l, 9l
int8 class; // for 5l, 9l
uint8 etype; // for 5g, 6g, 8g
int32 offset2; // for 5l, 8l
struct Node* node; // for 5g, 6g, 8g
@@ -89,9 +89,13 @@ struct Prog
int32 lineno;
Prog* link;
short as;
uchar reg; // arm only
uchar scond; // arm only
uchar scond; // arm only; condition codes
// operands
Addr from;
uchar reg; // arm, power64 only (e.g., ADD from, reg, to);
// also used for ADATA width on arm, power64
Addr from3; // power64 only (e.g., RLWM/FMADD from, reg, from3, to)
Addr to;
// for 5g, 6g, 8g internal use
@@ -103,11 +107,11 @@ struct Prog
Prog* comefrom; // 6l, 8l
Prog* pcrel; // 5l
int32 spadj;
uchar mark;
uint16 mark;
uint16 optab; // 5l, 9l
uchar back; // 6l, 8l
uchar ft; /* 6l, 8l oclass cache */
uchar tt; // 6l, 8l
uint16 optab; // 5l
uchar isize; // 6l, 8l
char width; /* fake for DATA */
@@ -233,10 +237,12 @@ enum
enum
{
R_ADDR = 1,
R_ADDRPOWER, // relocation for loading 31-bit address using addis and addi/ld/st for Power
R_SIZE,
R_CALL, // relocation for direct PC-relative call
R_CALLARM, // relocation for ARM direct call
R_CALLIND, // marker for indirect call (no actual relocating necessary)
R_CALLPOWER, // relocation for Power direct call
R_CONST,
R_PCREL,
R_TLS,
@@ -529,6 +535,9 @@ void span6(Link *ctxt, LSym *s);
// asm8.c
void span8(Link *ctxt, LSym *s);
// asm9.c
void span9(Link *ctxt, LSym *s);
// data.c
vlong addaddr(Link *ctxt, LSym *s, LSym *t);
vlong addaddrplus(Link *ctxt, LSym *s, LSym *t, vlong add);
@@ -576,10 +585,11 @@ Prog* copyp(Link*, Prog*);
Prog* appendp(Link*, Prog*);
vlong atolwhex(char*);
// list[568].c
// list[5689].c
void listinit5(void);
void listinit6(void);
void listinit8(void);
void listinit9(void);
// obj.c
int linklinefmt(Link *ctxt, Fmt *fp);
@@ -611,20 +621,29 @@ char* headstr(int);
extern char* anames5[];
extern char* anames6[];
extern char* anames8[];
extern char* anames9[];
extern char* cnames5[];
extern char* cnames9[];
extern char* dnames5[];
extern char* dnames6[];
extern char* dnames8[];
extern char* dnames9[];
extern LinkArch link386;
extern LinkArch linkamd64;
extern LinkArch linkamd64p32;
extern LinkArch linkarm;
extern LinkArch linkpower64;
extern LinkArch linkpower64le;
#pragma varargck type "A" int
#pragma varargck type "D" Addr*
#pragma varargck type "lD" Addr*
#pragma varargck type "P" Prog*
#pragma varargck type "R" int
#pragma varargck type "^" int
#pragma varargck type "^" int // for 5l/9l, C_* classes (liblink internal)
// TODO(ality): remove this workaround.
// It's here because Pconv in liblink/list?.c references %L.

View File

@@ -1 +1,2 @@
defaultcc: golang-codereviews@googlegroups.com
contributors: http://go.googlecode.com/hg/CONTRIBUTORS

View File

@@ -3603,11 +3603,17 @@ class MercurialVCS(VersionControlSystem):
if use_hg_shell:
base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath], silent_ok=True)
else:
base_content = str(self.repo[base_rev][oldrelpath].data())
try:
base_content = str(self.repo[base_rev][oldrelpath].data())
except Exception:
pass
is_binary = "\0" in base_content # Mercurial's heuristic
if status != "R":
new_content = open(relpath, "rb").read()
is_binary = is_binary or "\0" in new_content
try:
new_content = open(relpath, "rb").read()
is_binary = is_binary or "\0" in new_content
except Exception:
pass
if is_binary and base_content and use_hg_shell:
# Fetch again without converting newlines
base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath],

View File

@@ -67,6 +67,7 @@ struct Sym
int32 value;
ushort type;
char *name;
char* labelname;
char sym;
};
#define S ((Sym*)0)
@@ -136,6 +137,8 @@ void newio(void);
void newfile(char*, int);
Sym* slookup(char*);
Sym* lookup(void);
Sym* labellookup(Sym*);
void settext(LSym*);
void syminit(Sym*);
int32 yylex(void);
int getc(void);

View File

@@ -73,15 +73,11 @@ prog:
line
line:
LLAB ':'
{
if($1->value != pc)
yyerror("redeclaration of %s", $1->name);
$1->value = pc;
}
line
| LNAME ':'
LNAME ':'
{
$1 = labellookup($1);
if($1->type == LLAB && $1->value != pc)
yyerror("redeclaration of %s", $1->labelname);
$1->type = LLAB;
$1->value = pc;
}
@@ -218,18 +214,21 @@ inst:
*/
| LTYPEB name ',' imm
{
settext($2.sym);
$4.type = D_CONST2;
$4.offset2 = ArgsSizeUnknown;
outcode($1, Always, &$2, 0, &$4);
}
| LTYPEB name ',' con ',' imm
{
settext($2.sym);
$6.type = D_CONST2;
$6.offset2 = ArgsSizeUnknown;
outcode($1, Always, &$2, $4, &$6);
}
| LTYPEB name ',' con ',' imm '-' con
{
settext($2.sym);
$6.type = D_CONST2;
$6.offset2 = $8;
outcode($1, Always, &$2, $4, &$6);
@@ -373,15 +372,10 @@ rel:
}
| LNAME offset
{
$1 = labellookup($1);
$$ = nullgen;
if(pass == 2)
yyerror("undefined label: %s", $1->name);
$$.type = D_BRANCH;
$$.offset = $2;
}
| LLAB offset
{
$$ = nullgen;
if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->labelname);
$$.type = D_BRANCH;
$$.offset = $1->value + $2;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,24 @@
/* A Bison parser, made by GNU Bison 2.7.12-4996. */
/* A Bison parser, made by GNU Bison 2.3. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@@ -26,20 +29,10 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef YY_YY_Y_TAB_H_INCLUDED
# define YY_YY_Y_TAB_H_INCLUDED
/* Enabling traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
#if YYDEBUG
extern int yydebug;
#endif
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@@ -148,41 +141,24 @@ extern int yydebug;
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
{
/* Line 2053 of yacc.c */
#line 39 "a.y"
{
Sym *sym;
int32 lval;
double dval;
char sval[8];
Addr addr;
/* Line 2053 of yacc.c */
#line 166 "y.tab.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
}
/* Line 1529 of yacc.c. */
#line 157 "y.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE yylval;
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
int yyparse (void *YYPARSE_PARAM);
#else
int yyparse ();
#endif
#else /* ! YYPARSE_PARAM */
#if defined __STDC__ || defined __cplusplus
int yyparse (void);
#else
int yyparse ();
#endif
#endif /* ! YYPARSE_PARAM */
#endif /* !YY_YY_Y_TAB_H_INCLUDED */

View File

@@ -86,7 +86,7 @@ datagostring(Strlit *sval, Addr *a)
sym = stringsym(sval->s, sval->len);
a->type = D_OREG;
a->name = D_EXTERN;
a->etype = TINT32;
a->etype = TSTRING;
a->offset = 0; // header
a->reg = NREG;
a->sym = linksym(sym);

View File

@@ -1353,9 +1353,10 @@ naddr(Node *n, Addr *a, int canemitcode)
case OITAB:
// itable of interface value
naddr(n->left, a, canemitcode);
a->etype = TINT32;
a->etype = simtype[tptr];
if(a->type == D_CONST && a->offset == 0)
break; // len(nil)
a->width = widthptr;
break;
case OSPTR:

View File

@@ -63,8 +63,8 @@ enum
uint32 BLOAD(Reg*);
uint32 BSTORE(Reg*);
uint32 LOAD(Reg*);
uint32 STORE(Reg*);
uint64 LOAD(Reg*);
uint64 STORE(Reg*);
*/
// A Reg is a wrapper around a single Prog (one instruction) that holds
@@ -75,12 +75,18 @@ struct Reg
{
Flow f;
Bits set; // variables written by this instruction.
Bits use1; // variables read by prog->from.
Bits use2; // variables read by prog->to.
Bits set; // regopt variables written by this instruction.
Bits use1; // regopt variables read by prog->from.
Bits use2; // regopt variables read by prog->to.
// refahead/refbehind are the regopt variables whose current
// value may be used in the following/preceding instructions
// up to a CALL (or the value is clobbered).
Bits refbehind;
Bits refahead;
// calahead/calbehind are similar, but for variables in
// instructions that are reachable after hitting at least one
// CALL.
Bits calbehind;
Bits calahead;
Bits regdiff;
@@ -93,6 +99,16 @@ struct Reg
#define NRGN 600
/*c2go enum { NRGN = 600 }; */
// A Rgn represents a single regopt variable over a region of code
// where a register could potentially be dedicated to that variable.
// The code encompassed by a Rgn is defined by the flow graph,
// starting at enter, flood-filling forward while varno is refahead
// and backward while varno is refbehind, and following branches. A
// single variable may be represented by multiple disjoint Rgns and
// each Rgn may choose a different register for that variable.
// Registers are allocated to regions greedily in order of descending
// cost.
struct Rgn
{
Reg* enter;
@@ -144,8 +160,8 @@ void prop(Reg*, Bits, Bits);
void synch(Reg*, Bits);
uint32 allreg(uint32, Rgn*);
void paint1(Reg*, int);
uint32 paint2(Reg*, int);
void paint3(Reg*, int, int32, int);
uint32 paint2(Reg*, int, int);
void paint3(Reg*, int, uint32, int);
void addreg(Adr*, int);
void dumpit(char *str, Flow *r0, int);
@@ -156,10 +172,10 @@ void peep(Prog*);
void excise(Flow*);
int copyu(Prog*, Adr*, Adr*);
int32 RtoB(int);
int32 FtoB(int);
int BtoR(int32);
int BtoF(int32);
uint32 RtoB(int);
uint32 FtoB(int);
int BtoR(uint32);
int BtoF(uint32);
/*
* prog.c
@@ -187,16 +203,16 @@ enum
SizeF = 1<<7, // float aka float32
SizeD = 1<<8, // double aka float64
// Left side: address taken, read, write.
// Left side (Prog.from): address taken, read, write.
LeftAddr = 1<<9,
LeftRead = 1<<10,
LeftWrite = 1<<11,
// Register in middle; never written.
// Register in middle (Prog.reg); only ever read.
RegRead = 1<<12,
CanRegRead = 1<<13,
// Right side: address taken, read, write.
// Right side (Prog.to): address taken, read, write.
RightAddr = 1<<14,
RightRead = 1<<15,
RightWrite = 1<<16,

View File

@@ -35,7 +35,7 @@
#include "opt.h"
#define NREGVAR 32
#define REGBITS ((uint32)0xffffffff)
#define REGBITS ((uint64)0xffffffffull)
/*c2go enum {
NREGVAR = 32,
REGBITS = 0xffffffff,
@@ -86,7 +86,7 @@ setaddrs(Bits bit)
i = bnum(bit);
node = var[i].node;
n = var[i].name;
bit.b[i/32] &= ~(1L<<(i%32));
biclr(&bit, i);
// disable all pieces of that variable
for(i=0; i<nvar; i++) {
@@ -393,7 +393,7 @@ loop2:
for(z=0; z<BITS; z++)
bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
if(bany(&bit) & !r->f.refset) {
if(bany(&bit) && !r->f.refset) {
// should never happen - all variables are preset
if(debug['w'])
print("%L: used and not set: %Q\n", r->f.prog->lineno, bit);
@@ -425,7 +425,7 @@ loop2:
if(debug['R'] > 1)
print("\n");
paint1(r, i);
bit.b[i/32] &= ~(1L<<(i%32));
biclr(&bit, i);
if(change <= 0) {
if(debug['R'])
print("%L $%d: %Q\n",
@@ -454,9 +454,13 @@ brk:
* replace code (paint3)
*/
rgp = region;
if(debug['R'] && debug['v'])
print("\nregisterizing\n");
for(i=0; i<nregion; i++) {
if(debug['R'] && debug['v'])
print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
bit = blsh(rgp->varno);
vreg = paint2(rgp->enter, rgp->varno);
vreg = paint2(rgp->enter, rgp->varno, 0);
vreg = allreg(vreg, rgp);
if(debug['R']) {
if(rgp->regno >= NREG)
@@ -477,9 +481,6 @@ brk:
rgp++;
}
if(debug['R'] && debug['v'])
dumpit("pass6", &firstr->f, 1);
/*
* free aux structures. peep allocates new ones.
*/
@@ -488,6 +489,15 @@ brk:
flowend(g);
firstr = R;
if(debug['R'] && debug['v']) {
// Rebuild flow graph, since we inserted instructions
g = flowstart(firstp, sizeof(Reg));
firstr = (Reg*)g->start;
dumpit("pass6", &firstr->f, 1);
flowend(g);
firstr = R;
}
/*
* pass 7
* peep-hole on basic block
@@ -570,7 +580,7 @@ walkvardef(Node *n, Reg *r, int active)
break;
for(v=n->opt; v!=nil; v=v->nextinnode) {
bn = v - var;
r1->act.b[bn/32] |= 1L << (bn%32);
biset(&r1->act, bn);
}
if(r1->f.prog->as == ABL)
break;
@@ -606,7 +616,7 @@ addsplits(void)
~(r->calahead.b[z] & addrs.b[z]);
while(bany(&bit)) {
i = bnum(bit);
bit.b[i/32] &= ~(1L << (i%32));
biclr(&bit, i);
}
}
}
@@ -972,10 +982,10 @@ prop(Reg *r, Bits ref, Bits cal)
for(z=0; z<BITS; z++) {
if(cal.b[z] == 0)
continue;
for(i=0; i<32; i++) {
if(z*32+i >= nvar || ((cal.b[z]>>i)&1) == 0)
for(i=0; i<64; i++) {
if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
continue;
v = var+z*32+i;
v = var+z*64+i;
if(v->node->opt == nil) // v represents fixed register, not Go variable
continue;
@@ -991,10 +1001,10 @@ prop(Reg *r, Bits ref, Bits cal)
// This will set the bits at most twice, keeping the overall loop linear.
v1 = v->node->opt;
j = v1 - var;
if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
if(v == v1 || !btest(&cal, j)) {
for(; v1 != nil; v1 = v1->nextinnode) {
j = v1 - var;
cal.b[j/32] |= 1<<(j&31);
biset(&cal, j);
}
}
}
@@ -1115,10 +1125,10 @@ paint1(Reg *r, int bn)
Reg *r1;
Prog *p;
int z;
uint32 bb;
uint64 bb;
z = bn/32;
bb = 1L<<(bn%32);
z = bn/64;
bb = 1LL<<(bn%64);
if(r->act.b[z] & bb)
return;
for(;;) {
@@ -1189,14 +1199,14 @@ paint1(Reg *r, int bn)
}
uint32
paint2(Reg *r, int bn)
paint2(Reg *r, int bn, int depth)
{
Reg *r1;
int z;
uint32 bb, vreg;
uint64 bb, vreg;
z = bn/32;
bb = 1L << (bn%32);
z = bn/64;
bb = 1LL << (bn%64);
vreg = regbits;
if(!(r->act.b[z] & bb))
return vreg;
@@ -1213,6 +1223,9 @@ paint2(Reg *r, int bn)
r = r1;
}
for(;;) {
if(debug['R'] && debug['v'])
print(" paint2 %d %P\n", depth, r->f.prog);
r->act.b[z] &= ~bb;
vreg |= r->regu;
@@ -1220,14 +1233,14 @@ paint2(Reg *r, int bn)
if(r->refbehind.b[z] & bb)
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
if(r1->refahead.b[z] & bb)
vreg |= paint2(r1, bn);
vreg |= paint2(r1, bn, depth+1);
if(!(r->refahead.b[z] & bb))
break;
r1 = (Reg*)r->f.s2;
if(r1 != R)
if(r1->refbehind.b[z] & bb)
vreg |= paint2(r1, bn);
vreg |= paint2(r1, bn, depth+1);
r = (Reg*)r->f.s1;
if(r == R)
break;
@@ -1240,15 +1253,15 @@ paint2(Reg *r, int bn)
}
void
paint3(Reg *r, int bn, int32 rb, int rn)
paint3(Reg *r, int bn, uint32 rb, int rn)
{
Reg *r1;
Prog *p;
int z;
uint32 bb;
uint64 bb;
z = bn/32;
bb = 1L << (bn%32);
z = bn/64;
bb = 1LL << (bn%64);
if(r->act.b[z] & bb)
return;
for(;;) {
@@ -1333,7 +1346,7 @@ addreg(Adr *a, int rn)
* 10 R10
* 12 R12
*/
int32
uint32
RtoB(int r)
{
if(r >= REGTMP-2 && r != 12) // excluded R9 and R10 for m and g, but not R12
@@ -1342,8 +1355,10 @@ RtoB(int r)
}
int
BtoR(int32 b)
BtoR(uint32 b)
{
// TODO Allow R0 and R1, but be careful with a 0 return
// TODO Allow R9. Only R10 is reserved now (just g, not m).
b &= 0x11fcL; // excluded R9 and R10 for m and g, but not R12
if(b == 0)
return 0;
@@ -1357,7 +1372,7 @@ BtoR(int32 b)
* ... ...
* 31 F15
*/
int32
uint32
FtoB(int f)
{
@@ -1367,7 +1382,7 @@ FtoB(int f)
}
int
BtoF(int32 b)
BtoF(uint32 b)
{
b &= 0xfffc0000L;
@@ -1442,12 +1457,14 @@ dumpit(char *str, Flow *r0, int isreg)
print(" (only)");
print("\n");
}
// r1 = r->s1;
// if(r1 != nil) {
// print(" succ:");
// for(; r1 != R; r1 = r1->s1)
// print(" %.4ud", (int)r1->prog->pc);
// print("\n");
// }
// Print successors if it's not just the next one
if(r->s1 != r->link || r->s2 != nil) {
print(" succ:");
if(r->s1 != nil)
print(" %.4ud", (int)r->s1->prog->pc);
if(r->s2 != nil)
print(" %.4ud", (int)r->s2->prog->pc);
print("\n");
}
}
}

View File

@@ -338,6 +338,8 @@ enum
D_STATIC = (D_NONE+4),
D_AUTO = (D_NONE+5),
D_PARAM = (D_NONE+6),
D_LAST = (D_NONE+26),
};
/*

View File

@@ -70,6 +70,7 @@ struct Sym
vlong value;
ushort type;
char *name;
char* labelname;
char sym;
};
#define S ((Sym*)0)
@@ -148,6 +149,8 @@ void newio(void);
void newfile(char*, int);
Sym* slookup(char*);
Sym* lookup(void);
Sym* labellookup(Sym*);
void settext(LSym*);
void syminit(Sym*);
int32 yylex(void);
int getc(void);

View File

@@ -71,15 +71,11 @@ prog:
line
line:
LLAB ':'
{
if($1->value != pc)
yyerror("redeclaration of %s", $1->name);
$1->value = pc;
}
line
| LNAME ':'
LNAME ':'
{
$1 = labellookup($1);
if($1->type == LLAB && $1->value != pc)
yyerror("redeclaration of %s (%s)", $1->labelname, $1->name);
$1->type = LLAB;
$1->value = pc;
}
@@ -197,11 +193,13 @@ spec1: /* DATA */
spec2: /* TEXT */
mem ',' imm2
{
settext($1.sym);
$$.from = $1;
$$.to = $3;
}
| mem ',' con ',' imm2
{
settext($1.sym);
$$.from = $1;
$$.from.scale = $3;
$$.to = $5;
@@ -363,15 +361,10 @@ rel:
}
| LNAME offset
{
$1 = labellookup($1);
$$ = nullgen;
if(pass == 2)
yyerror("undefined label: %s", $1->name);
$$.type = D_BRANCH;
$$.offset = $2;
}
| LLAB offset
{
$$ = nullgen;
if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->labelname);
$$.type = D_BRANCH;
$$.offset = $1->value + $2;
}

File diff suppressed because it is too large Load Diff

View File

@@ -81,7 +81,7 @@ datagostring(Strlit *sval, Addr *a)
a->sym = linksym(sym);
a->node = sym->def;
a->offset = 0; // header
a->etype = TINT32;
a->etype = TSTRING;
}
void

View File

@@ -63,8 +63,8 @@ enum
uint32 BLOAD(Reg*);
uint32 BSTORE(Reg*);
uint32 LOAD(Reg*);
uint32 STORE(Reg*);
uint64 LOAD(Reg*);
uint64 STORE(Reg*);
*/
// A Reg is a wrapper around a single Prog (one instruction) that holds
@@ -75,12 +75,18 @@ struct Reg
{
Flow f;
Bits set; // variables written by this instruction.
Bits use1; // variables read by prog->from.
Bits use2; // variables read by prog->to.
Bits set; // regopt variables written by this instruction.
Bits use1; // regopt variables read by prog->from.
Bits use2; // regopt variables read by prog->to.
// refahead/refbehind are the regopt variables whose current
// value may be used in the following/preceding instructions
// up to a CALL (or the value is clobbered).
Bits refbehind;
Bits refahead;
// calahead/calbehind are similar, but for variables in
// instructions that are reachable after hitting at least one
// CALL.
Bits calbehind;
Bits calahead;
Bits regdiff;
@@ -93,6 +99,16 @@ struct Reg
#define NRGN 600
/*c2go enum { NRGN = 600 }; */
// A Rgn represents a single regopt variable over a region of code
// where a register could potentially be dedicated to that variable.
// The code encompassed by a Rgn is defined by the flow graph,
// starting at enter, flood-filling forward while varno is refahead
// and backward while varno is refbehind, and following branches. A
// single variable may be represented by multiple disjoint Rgns and
// each Rgn may choose a different register for that variable.
// Registers are allocated to regions greedily in order of descending
// cost.
struct Rgn
{
Reg* enter;
@@ -140,8 +156,8 @@ void prop(Reg*, Bits, Bits);
void synch(Reg*, Bits);
uint32 allreg(uint32, Rgn*);
void paint1(Reg*, int);
uint32 paint2(Reg*, int);
void paint3(Reg*, int, int32, int);
uint32 paint2(Reg*, int, int);
void paint3(Reg*, int, uint32, int);
void addreg(Adr*, int);
void dumpone(Flow*, int);
void dumpit(char*, Flow*, int);
@@ -153,10 +169,10 @@ void peep(Prog*);
void excise(Flow*);
int copyu(Prog*, Adr*, Adr*);
int32 RtoB(int);
int32 FtoB(int);
int BtoR(int32);
int BtoF(int32);
uint32 RtoB(int);
uint32 FtoB(int);
int BtoR(uint32);
int BtoF(uint32);
/*
* prog.c
@@ -165,8 +181,8 @@ typedef struct ProgInfo ProgInfo;
struct ProgInfo
{
uint32 flags; // the bits below
uint32 reguse; // required registers used by this instruction
uint32 regset; // required registers set by this instruction
uint32 reguse; // registers implicitly used by this instruction
uint32 regset; // registers implicitly set by this instruction
uint32 regindex; // registers used by addressing mode
};
@@ -187,12 +203,12 @@ enum
SizeF = 1<<7, // float aka float32
SizeD = 1<<8, // double aka float64
// Left side: address taken, read, write.
// Left side (Prog.from): address taken, read, write.
LeftAddr = 1<<9,
LeftRead = 1<<10,
LeftWrite = 1<<11,
// Right side: address taken, read, write.
// Right side (Prog.to): address taken, read, write.
RightAddr = 1<<12,
RightRead = 1<<13,
RightWrite = 1<<14,

View File

@@ -34,7 +34,7 @@
#include "opt.h"
#define NREGVAR 32 /* 16 general + 16 floating */
#define REGBITS ((uint32)0xffffffff)
#define REGBITS ((uint64)0xffffffffull)
/*c2go enum {
NREGVAR = 32,
REGBITS = 0xffffffff,
@@ -71,7 +71,7 @@ setaddrs(Bits bit)
i = bnum(bit);
node = var[i].node;
n = var[i].name;
bit.b[i/32] &= ~(1L<<(i%32));
biclr(&bit, i);
// disable all pieces of that variable
for(i=0; i<nvar; i++) {
@@ -364,7 +364,7 @@ loop2:
rgp->varno = i;
change = 0;
paint1(r, i);
bit.b[i/32] &= ~(1L<<(i%32));
biclr(&bit, i);
if(change <= 0)
continue;
rgp->cost = change;
@@ -389,9 +389,13 @@ brk:
* replace code (paint3)
*/
rgp = region;
if(debug['R'] && debug['v'])
print("\nregisterizing\n");
for(i=0; i<nregion; i++) {
if(debug['R'] && debug['v'])
print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
bit = blsh(rgp->varno);
vreg = paint2(rgp->enter, rgp->varno);
vreg = paint2(rgp->enter, rgp->varno, 0);
vreg = allreg(vreg, rgp);
if(rgp->regno != 0) {
if(debug['R'] && debug['v']) {
@@ -406,9 +410,6 @@ brk:
rgp++;
}
if(debug['R'] && debug['v'])
dumpit("pass6", &firstr->f, 1);
/*
* free aux structures. peep allocates new ones.
*/
@@ -417,6 +418,15 @@ brk:
flowend(g);
firstr = R;
if(debug['R'] && debug['v']) {
// Rebuild flow graph, since we inserted instructions
g = flowstart(firstp, sizeof(Reg));
firstr = (Reg*)g->start;
dumpit("pass6", &firstr->f, 1);
flowend(g);
firstr = R;
}
/*
* pass 7
* peep-hole on basic block
@@ -477,7 +487,7 @@ walkvardef(Node *n, Reg *r, int active)
break;
for(v=n->opt; v!=nil; v=v->nextinnode) {
bn = v - var;
r1->act.b[bn/32] |= 1L << (bn%32);
biset(&r1->act, bn);
}
if(r1->f.prog->as == ACALL)
break;
@@ -621,6 +631,9 @@ mkvar(Reg *r, Adr *a)
if(r != R)
r->use1.b[0] |= doregbits(a->index);
if(t >= D_INDIR && t < 2*D_INDIR)
goto none;
switch(t) {
default:
regu = doregbits(t);
@@ -822,10 +835,10 @@ prop(Reg *r, Bits ref, Bits cal)
for(z=0; z<BITS; z++) {
if(cal.b[z] == 0)
continue;
for(i=0; i<32; i++) {
if(z*32+i >= nvar || ((cal.b[z]>>i)&1) == 0)
for(i=0; i<64; i++) {
if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
continue;
v = var+z*32+i;
v = var+z*64+i;
if(v->node->opt == nil) // v represents fixed register, not Go variable
continue;
@@ -841,10 +854,10 @@ prop(Reg *r, Bits ref, Bits cal)
// This will set the bits at most twice, keeping the overall loop linear.
v1 = v->node->opt;
j = v1 - var;
if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
if(v == v1 || !btest(&cal, j)) {
for(; v1 != nil; v1 = v1->nextinnode) {
j = v1 - var;
cal.b[j/32] |= 1UL<<(j&31);
biset(&cal, j);
}
}
}
@@ -959,10 +972,10 @@ paint1(Reg *r, int bn)
{
Reg *r1;
int z;
uint32 bb;
uint64 bb;
z = bn/32;
bb = 1L<<(bn%32);
z = bn/64;
bb = 1LL<<(bn%64);
if(r->act.b[z] & bb)
return;
for(;;) {
@@ -1017,54 +1030,14 @@ paint1(Reg *r, int bn)
}
uint32
regset(Reg *r, uint32 bb)
{
uint32 b, set;
Adr v;
int c;
set = 0;
v = zprog.from;
while(b = bb & ~(bb-1)) {
v.type = b & 0xFFFF? BtoR(b): BtoF(b);
if(v.type == 0)
fatal("zero v.type for %#ux", b);
c = copyu(r->f.prog, &v, nil);
if(c == 3)
set |= b;
bb &= ~b;
}
return set;
}
uint32
reguse(Reg *r, uint32 bb)
{
uint32 b, set;
Adr v;
int c;
set = 0;
v = zprog.from;
while(b = bb & ~(bb-1)) {
v.type = b & 0xFFFF? BtoR(b): BtoF(b);
c = copyu(r->f.prog, &v, nil);
if(c == 1 || c == 2 || c == 4)
set |= b;
bb &= ~b;
}
return set;
}
uint32
paint2(Reg *r, int bn)
paint2(Reg *r, int bn, int depth)
{
Reg *r1;
int z;
uint32 bb, vreg, x;
uint64 bb, vreg;
z = bn/32;
bb = 1L << (bn%32);
z = bn/64;
bb = 1LL << (bn%64);
vreg = regbits;
if(!(r->act.b[z] & bb))
return vreg;
@@ -1081,6 +1054,9 @@ paint2(Reg *r, int bn)
r = r1;
}
for(;;) {
if(debug['R'] && debug['v'])
print(" paint2 %d %P\n", depth, r->f.prog);
r->act.b[z] &= ~bb;
vreg |= r->regu;
@@ -1088,14 +1064,14 @@ paint2(Reg *r, int bn)
if(r->refbehind.b[z] & bb)
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
if(r1->refahead.b[z] & bb)
vreg |= paint2(r1, bn);
vreg |= paint2(r1, bn, depth+1);
if(!(r->refahead.b[z] & bb))
break;
r1 = (Reg*)r->f.s2;
if(r1 != R)
if(r1->refbehind.b[z] & bb)
vreg |= paint2(r1, bn);
vreg |= paint2(r1, bn, depth+1);
r = (Reg*)r->f.s1;
if(r == R)
break;
@@ -1105,27 +1081,19 @@ paint2(Reg *r, int bn)
break;
}
bb = vreg;
for(; r; r=(Reg*)r->f.s1) {
x = r->regu & ~bb;
if(x) {
vreg |= reguse(r, x);
bb |= regset(r, x);
}
}
return vreg;
}
void
paint3(Reg *r, int bn, int32 rb, int rn)
paint3(Reg *r, int bn, uint32 rb, int rn)
{
Reg *r1;
Prog *p;
int z;
uint32 bb;
uint64 bb;
z = bn/32;
bb = 1L << (bn%32);
z = bn/64;
bb = 1LL << (bn%64);
if(r->act.b[z] & bb)
return;
for(;;) {
@@ -1198,7 +1166,7 @@ addreg(Adr *a, int rn)
ostats.ncvtreg++;
}
int32
uint32
RtoB(int r)
{
@@ -1208,7 +1176,7 @@ RtoB(int r)
}
int
BtoR(int32 b)
BtoR(uint32 b)
{
b &= 0xffffL;
if(nacl)
@@ -1224,7 +1192,7 @@ BtoR(int32 b)
* ...
* 31 X15
*/
int32
uint32
FtoB(int f)
{
if(f < D_X0 || f > D_X15)
@@ -1233,7 +1201,7 @@ FtoB(int f)
}
int
BtoF(int32 b)
BtoF(uint32 b)
{
b &= 0xFFFF0000L;
@@ -1304,12 +1272,14 @@ dumpit(char *str, Flow *r0, int isreg)
print(" %.4ud", (int)r1->prog->pc);
print("\n");
}
// r1 = r->s1;
// if(r1 != R) {
// print(" succ:");
// for(; r1 != R; r1 = r1->s1)
// print(" %.4ud", (int)r1->prog->pc);
// print("\n");
// }
// Print successors if it's not just the next one
if(r->s1 != r->link || r->s2 != nil) {
print(" succ:");
if(r->s1 != nil)
print(" %.4ud", (int)r->s1->prog->pc);
if(r->s2 != nil)
print(" %.4ud", (int)r->s2->prog->pc);
print("\n");
}
}
}

View File

@@ -865,6 +865,8 @@ enum
D_INDIR, /* additive */
D_LAST,
T_TYPE = 1<<0,
T_INDEX = 1<<1,
T_OFFSET = 1<<2,

View File

@@ -70,6 +70,7 @@ struct Sym
int32 value;
ushort type;
char *name;
char* labelname;
char sym;
};
#define S ((Sym*)0)
@@ -148,6 +149,8 @@ void newio(void);
void newfile(char*, int);
Sym* slookup(char*);
Sym* lookup(void);
Sym* labellookup(Sym*);
void settext(LSym*);
void syminit(Sym*);
int32 yylex(void);
int getc(void);

View File

@@ -74,15 +74,11 @@ prog:
line
line:
LLAB ':'
{
if($1->value != pc)
yyerror("redeclaration of %s", $1->name);
$1->value = pc;
}
line
| LNAME ':'
LNAME ':'
{
$1 = labellookup($1);
if($1->type == LLAB && $1->value != pc)
yyerror("redeclaration of %s", $1->labelname);
$1->type = LLAB;
$1->value = pc;
}
@@ -199,11 +195,13 @@ spec1: /* DATA */
spec2: /* TEXT */
mem ',' imm2
{
settext($1.sym);
$$.from = $1;
$$.to = $3;
}
| mem ',' con ',' imm2
{
settext($1.sym);
$$.from = $1;
$$.from.scale = $3;
$$.to = $5;
@@ -362,15 +360,10 @@ rel:
}
| LNAME offset
{
$1 = labellookup($1);
$$ = nullgen;
if(pass == 2)
yyerror("undefined label: %s", $1->name);
$$.type = D_BRANCH;
$$.offset = $2;
}
| LLAB offset
{
$$ = nullgen;
if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->labelname);
$$.type = D_BRANCH;
$$.offset = $1->value + $2;
}

File diff suppressed because it is too large Load Diff

View File

@@ -81,7 +81,7 @@ datagostring(Strlit *sval, Addr *a)
a->sym = linksym(sym);
a->node = sym->def;
a->offset = 0; // header
a->etype = TINT32;
a->etype = TSTRING;
}
void

View File

@@ -63,8 +63,8 @@ enum
uint32 BLOAD(Reg*);
uint32 BSTORE(Reg*);
uint32 LOAD(Reg*);
uint32 STORE(Reg*);
uint64 LOAD(Reg*);
uint64 STORE(Reg*);
*/
// A Reg is a wrapper around a single Prog (one instruction) that holds
@@ -75,12 +75,18 @@ struct Reg
{
Flow f;
Bits set; // variables written by this instruction.
Bits use1; // variables read by prog->from.
Bits use2; // variables read by prog->to.
Bits set; // regopt variables written by this instruction.
Bits use1; // regopt variables read by prog->from.
Bits use2; // regopt variables read by prog->to.
// refahead/refbehind are the regopt variables whose current
// value may be used in the following/preceding instructions
// up to a CALL (or the value is clobbered).
Bits refbehind;
Bits refahead;
// calahead/calbehind are similar, but for variables in
// instructions that are reachable after hitting at least one
// CALL.
Bits calbehind;
Bits calahead;
Bits regdiff;
@@ -106,6 +112,16 @@ struct Reg
#define NRGN 600
/*c2go enum { NRGN = 600 }; */
// A Rgn represents a single regopt variable over a region of code
// where a register could potentially be dedicated to that variable.
// The code encompassed by a Rgn is defined by the flow graph,
// starting at enter, flood-filling forward while varno is refahead
// and backward while varno is refbehind, and following branches. A
// single variable may be represented by multiple disjoint Rgns and
// each Rgn may choose a different register for that variable.
// Registers are allocated to regions greedily in order of descending
// cost.
struct Rgn
{
Reg* enter;
@@ -158,8 +174,8 @@ void loopit(Reg*, int32);
void synch(Reg*, Bits);
uint32 allreg(uint32, Rgn*);
void paint1(Reg*, int);
uint32 paint2(Reg*, int);
void paint3(Reg*, int, int32, int);
uint32 paint2(Reg*, int, int);
void paint3(Reg*, int, uint32, int);
void addreg(Adr*, int);
void dumpone(Flow*, int);
void dumpit(char*, Flow*, int);
@@ -171,10 +187,10 @@ void peep(Prog*);
void excise(Flow*);
int copyu(Prog*, Adr*, Adr*);
int32 RtoB(int);
int32 FtoB(int);
int BtoR(int32);
int BtoF(int32);
uint32 RtoB(int);
uint32 FtoB(int);
int BtoR(uint32);
int BtoF(uint32);
/*
* prog.c
@@ -183,8 +199,8 @@ typedef struct ProgInfo ProgInfo;
struct ProgInfo
{
uint32 flags; // the bits below
uint32 reguse; // required registers used by this instruction
uint32 regset; // required registers set by this instruction
uint32 reguse; // registers implicitly used by this instruction
uint32 regset; // registers implicitly set by this instruction
uint32 regindex; // registers used by addressing mode
};
@@ -205,12 +221,12 @@ enum
SizeF = 1<<7, // float aka float32
SizeD = 1<<8, // double aka float64
// Left side: address taken, read, write.
// Left side (Prog.from): address taken, read, write.
LeftAddr = 1<<9,
LeftRead = 1<<10,
LeftWrite = 1<<11,
// Right side: address taken, read, write.
// Right side (Prog.to): address taken, read, write.
RightAddr = 1<<12,
RightRead = 1<<13,
RightWrite = 1<<14,

View File

@@ -34,7 +34,7 @@
#include "opt.h"
#define NREGVAR 16 /* 8 integer + 8 floating */
#define REGBITS ((uint32)0xffff)
#define REGBITS ((uint64)0xffffull)
/*c2go enum {
NREGVAR = 16,
REGBITS = (1<<NREGVAR) - 1,
@@ -71,7 +71,7 @@ setaddrs(Bits bit)
i = bnum(bit);
node = var[i].node;
n = var[i].name;
bit.b[i/32] &= ~(1L<<(i%32));
biclr(&bit, i);
// disable all pieces of that variable
for(i=0; i<nvar; i++) {
@@ -336,7 +336,7 @@ loop2:
rgp->varno = i;
change = 0;
paint1(r, i);
bit.b[i/32] &= ~(1L<<(i%32));
biclr(&bit, i);
if(change <= 0)
continue;
rgp->cost = change;
@@ -358,18 +358,19 @@ brk:
* replace code (paint3)
*/
rgp = region;
if(debug['R'] && debug['v'])
print("\nregisterizing\n");
for(i=0; i<nregion; i++) {
if(debug['R'] && debug['v'])
print("region %d: cost %d varno %d enter %d\n", i, rgp->cost, rgp->varno, rgp->enter->f.prog->pc);
bit = blsh(rgp->varno);
vreg = paint2(rgp->enter, rgp->varno);
vreg = paint2(rgp->enter, rgp->varno, 0);
vreg = allreg(vreg, rgp);
if(rgp->regno != 0)
paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
rgp++;
}
if(debug['R'] && debug['v'])
dumpit("pass6", &firstr->f, 1);
/*
* free aux structures. peep allocates new ones.
*/
@@ -378,6 +379,15 @@ brk:
flowend(g);
firstr = R;
if(debug['R'] && debug['v']) {
// Rebuild flow graph, since we inserted instructions
g = flowstart(firstp, sizeof(Reg));
firstr = (Reg*)g->start;
dumpit("pass6", &firstr->f, 1);
flowend(g);
firstr = R;
}
/*
* pass 7
* peep-hole on basic block
@@ -446,7 +456,7 @@ walkvardef(Node *n, Reg *r, int active)
break;
for(v=n->opt; v!=nil; v=v->nextinnode) {
bn = v - var;
r1->act.b[bn/32] |= 1L << (bn%32);
biset(&r1->act, bn);
}
if(r1->f.prog->as == ACALL)
break;
@@ -788,10 +798,10 @@ prop(Reg *r, Bits ref, Bits cal)
for(z=0; z<BITS; z++) {
if(cal.b[z] == 0)
continue;
for(i=0; i<32; i++) {
if(z*32+i >= nvar || ((cal.b[z]>>i)&1) == 0)
for(i=0; i<64; i++) {
if(z*64+i >= nvar || ((cal.b[z]>>i)&1) == 0)
continue;
v = var+z*32+i;
v = var+z*64+i;
if(v->node->opt == nil) // v represents fixed register, not Go variable
continue;
@@ -807,10 +817,10 @@ prop(Reg *r, Bits ref, Bits cal)
// This will set the bits at most twice, keeping the overall loop linear.
v1 = v->node->opt;
j = v1 - var;
if(v == v1 || ((cal.b[j/32]>>(j&31))&1) == 0) {
if(v == v1 || !btest(&cal, j)) {
for(; v1 != nil; v1 = v1->nextinnode) {
j = v1 - var;
cal.b[j/32] |= 1<<(j&31);
biset(&cal, j);
}
}
}
@@ -926,10 +936,10 @@ paint1(Reg *r, int bn)
Reg *r1;
Prog *p;
int z;
uint32 bb;
uint64 bb;
z = bn/32;
bb = 1L<<(bn%32);
z = bn/64;
bb = 1LL<<(bn%64);
if(r->act.b[z] & bb)
return;
for(;;) {
@@ -996,52 +1006,14 @@ paint1(Reg *r, int bn)
}
uint32
regset(Reg *r, uint32 bb)
{
uint32 b, set;
Adr v;
int c;
set = 0;
v = zprog.from;
while(b = bb & ~(bb-1)) {
v.type = b & 0xFF ? BtoR(b): BtoF(b);
c = copyu(r->f.prog, &v, nil);
if(c == 3)
set |= b;
bb &= ~b;
}
return set;
}
uint32
reguse(Reg *r, uint32 bb)
{
uint32 b, set;
Adr v;
int c;
set = 0;
v = zprog.from;
while(b = bb & ~(bb-1)) {
v.type = b & 0xFF ? BtoR(b): BtoF(b);
c = copyu(r->f.prog, &v, nil);
if(c == 1 || c == 2 || c == 4)
set |= b;
bb &= ~b;
}
return set;
}
uint32
paint2(Reg *r, int bn)
paint2(Reg *r, int bn, int depth)
{
Reg *r1;
int z;
uint32 bb, vreg, x;
uint64 bb, vreg;
z = bn/32;
bb = 1L << (bn%32);
z = bn/64;
bb = 1LL << (bn%64);
vreg = regbits;
if(!(r->act.b[z] & bb))
return vreg;
@@ -1058,6 +1030,9 @@ paint2(Reg *r, int bn)
r = r1;
}
for(;;) {
if(debug['R'] && debug['v'])
print(" paint2 %d %P\n", depth, r->f.prog);
r->act.b[z] &= ~bb;
vreg |= r->regu;
@@ -1065,14 +1040,14 @@ paint2(Reg *r, int bn)
if(r->refbehind.b[z] & bb)
for(r1 = (Reg*)r->f.p2; r1 != R; r1 = (Reg*)r1->f.p2link)
if(r1->refahead.b[z] & bb)
vreg |= paint2(r1, bn);
vreg |= paint2(r1, bn, depth+1);
if(!(r->refahead.b[z] & bb))
break;
r1 = (Reg*)r->f.s2;
if(r1 != R)
if(r1->refbehind.b[z] & bb)
vreg |= paint2(r1, bn);
vreg |= paint2(r1, bn, depth+1);
r = (Reg*)r->f.s1;
if(r == R)
break;
@@ -1082,27 +1057,19 @@ paint2(Reg *r, int bn)
break;
}
bb = vreg;
for(; r; r=(Reg*)r->f.s1) {
x = r->regu & ~bb;
if(x) {
vreg |= reguse(r, x);
bb |= regset(r, x);
}
}
return vreg;
}
void
paint3(Reg *r, int bn, int32 rb, int rn)
paint3(Reg *r, int bn, uint32 rb, int rn)
{
Reg *r1;
Prog *p;
int z;
uint32 bb;
uint64 bb;
z = bn/32;
bb = 1L << (bn%32);
z = bn/64;
bb = 1LL << (bn%64);
if(r->act.b[z] & bb)
return;
for(;;) {
@@ -1175,7 +1142,7 @@ addreg(Adr *a, int rn)
ostats.ncvtreg++;
}
int32
uint32
RtoB(int r)
{
@@ -1185,7 +1152,7 @@ RtoB(int r)
}
int
BtoR(int32 b)
BtoR(uint32 b)
{
b &= 0xffL;
@@ -1194,7 +1161,7 @@ BtoR(int32 b)
return bitno(b) + D_AX;
}
int32
uint32
FtoB(int f)
{
if(f < D_X0 || f > D_X7)
@@ -1203,7 +1170,7 @@ FtoB(int f)
}
int
BtoF(int32 b)
BtoF(uint32 b)
{
b &= 0xFF00L;
if(b == 0)
@@ -1273,12 +1240,14 @@ dumpit(char *str, Flow *r0, int isreg)
print(" %.4ud", (int)r1->prog->pc);
print("\n");
}
// r1 = r->s1;
// if(r1 != nil) {
// print(" succ:");
// for(; r1 != R; r1 = r1->s1)
// print(" %.4ud", (int)r1->prog->pc);
// print("\n");
// }
// Print successors if it's not just the next one
if(r->s1 != r->link || r->s2 != nil) {
print(" succ:");
if(r->s1 != nil)
print(" %.4ud", (int)r->s1->prog->pc);
if(r->s2 != nil)
print(" %.4ud", (int)r->s2->prog->pc);
print("\n");
}
}
}

View File

@@ -654,6 +654,8 @@ enum
D_CONST2 = D_INDIR+D_INDIR,
D_LAST,
T_TYPE = 1<<0,
T_INDEX = 1<<1,
T_OFFSET = 1<<2,

10
src/cmd/9a/Makefile Normal file
View File

@@ -0,0 +1,10 @@
# Copyright 2012 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
include ../../Make.dist
install: y.tab.h
y.tab.h: a.y
LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y a.y

170
src/cmd/9a/a.h Normal file
View File

@@ -0,0 +1,170 @@
// cmd/9a/a.h from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <bio.h>
#include <link.h>
#include "../9l/9.out.h"
#ifndef EXTERN
#define EXTERN extern
#endif
#undef getc
#undef ungetc
#undef BUFSIZ
#define getc ccgetc
#define ungetc ccungetc
typedef struct Sym Sym;
typedef struct Io Io;
#define MAXALIGN 7
#define FPCHIP 1
#define NSYMB 8192
#define BUFSIZ 8192
#define HISTSZ 20
#define NINCLUDE 10
#define NHUNK 10000
#ifndef EOF
#define EOF (-1)
#endif
#define IGN (-2)
#define GETC() ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
#define NHASH 503
#define STRINGSZ 200
#define NMACRO 10
struct Sym
{
Sym* link;
char* macro;
vlong value;
ushort type;
char *name;
char* labelname;
char sym;
};
#define S ((Sym*)0)
EXTERN struct
{
char* p;
int c;
} fi;
struct Io
{
Io* link;
char b[BUFSIZ];
char* p;
short c;
short f;
};
#define I ((Io*)0)
enum
{
CLAST,
CMACARG,
CMACRO,
CPREPROC,
};
EXTERN int debug[256];
EXTERN Sym* hash[NHASH];
EXTERN char** Dlist;
EXTERN int nDlist;
EXTERN int newflag;
EXTERN char* hunk;
EXTERN char** include;
EXTERN Io* iofree;
EXTERN Io* ionext;
EXTERN Io* iostack;
EXTERN int32 lineno;
EXTERN int nerrors;
EXTERN int32 nhunk;
EXTERN int nosched;
EXTERN int ninclude;
EXTERN int32 nsymb;
EXTERN Addr nullgen;
EXTERN char* outfile;
EXTERN int pass;
EXTERN int32 pc;
EXTERN int peekc;
EXTERN int sym;
EXTERN char* symb;
EXTERN int thechar;
EXTERN char* thestring;
EXTERN int32 thunk;
EXTERN Biobuf obuf;
EXTERN Link* ctxt;
EXTERN Biobuf bstdout;
void* alloc(int32);
void* allocn(void*, int32, int32);
void ensuresymb(int32);
void errorexit(void);
void pushio(void);
void newio(void);
void newfile(char*, int);
Sym* slookup(char*);
Sym* lookup(void);
Sym* labellookup(Sym*);
void settext(LSym*);
void syminit(Sym*);
int32 yylex(void);
int getc(void);
int getnsc(void);
void unget(int);
int escchar(int);
void cinit(void);
void pinit(char*);
void cclean(void);
void outcode(int, Addr*, int, Addr*);
void outgcode(int, Addr*, int, Addr*, Addr*);
int filbuf(void);
Sym* getsym(void);
void domacro(void);
void macund(void);
void macdef(void);
void macexpand(Sym*, char*);
void macinc(void);
void macprag(void);
void maclin(void);
void macif(int);
void macend(void);
void dodefine(char*);
void prfile(int32);
void linehist(char*, int);
void gethunk(void);
void yyerror(char*, ...);
int yyparse(void);
void setinclude(char*);
int assemble(char*);

991
src/cmd/9a/a.y Normal file
View File

@@ -0,0 +1,991 @@
// cmd/9a/a.y from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
%{
#include <u.h>
#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
#include <libc.h>
#include "a.h"
#include "../../runtime/funcdata.h"
%}
%union
{
Sym *sym;
vlong lval;
double dval;
char sval[8];
Addr addr;
}
%left '|'
%left '^'
%left '&'
%left '<' '>'
%left '+' '-'
%left '*' '/' '%'
%token <lval> LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP
%token <lval> LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW
%token <lval> LNOP LEND LRETT LWORD LTEXT LDATA LRETRN
%token <lval> LCONST LSP LSB LFP LPC LCREG LFLUSH
%token <lval> LREG LFREG LR LCR LF LFPSCR
%token <lval> LLR LCTR LSPR LSPREG LSEG LMSR
%token <lval> LPCDAT LFUNCDAT LSCHED LXLD LXST LXOP LXMV
%token <lval> LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA
%token <dval> LFCONST
%token <sval> LSCONST
%token <sym> LNAME LLAB LVAR
%type <lval> con expr pointer offset sreg
%type <addr> addr rreg regaddr name creg freg xlreg lr ctr
%type <addr> imm ximm fimm rel psr lcr cbit fpscr fpscrf msr mask
%%
prog:
| prog line
line:
LNAME ':'
{
$1 = labellookup($1);
if($1->type == LLAB && $1->value != pc)
yyerror("redeclaration of %s", $1->labelname);
$1->type = LLAB;
$1->value = pc;
}
line
| LNAME '=' expr ';'
{
$1->type = LVAR;
$1->value = $3;
}
| LVAR '=' expr ';'
{
if($1->value != $3)
yyerror("redeclaration of %s", $1->name);
$1->value = $3;
}
| LSCHED ';'
{
nosched = $1;
}
| ';'
| inst ';'
| error ';'
inst:
/*
* load ints and bytes
*/
LMOVW rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW addr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW regaddr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVB rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVB addr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVB regaddr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
/*
* load floats
*/
| LFMOV addr ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFMOV regaddr ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFMOV fimm ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFMOV freg ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFMOV freg ',' addr
{
outcode($1, &$2, NREG, &$4);
}
| LFMOV freg ',' regaddr
{
outcode($1, &$2, NREG, &$4);
}
/*
* store ints and bytes
*/
| LMOVW rreg ',' addr
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW rreg ',' regaddr
{
outcode($1, &$2, NREG, &$4);
}
| LMOVB rreg ',' addr
{
outcode($1, &$2, NREG, &$4);
}
| LMOVB rreg ',' regaddr
{
outcode($1, &$2, NREG, &$4);
}
/*
* store floats
*/
| LMOVW freg ',' addr
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW freg ',' regaddr
{
outcode($1, &$2, NREG, &$4);
}
/*
* floating point status
*/
| LMOVW fpscr ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW freg ',' fpscr
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW freg ',' imm ',' fpscr
{
outgcode($1, &$2, NREG, &$4, &$6);
}
| LMOVW fpscr ',' creg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW imm ',' fpscrf
{
outcode($1, &$2, NREG, &$4);
}
| LMTFSB imm ',' con
{
outcode($1, &$2, $4, &nullgen);
}
/*
* field moves (mtcrf)
*/
| LMOVW rreg ',' imm ',' lcr
{
outgcode($1, &$2, NREG, &$4, &$6);
}
| LMOVW rreg ',' creg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW rreg ',' lcr
{
outcode($1, &$2, NREG, &$4);
}
/*
* integer operations
* logical instructions
* shift instructions
* unary instructions
*/
| LADDW rreg ',' sreg ',' rreg
{
outcode($1, &$2, $4, &$6);
}
| LADDW imm ',' sreg ',' rreg
{
outcode($1, &$2, $4, &$6);
}
| LADDW rreg ',' imm ',' rreg
{
outgcode($1, &$2, NREG, &$4, &$6);
}
| LADDW rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LADDW imm ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LLOGW rreg ',' sreg ',' rreg
{
outcode($1, &$2, $4, &$6);
}
| LLOGW rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LSHW rreg ',' sreg ',' rreg
{
outcode($1, &$2, $4, &$6);
}
| LSHW rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LSHW imm ',' sreg ',' rreg
{
outcode($1, &$2, $4, &$6);
}
| LSHW imm ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LABS rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LABS rreg
{
outcode($1, &$2, NREG, &$2);
}
/*
* multiply-accumulate
*/
| LMA rreg ',' sreg ',' rreg
{
outcode($1, &$2, $4, &$6);
}
/*
* move immediate: macro for cau+or, addi, addis, and other combinations
*/
| LMOVW imm ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW ximm ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
/*
* condition register operations
*/
| LCROP cbit ',' cbit
{
outcode($1, &$2, $4.reg, &$4);
}
| LCROP cbit ',' con ',' cbit
{
outcode($1, &$2, $4, &$6);
}
/*
* condition register moves
* move from machine state register
*/
| LMOVW creg ',' creg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW psr ',' creg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW lcr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW psr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW xlreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW rreg ',' xlreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW creg ',' psr
{
outcode($1, &$2, NREG, &$4);
}
| LMOVW rreg ',' psr
{
outcode($1, &$2, NREG, &$4);
}
/*
* branch, branch conditional
* branch conditional register
* branch conditional to count register
*/
| LBRA rel
{
outcode($1, &nullgen, NREG, &$2);
}
| LBRA addr
{
outcode($1, &nullgen, NREG, &$2);
}
| LBRA '(' xlreg ')'
{
outcode($1, &nullgen, NREG, &$3);
}
| LBRA ',' rel
{
outcode($1, &nullgen, NREG, &$3);
}
| LBRA ',' addr
{
outcode($1, &nullgen, NREG, &$3);
}
| LBRA ',' '(' xlreg ')'
{
outcode($1, &nullgen, NREG, &$4);
}
| LBRA creg ',' rel
{
outcode($1, &$2, NREG, &$4);
}
| LBRA creg ',' addr
{
outcode($1, &$2, NREG, &$4);
}
| LBRA creg ',' '(' xlreg ')'
{
outcode($1, &$2, NREG, &$5);
}
| LBRA con ',' rel
{
outcode($1, &nullgen, $2, &$4);
}
| LBRA con ',' addr
{
outcode($1, &nullgen, $2, &$4);
}
| LBRA con ',' '(' xlreg ')'
{
outcode($1, &nullgen, $2, &$5);
}
| LBRA con ',' con ',' rel
{
Addr g;
g = nullgen;
g.type = D_CONST;
g.offset = $2;
outcode($1, &g, $4, &$6);
}
| LBRA con ',' con ',' addr
{
Addr g;
g = nullgen;
g.type = D_CONST;
g.offset = $2;
outcode($1, &g, $4, &$6);
}
| LBRA con ',' con ',' '(' xlreg ')'
{
Addr g;
g = nullgen;
g.type = D_CONST;
g.offset = $2;
outcode($1, &g, $4, &$7);
}
/*
* conditional trap
*/
| LTRAP rreg ',' sreg
{
outcode($1, &$2, $4, &nullgen);
}
| LTRAP imm ',' sreg
{
outcode($1, &$2, $4, &nullgen);
}
| LTRAP rreg comma
{
outcode($1, &$2, NREG, &nullgen);
}
| LTRAP comma
{
outcode($1, &nullgen, NREG, &nullgen);
}
/*
* floating point operate
*/
| LFCONV freg ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFADD freg ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFADD freg ',' freg ',' freg
{
outcode($1, &$2, $4.reg, &$6);
}
| LFMA freg ',' freg ',' freg ',' freg
{
outgcode($1, &$2, $4.reg, &$6, &$8);
}
| LFCMP freg ',' freg
{
outcode($1, &$2, NREG, &$4);
}
| LFCMP freg ',' freg ',' creg
{
outcode($1, &$2, $6.reg, &$4);
}
/*
* CMP
*/
| LCMP rreg ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LCMP rreg ',' imm
{
outcode($1, &$2, NREG, &$4);
}
| LCMP rreg ',' rreg ',' creg
{
outcode($1, &$2, $6.reg, &$4);
}
| LCMP rreg ',' imm ',' creg
{
outcode($1, &$2, $6.reg, &$4);
}
/*
* rotate and mask
*/
| LRLWM imm ',' rreg ',' imm ',' rreg
{
outgcode($1, &$2, $4.reg, &$6, &$8);
}
| LRLWM imm ',' rreg ',' mask ',' rreg
{
outgcode($1, &$2, $4.reg, &$6, &$8);
}
| LRLWM rreg ',' rreg ',' imm ',' rreg
{
outgcode($1, &$2, $4.reg, &$6, &$8);
}
| LRLWM rreg ',' rreg ',' mask ',' rreg
{
outgcode($1, &$2, $4.reg, &$6, &$8);
}
/*
* load/store multiple
*/
| LMOVMW addr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LMOVMW rreg ',' addr
{
outcode($1, &$2, NREG, &$4);
}
/*
* various indexed load/store
* indexed unary (eg, cache clear)
*/
| LXLD regaddr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LXLD regaddr ',' imm ',' rreg
{
outgcode($1, &$2, NREG, &$4, &$6);
}
| LXST rreg ',' regaddr
{
outcode($1, &$2, NREG, &$4);
}
| LXST rreg ',' imm ',' regaddr
{
outgcode($1, &$2, NREG, &$4, &$6);
}
| LXMV regaddr ',' rreg
{
outcode($1, &$2, NREG, &$4);
}
| LXMV rreg ',' regaddr
{
outcode($1, &$2, NREG, &$4);
}
| LXOP regaddr
{
outcode($1, &$2, NREG, &nullgen);
}
/*
* NOP
*/
| LNOP comma
{
outcode($1, &nullgen, NREG, &nullgen);
}
| LNOP rreg comma
{
outcode($1, &$2, NREG, &nullgen);
}
| LNOP freg comma
{
outcode($1, &$2, NREG, &nullgen);
}
| LNOP ',' rreg
{
outcode($1, &nullgen, NREG, &$3);
}
| LNOP ',' freg
{
outcode($1, &nullgen, NREG, &$3);
}
| LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */
{
outcode($1, &$2, NREG, &nullgen);
}
/*
* word
*/
| LWORD imm comma
{
outcode($1, &$2, NREG, &nullgen);
}
| LWORD ximm comma
{
outcode($1, &$2, NREG, &nullgen);
}
/*
* PCDATA
*/
| LPCDAT imm ',' imm
{
if($2.type != D_CONST || $4.type != D_CONST)
yyerror("arguments to PCDATA must be integer constants");
outcode($1, &$2, NREG, &$4);
}
/*
* FUNCDATA
*/
| LFUNCDAT imm ',' addr
{
if($2.type != D_CONST)
yyerror("index for FUNCDATA must be integer constant");
if($4.type != D_EXTERN && $4.type != D_STATIC && $4.type != D_OREG)
yyerror("value for FUNCDATA must be symbol reference");
outcode($1, &$2, NREG, &$4);
}
/*
* END
*/
| LEND comma
{
outcode($1, &nullgen, NREG, &nullgen);
}
/*
* TEXT/GLOBL
*/
| LTEXT name ',' imm
{
settext($2.sym);
outcode($1, &$2, NREG, &$4);
}
| LTEXT name ',' con ',' imm
{
settext($2.sym);
$6.offset &= 0xffffffffull;
$6.offset |= (vlong)ArgsSizeUnknown << 32;
outcode($1, &$2, $4, &$6);
}
| LTEXT name ',' con ',' imm '-' con
{
settext($2.sym);
$6.offset &= 0xffffffffull;
$6.offset |= ($8 & 0xffffffffull) << 32;
outcode($1, &$2, $4, &$6);
}
/*
* DATA
*/
| LDATA name '/' con ',' imm
{
outcode($1, &$2, $4, &$6);
}
| LDATA name '/' con ',' ximm
{
outcode($1, &$2, $4, &$6);
}
| LDATA name '/' con ',' fimm
{
outcode($1, &$2, $4, &$6);
}
/*
* RETURN
*/
| LRETRN comma
{
outcode($1, &nullgen, NREG, &nullgen);
}
rel:
con '(' LPC ')'
{
$$ = nullgen;
$$.type = D_BRANCH;
$$.offset = $1 + pc;
}
| LNAME offset
{
$1 = labellookup($1);
$$ = nullgen;
if(pass == 2 && $1->type != LLAB)
yyerror("undefined label: %s", $1->labelname);
$$.type = D_BRANCH;
$$.offset = $1->value + $2;
}
rreg:
sreg
{
$$ = nullgen;
$$.type = D_REG;
$$.reg = $1;
}
xlreg:
lr
| ctr
lr:
LLR
{
$$ = nullgen;
$$.type = D_SPR;
$$.offset = $1;
}
lcr:
LCR
{
$$ = nullgen;
$$.type = D_CREG;
$$.reg = NREG; /* whole register */
}
ctr:
LCTR
{
$$ = nullgen;
$$.type = D_SPR;
$$.offset = $1;
}
msr:
LMSR
{
$$ = nullgen;
$$.type = D_MSR;
}
psr:
LSPREG
{
$$ = nullgen;
$$.type = D_SPR;
$$.offset = $1;
}
| LSPR '(' con ')'
{
$$ = nullgen;
$$.type = $1;
$$.offset = $3;
}
| msr
fpscr:
LFPSCR
{
$$ = nullgen;
$$.type = D_FPSCR;
$$.reg = NREG;
}
fpscrf:
LFPSCR '(' con ')'
{
$$ = nullgen;
$$.type = D_FPSCR;
$$.reg = $3;
}
freg:
LFREG
{
$$ = nullgen;
$$.type = D_FREG;
$$.reg = $1;
}
| LF '(' con ')'
{
$$ = nullgen;
$$.type = D_FREG;
$$.reg = $3;
}
creg:
LCREG
{
$$ = nullgen;
$$.type = D_CREG;
$$.reg = $1;
}
| LCR '(' con ')'
{
$$ = nullgen;
$$.type = D_CREG;
$$.reg = $3;
}
cbit: con
{
$$ = nullgen;
$$.type = D_REG;
$$.reg = $1;
}
mask:
con ',' con
{
int mb, me;
uint32 v;
$$ = nullgen;
$$.type = D_CONST;
mb = $1;
me = $3;
if(mb < 0 || mb > 31 || me < 0 || me > 31){
yyerror("illegal mask start/end value(s)");
mb = me = 0;
}
if(mb <= me)
v = ((uint32)~0L>>mb) & (~0L<<(31-me));
else
v = ~(((uint32)~0L>>(me+1)) & (~0L<<(31-(mb-1))));
$$.offset = v;
}
ximm:
'$' addr
{
$$ = $2;
$$.type = D_CONST;
}
| '$' LSCONST
{
$$ = nullgen;
$$.type = D_SCONST;
memcpy($$.u.sval, $2, sizeof($$.u.sval));
}
fimm:
'$' LFCONST
{
$$ = nullgen;
$$.type = D_FCONST;
$$.u.dval = $2;
}
| '$' '-' LFCONST
{
$$ = nullgen;
$$.type = D_FCONST;
$$.u.dval = -$3;
}
imm: '$' con
{
$$ = nullgen;
$$.type = D_CONST;
$$.offset = $2;
}
sreg:
LREG
| LR '(' con ')'
{
if($$ < 0 || $$ >= NREG)
print("register value out of range\n");
$$ = $3;
}
regaddr:
'(' sreg ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.reg = $2;
$$.offset = 0;
}
| '(' sreg '+' sreg ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.reg = $2;
$$.scale = $4;
$$.offset = 0;
}
addr:
name
| con '(' sreg ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.reg = $3;
$$.offset = $1;
}
name:
con '(' pointer ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.name = $3;
$$.sym = nil;
$$.offset = $1;
}
| LNAME offset '(' pointer ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.name = $4;
$$.sym = linklookup(ctxt, $1->name, 0);
$$.offset = $2;
}
| LNAME '<' '>' offset '(' LSB ')'
{
$$ = nullgen;
$$.type = D_OREG;
$$.name = D_STATIC;
$$.sym = linklookup(ctxt, $1->name, 0);
$$.offset = $4;
}
comma:
| ','
offset:
{
$$ = 0;
}
| '+' con
{
$$ = $2;
}
| '-' con
{
$$ = -$2;
}
pointer:
LSB
| LSP
| LFP
con:
LCONST
| LVAR
{
$$ = $1->value;
}
| '-' con
{
$$ = -$2;
}
| '+' con
{
$$ = $2;
}
| '~' con
{
$$ = ~$2;
}
| '(' expr ')'
{
$$ = $2;
}
expr:
con
| expr '+' expr
{
$$ = $1 + $3;
}
| expr '-' expr
{
$$ = $1 - $3;
}
| expr '*' expr
{
$$ = $1 * $3;
}
| expr '/' expr
{
$$ = $1 / $3;
}
| expr '%' expr
{
$$ = $1 % $3;
}
| expr '<' '<' expr
{
$$ = $1 << $4;
}
| expr '>' '>' expr
{
$$ = $1 >> $4;
}
| expr '&' expr
{
$$ = $1 & $3;
}
| expr '^' expr
{
$$ = $1 ^ $3;
}
| expr '|' expr
{
$$ = $1 | $3;
}

21
src/cmd/9a/doc.go Normal file
View File

@@ -0,0 +1,21 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
9a is a version of the Plan 9 assembler. The original is documented at
http://plan9.bell-labs.com/magic/man2html/1/8a
Go-specific considerations are documented at
http://golang.org/doc/asm
Its target architecture is the Power64, referred to by these tools as
power64 (big endian) or power64le (little endian).
*/
package main

725
src/cmd/9a/lex.c Normal file
View File

@@ -0,0 +1,725 @@
// cmd/9a/lex.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#define EXTERN
#include <u.h>
#include <libc.h>
#include "a.h"
#include "y.tab.h"
enum
{
Plan9 = 1<<0,
Unix = 1<<1,
Windows = 1<<2,
};
int
systemtype(int sys)
{
#ifdef _WIN32
return sys&Windows;
#else
return sys&Plan9;
#endif
}
int
pathchar(void)
{
return '/';
}
int
Lconv(Fmt *fp)
{
return linklinefmt(ctxt, fp);
}
void
dodef(char *p)
{
if(nDlist%8 == 0)
Dlist = allocn(Dlist, nDlist*sizeof(char *),
8*sizeof(char *));
Dlist[nDlist++] = p;
}
LinkArch* thelinkarch = &linkpower64;
void
usage(void)
{
print("usage: %ca [options] file.c...\n", thechar);
flagprint(1);
errorexit();
}
void
main(int argc, char *argv[])
{
char *p;
thechar = '9';
thestring = "power64";
// Allow GOARCH=thestring or GOARCH=thestringsuffix,
// but not other values.
p = getgoarch();
if(strncmp(p, thestring, strlen(thestring)) != 0)
sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
if(strcmp(p, "power64le") == 0)
thelinkarch = &linkpower64le;
ctxt = linknew(thelinkarch);
ctxt->diag = yyerror;
ctxt->bso = &bstdout;
ctxt->enforce_data_order = 1;
Binit(&bstdout, 1, OWRITE);
listinit9();
fmtinstall('L', Lconv);
ensuresymb(NSYMB);
memset(debug, 0, sizeof(debug));
cinit();
outfile = 0;
setinclude(".");
flagfn1("D", "name[=value]: add #define", dodef);
flagfn1("I", "dir: add dir to include path", setinclude);
flagcount("S", "print assembly and machine code", &debug['S']);
flagcount("m", "debug preprocessor macros", &debug['m']);
flagstr("o", "file: set output file", &outfile);
flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
flagparse(&argc, &argv, usage);
ctxt->debugasm = debug['S'];
if(argc < 1)
usage();
if(argc > 1){
print("can't assemble multiple files\n");
errorexit();
}
if(assemble(argv[0]))
errorexit();
Bflush(&bstdout);
exits(0);
}
int
assemble(char *file)
{
char *ofile, *p;
int i, of;
ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar)
strcpy(ofile, file);
p = utfrrune(ofile, pathchar());
if(p) {
include[0] = ofile;
*p++ = 0;
} else
p = ofile;
if(outfile == 0) {
outfile = p;
if(outfile){
p = utfrrune(outfile, '.');
if(p)
if(p[1] == 's' && p[2] == 0)
p[0] = 0;
p = utfrune(outfile, 0);
p[0] = '.';
p[1] = thechar;
p[2] = 0;
} else
outfile = "/dev/null";
}
of = create(outfile, OWRITE, 0664);
if(of < 0) {
yyerror("%ca: cannot create %s", thechar, outfile);
errorexit();
}
Binit(&obuf, of, OWRITE);
Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
Bprint(&obuf, "!\n");
for(pass = 1; pass <= 2; pass++) {
nosched = 0;
pinit(file);
for(i=0; i<nDlist; i++)
dodefine(Dlist[i]);
yyparse();
cclean();
if(nerrors)
return nerrors;
}
writeobj(ctxt, &obuf);
Bflush(&obuf);
return 0;
}
struct
{
char *name;
ushort type;
ushort value;
} itab[] =
{
"SP", LSP, D_AUTO,
"SB", LSB, D_EXTERN,
"FP", LFP, D_PARAM,
"PC", LPC, D_BRANCH,
"LR", LLR, D_LR,
"CTR", LCTR, D_CTR,
"XER", LSPREG, D_XER,
"MSR", LMSR, D_MSR,
"FPSCR", LFPSCR, D_FPSCR,
"SPR", LSPR, D_SPR,
"DCR", LSPR, D_DCR,
"CR", LCR, 0,
"CR0", LCREG, 0,
"CR1", LCREG, 1,
"CR2", LCREG, 2,
"CR3", LCREG, 3,
"CR4", LCREG, 4,
"CR5", LCREG, 5,
"CR6", LCREG, 6,
"CR7", LCREG, 7,
"R", LR, 0,
"R0", LREG, 0,
"R1", LREG, 1,
"R2", LREG, 2,
"R3", LREG, 3,
"R4", LREG, 4,
"R5", LREG, 5,
"R6", LREG, 6,
"R7", LREG, 7,
"R8", LREG, 8,
"R9", LREG, 9,
"R10", LREG, 10,
"R11", LREG, 11,
"R12", LREG, 12,
"R13", LREG, 13,
"R14", LREG, 14,
"R15", LREG, 15,
"R16", LREG, 16,
"R17", LREG, 17,
"R18", LREG, 18,
"R19", LREG, 19,
"R20", LREG, 20,
"R21", LREG, 21,
"R22", LREG, 22,
"R23", LREG, 23,
"R24", LREG, 24,
"R25", LREG, 25,
"R26", LREG, 26,
"R27", LREG, 27,
"R28", LREG, 28,
"R29", LREG, 29,
"R30", LREG, 30,
"R31", LREG, 31,
"F", LF, 0,
"F0", LFREG, 0,
"F1", LFREG, 1,
"F2", LFREG, 2,
"F3", LFREG, 3,
"F4", LFREG, 4,
"F5", LFREG, 5,
"F6", LFREG, 6,
"F7", LFREG, 7,
"F8", LFREG, 8,
"F9", LFREG, 9,
"F10", LFREG, 10,
"F11", LFREG, 11,
"F12", LFREG, 12,
"F13", LFREG, 13,
"F14", LFREG, 14,
"F15", LFREG, 15,
"F16", LFREG, 16,
"F17", LFREG, 17,
"F18", LFREG, 18,
"F19", LFREG, 19,
"F20", LFREG, 20,
"F21", LFREG, 21,
"F22", LFREG, 22,
"F23", LFREG, 23,
"F24", LFREG, 24,
"F25", LFREG, 25,
"F26", LFREG, 26,
"F27", LFREG, 27,
"F28", LFREG, 28,
"F29", LFREG, 29,
"F30", LFREG, 30,
"F31", LFREG, 31,
"CREQV", LCROP, ACREQV,
"CRXOR", LCROP, ACRXOR,
"CRAND", LCROP, ACRAND,
"CROR", LCROP, ACROR,
"CRANDN", LCROP, ACRANDN,
"CRORN", LCROP, ACRORN,
"CRNAND", LCROP, ACRNAND,
"CRNOR", LCROP, ACRNOR,
"ADD", LADDW, AADD,
"ADDV", LADDW, AADDV,
"ADDCC", LADDW, AADDCC,
"ADDVCC", LADDW, AADDVCC,
"ADDC", LADDW, AADDC,
"ADDCV", LADDW, AADDCV,
"ADDCCC", LADDW, AADDCCC,
"ADDCVCC", LADDW, AADDCVCC,
"ADDE", LLOGW, AADDE,
"ADDEV", LLOGW, AADDEV,
"ADDECC", LLOGW, AADDECC,
"ADDEVCC", LLOGW, AADDEVCC,
"ADDME", LABS, AADDME,
"ADDMEV", LABS, AADDMEV,
"ADDMECC", LABS, AADDMECC,
"ADDMEVCC", LABS, AADDMEVCC,
"ADDZE", LABS, AADDZE,
"ADDZEV", LABS, AADDZEV,
"ADDZECC", LABS, AADDZECC,
"ADDZEVCC", LABS, AADDZEVCC,
"SUB", LADDW, ASUB,
"SUBV", LADDW, ASUBV,
"SUBCC", LADDW, ASUBCC,
"SUBVCC", LADDW, ASUBVCC,
"SUBE", LLOGW, ASUBE,
"SUBECC", LLOGW, ASUBECC,
"SUBEV", LLOGW, ASUBEV,
"SUBEVCC", LLOGW, ASUBEVCC,
"SUBC", LADDW, ASUBC,
"SUBCCC", LADDW, ASUBCCC,
"SUBCV", LADDW, ASUBCV,
"SUBCVCC", LADDW, ASUBCVCC,
"SUBME", LABS, ASUBME,
"SUBMEV", LABS, ASUBMEV,
"SUBMECC", LABS, ASUBMECC,
"SUBMEVCC", LABS, ASUBMEVCC,
"SUBZE", LABS, ASUBZE,
"SUBZEV", LABS, ASUBZEV,
"SUBZECC", LABS, ASUBZECC,
"SUBZEVCC", LABS, ASUBZEVCC,
"AND", LADDW, AAND,
"ANDCC", LADDW, AANDCC, /* includes andil & andiu */
"ANDN", LLOGW, AANDN,
"ANDNCC", LLOGW, AANDNCC,
"EQV", LLOGW, AEQV,
"EQVCC", LLOGW, AEQVCC,
"NAND", LLOGW, ANAND,
"NANDCC", LLOGW, ANANDCC,
"NOR", LLOGW, ANOR,
"NORCC", LLOGW, ANORCC,
"OR", LADDW, AOR, /* includes oril & oriu */
"ORCC", LADDW, AORCC,
"ORN", LLOGW, AORN,
"ORNCC", LLOGW, AORNCC,
"XOR", LADDW, AXOR, /* includes xoril & xoriu */
"XORCC", LLOGW, AXORCC,
"EXTSB", LABS, AEXTSB,
"EXTSBCC", LABS, AEXTSBCC,
"EXTSH", LABS, AEXTSH,
"EXTSHCC", LABS, AEXTSHCC,
"CNTLZW", LABS, ACNTLZW,
"CNTLZWCC", LABS, ACNTLZWCC,
"RLWMI", LRLWM, ARLWMI,
"RLWMICC", LRLWM, ARLWMICC,
"RLWNM", LRLWM, ARLWNM,
"RLWNMCC", LRLWM, ARLWNMCC,
"SLW", LSHW, ASLW,
"SLWCC", LSHW, ASLWCC,
"SRW", LSHW, ASRW,
"SRWCC", LSHW, ASRWCC,
"SRAW", LSHW, ASRAW,
"SRAWCC", LSHW, ASRAWCC,
"BR", LBRA, ABR,
"BC", LBRA, ABC,
"BCL", LBRA, ABC,
"BL", LBRA, ABL,
"BEQ", LBRA, ABEQ,
"BNE", LBRA, ABNE,
"BGT", LBRA, ABGT,
"BGE", LBRA, ABGE,
"BLT", LBRA, ABLT,
"BLE", LBRA, ABLE,
"BVC", LBRA, ABVC,
"BVS", LBRA, ABVS,
"CMP", LCMP, ACMP,
"CMPU", LCMP, ACMPU,
"CMPW", LCMP, ACMPW,
"CMPWU", LCMP, ACMPWU,
"DIVW", LLOGW, ADIVW,
"DIVWV", LLOGW, ADIVWV,
"DIVWCC", LLOGW, ADIVWCC,
"DIVWVCC", LLOGW, ADIVWVCC,
"DIVWU", LLOGW, ADIVWU,
"DIVWUV", LLOGW, ADIVWUV,
"DIVWUCC", LLOGW, ADIVWUCC,
"DIVWUVCC", LLOGW, ADIVWUVCC,
"FABS", LFCONV, AFABS,
"FABSCC", LFCONV, AFABSCC,
"FNEG", LFCONV, AFNEG,
"FNEGCC", LFCONV, AFNEGCC,
"FNABS", LFCONV, AFNABS,
"FNABSCC", LFCONV, AFNABSCC,
"FADD", LFADD, AFADD,
"FADDCC", LFADD, AFADDCC,
"FSUB", LFADD, AFSUB,
"FSUBCC", LFADD, AFSUBCC,
"FMUL", LFADD, AFMUL,
"FMULCC", LFADD, AFMULCC,
"FDIV", LFADD, AFDIV,
"FDIVCC", LFADD, AFDIVCC,
"FRSP", LFCONV, AFRSP,
"FRSPCC", LFCONV, AFRSPCC,
"FCTIW", LFCONV, AFCTIW,
"FCTIWCC", LFCONV, AFCTIWCC,
"FCTIWZ", LFCONV, AFCTIWZ,
"FCTIWZCC", LFCONV, AFCTIWZCC,
"FMADD", LFMA, AFMADD,
"FMADDCC", LFMA, AFMADDCC,
"FMSUB", LFMA, AFMSUB,
"FMSUBCC", LFMA, AFMSUBCC,
"FNMADD", LFMA, AFNMADD,
"FNMADDCC", LFMA, AFNMADDCC,
"FNMSUB", LFMA, AFNMSUB,
"FNMSUBCC", LFMA, AFNMSUBCC,
"FMADDS", LFMA, AFMADDS,
"FMADDSCC", LFMA, AFMADDSCC,
"FMSUBS", LFMA, AFMSUBS,
"FMSUBSCC", LFMA, AFMSUBSCC,
"FNMADDS", LFMA, AFNMADDS,
"FNMADDSCC", LFMA, AFNMADDSCC,
"FNMSUBS", LFMA, AFNMSUBS,
"FNMSUBSCC", LFMA, AFNMSUBSCC,
"FCMPU", LFCMP, AFCMPU,
"FCMPO", LFCMP, AFCMPO,
"MTFSB0", LMTFSB, AMTFSB0,
"MTFSB1", LMTFSB, AMTFSB1,
"FMOVD", LFMOV, AFMOVD,
"FMOVS", LFMOV, AFMOVS,
"FMOVDCC", LFCONV, AFMOVDCC, /* fmr. */
"GLOBL", LTEXT, AGLOBL,
"MOVB", LMOVB, AMOVB,
"MOVBZ", LMOVB, AMOVBZ,
"MOVBU", LMOVB, AMOVBU,
"MOVBZU", LMOVB, AMOVBZU,
"MOVH", LMOVB, AMOVH,
"MOVHZ", LMOVB, AMOVHZ,
"MOVHU", LMOVB, AMOVHU,
"MOVHZU", LMOVB, AMOVHZU,
"MOVHBR", LXMV, AMOVHBR,
"MOVWBR", LXMV, AMOVWBR,
"MOVW", LMOVW, AMOVW,
"MOVWU", LMOVW, AMOVWU,
"MOVMW", LMOVMW, AMOVMW,
"MOVFL", LMOVW, AMOVFL,
"MULLW", LADDW, AMULLW, /* includes multiply immediate 10-139 */
"MULLWV", LLOGW, AMULLWV,
"MULLWCC", LLOGW, AMULLWCC,
"MULLWVCC", LLOGW, AMULLWVCC,
"MULHW", LLOGW, AMULHW,
"MULHWCC", LLOGW, AMULHWCC,
"MULHWU", LLOGW, AMULHWU,
"MULHWUCC", LLOGW, AMULHWUCC,
"NEG", LABS, ANEG,
"NEGV", LABS, ANEGV,
"NEGCC", LABS, ANEGCC,
"NEGVCC", LABS, ANEGVCC,
"NOP", LNOP, ANOP, /* ori 0,0,0 */
"SYSCALL", LNOP, ASYSCALL,
"UNDEF", LNOP, AUNDEF,
"RETURN", LRETRN, ARETURN,
"RFI", LRETRN, ARFI,
"RFCI", LRETRN, ARFCI,
"DATA", LDATA, ADATA,
"END", LEND, AEND,
"TEXT", LTEXT, ATEXT,
/* 64-bit instructions */
"CNTLZD", LABS, ACNTLZD,
"CNTLZDCC", LABS, ACNTLZDCC,
"DIVD", LLOGW, ADIVD,
"DIVDCC", LLOGW, ADIVDCC,
"DIVDVCC", LLOGW, ADIVDVCC,
"DIVDV", LLOGW, ADIVDV,
"DIVDU", LLOGW, ADIVDU,
"DIVDUCC", LLOGW, ADIVDUCC,
"DIVDUVCC", LLOGW, ADIVDUVCC,
"DIVDUV", LLOGW, ADIVDUV,
"EXTSW", LABS, AEXTSW,
"EXTSWCC", LABS, AEXTSWCC,
"FCTID", LFCONV, AFCTID,
"FCTIDCC", LFCONV, AFCTIDCC,
"FCTIDZ", LFCONV, AFCTIDZ,
"FCTIDZCC", LFCONV, AFCTIDZCC,
"FCFID", LFCONV, AFCFID,
"FCFIDCC", LFCONV, AFCFIDCC,
"LDAR", LXLD, ALDAR,
"MOVD", LMOVW, AMOVD,
"MOVDU", LMOVW, AMOVDU,
"MOVWZ", LMOVW, AMOVWZ,
"MOVWZU", LMOVW, AMOVWZU,
"MULHD", LLOGW, AMULHD,
"MULHDCC", LLOGW, AMULHDCC,
"MULHDU", LLOGW, AMULHDU,
"MULHDUCC", LLOGW, AMULHDUCC,
"MULLD", LADDW, AMULLD, /* includes multiply immediate? */
"MULLDCC", LLOGW, AMULLDCC,
"MULLDVCC", LLOGW, AMULLDVCC,
"MULLDV", LLOGW, AMULLDV,
"RFID", LRETRN, ARFID,
"HRFID", LRETRN, AHRFID,
"RLDMI", LRLWM, ARLDMI,
"RLDMICC", LRLWM, ARLDMICC,
"RLDC", LRLWM, ARLDC,
"RLDCCC", LRLWM, ARLDCCC,
"RLDCR", LRLWM, ARLDCR,
"RLDCRCC", LRLWM, ARLDCRCC,
"RLDCL", LRLWM, ARLDCL,
"RLDCLCC", LRLWM, ARLDCLCC,
"SLBIA", LNOP, ASLBIA,
"SLBIE", LNOP, ASLBIE,
"SLBMFEE", LABS, ASLBMFEE,
"SLBMFEV", LABS, ASLBMFEV,
"SLBMTE", LABS, ASLBMTE,
"SLD", LSHW, ASLD,
"SLDCC", LSHW, ASLDCC,
"SRD", LSHW, ASRD,
"SRAD", LSHW, ASRAD,
"SRADCC", LSHW, ASRADCC,
"SRDCC", LSHW, ASRDCC,
"STDCCC", LXST, ASTDCCC,
"TD", LADDW, ATD,
/* pseudo instructions */
"REM", LLOGW, AREM,
"REMCC", LLOGW, AREMCC,
"REMV", LLOGW, AREMV,
"REMVCC", LLOGW, AREMVCC,
"REMU", LLOGW, AREMU,
"REMUCC", LLOGW, AREMUCC,
"REMUV", LLOGW, AREMUV,
"REMUVCC", LLOGW, AREMUVCC,
"REMD", LLOGW, AREMD,
"REMDCC", LLOGW, AREMDCC,
"REMDV", LLOGW, AREMDV,
"REMDVCC", LLOGW, AREMDVCC,
"REMDU", LLOGW, AREMDU,
"REMDUCC", LLOGW, AREMDUCC,
"REMDUV", LLOGW, AREMDUV,
"REMDUVCC", LLOGW, AREMDUVCC,
/* special instructions */
"DCBF", LXOP, ADCBF,
"DCBI", LXOP, ADCBI,
"DCBST", LXOP, ADCBST,
"DCBT", LXOP, ADCBT,
"DCBTST", LXOP, ADCBTST,
"DCBZ", LXOP, ADCBZ,
"ICBI", LXOP, AICBI,
"ECIWX", LXLD, AECIWX,
"ECOWX", LXST, AECOWX,
"LWAR", LXLD, ALWAR,
"LWAR", LXLD, ALWAR,
"STWCCC", LXST, ASTWCCC,
"EIEIO", LRETRN, AEIEIO,
"TLBIE", LNOP, ATLBIE,
"TLBIEL", LNOP, ATLBIEL,
"LSW", LXLD, ALSW,
"STSW", LXST, ASTSW,
"ISYNC", LRETRN, AISYNC,
"SYNC", LRETRN, ASYNC,
"TLBSYNC", LRETRN, ATLBSYNC,
"PTESYNC", LRETRN, APTESYNC,
/* "TW", LADDW, ATW,*/
"WORD", LWORD, AWORD,
"DWORD", LWORD, ADWORD,
"SCHED", LSCHED, 0,
"NOSCHED", LSCHED, 0x80,
"PCDATA", LPCDAT, APCDATA,
"FUNCDATA", LFUNCDAT, AFUNCDATA,
0
};
void
cinit(void)
{
Sym *s;
int i;
nullgen.type = D_NONE;
nullgen.name = D_NONE;
nullgen.reg = NREG;
nullgen.scale = NREG; // replaced Gen.xreg with Prog.scale
nerrors = 0;
iostack = I;
iofree = I;
peekc = IGN;
nhunk = 0;
for(i=0; i<NHASH; i++)
hash[i] = S;
for(i=0; itab[i].name; i++) {
s = slookup(itab[i].name);
s->type = itab[i].type;
s->value = itab[i].value;
}
}
void
syminit(Sym *s)
{
s->type = LNAME;
s->value = 0;
}
void
cclean(void)
{
outcode(AEND, &nullgen, NREG, &nullgen);
}
static Prog *lastpc;
void
outcode(int a, Addr *g1, int reg, Addr *g2)
{
Prog *p;
Plist *pl;
if(pass == 1)
goto out;
if(g1->scale != NREG) {
if(reg != NREG || g2->scale != NREG)
yyerror("bad addressing modes");
reg = g1->scale;
} else
if(g2->scale != NREG) {
if(reg != NREG)
yyerror("bad addressing modes");
reg = g2->scale;
}
p = ctxt->arch->prg();
p->as = a;
p->lineno = lineno;
if(nosched)
p->mark |= NOSCHED;
p->from = *g1;
p->reg = reg;
p->to = *g2;
p->pc = pc;
if(lastpc == nil) {
pl = linknewplist(ctxt);
pl->firstpc = p;
} else
lastpc->link = p;
lastpc = p;
out:
if(a != AGLOBL && a != ADATA)
pc++;
}
void
outgcode(int a, Addr *g1, int reg, Addr *g2, Addr *g3)
{
Prog *p;
Plist *pl;
if(pass == 1)
goto out;
p = ctxt->arch->prg();
p->as = a;
p->lineno = lineno;
if(nosched)
p->mark |= NOSCHED;
p->from = *g1;
p->reg = reg;
p->from3 = *g2;
p->to = *g3;
p->pc = pc;
if(lastpc == nil) {
pl = linknewplist(ctxt);
pl->firstpc = p;
} else
lastpc->link = p;
lastpc = p;
out:
if(a != AGLOBL && a != ADATA)
pc++;
}
#include "../cc/lexbody"
#include "../cc/macbody"

3398
src/cmd/9a/y.tab.c Normal file

File diff suppressed because it is too large Load Diff

188
src/cmd/9a/y.tab.h Normal file
View File

@@ -0,0 +1,188 @@
/* A Bison parser, made by GNU Bison 2.3. */
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
LMOVW = 258,
LMOVB = 259,
LABS = 260,
LLOGW = 261,
LSHW = 262,
LADDW = 263,
LCMP = 264,
LCROP = 265,
LBRA = 266,
LFMOV = 267,
LFCONV = 268,
LFCMP = 269,
LFADD = 270,
LFMA = 271,
LTRAP = 272,
LXORW = 273,
LNOP = 274,
LEND = 275,
LRETT = 276,
LWORD = 277,
LTEXT = 278,
LDATA = 279,
LRETRN = 280,
LCONST = 281,
LSP = 282,
LSB = 283,
LFP = 284,
LPC = 285,
LCREG = 286,
LFLUSH = 287,
LREG = 288,
LFREG = 289,
LR = 290,
LCR = 291,
LF = 292,
LFPSCR = 293,
LLR = 294,
LCTR = 295,
LSPR = 296,
LSPREG = 297,
LSEG = 298,
LMSR = 299,
LPCDAT = 300,
LFUNCDAT = 301,
LSCHED = 302,
LXLD = 303,
LXST = 304,
LXOP = 305,
LXMV = 306,
LRLWM = 307,
LMOVMW = 308,
LMOVEM = 309,
LMOVFL = 310,
LMTFSB = 311,
LMA = 312,
LFCONST = 313,
LSCONST = 314,
LNAME = 315,
LLAB = 316,
LVAR = 317
};
#endif
/* Tokens. */
#define LMOVW 258
#define LMOVB 259
#define LABS 260
#define LLOGW 261
#define LSHW 262
#define LADDW 263
#define LCMP 264
#define LCROP 265
#define LBRA 266
#define LFMOV 267
#define LFCONV 268
#define LFCMP 269
#define LFADD 270
#define LFMA 271
#define LTRAP 272
#define LXORW 273
#define LNOP 274
#define LEND 275
#define LRETT 276
#define LWORD 277
#define LTEXT 278
#define LDATA 279
#define LRETRN 280
#define LCONST 281
#define LSP 282
#define LSB 283
#define LFP 284
#define LPC 285
#define LCREG 286
#define LFLUSH 287
#define LREG 288
#define LFREG 289
#define LR 290
#define LCR 291
#define LF 292
#define LFPSCR 293
#define LLR 294
#define LCTR 295
#define LSPR 296
#define LSPREG 297
#define LSEG 298
#define LMSR 299
#define LPCDAT 300
#define LFUNCDAT 301
#define LSCHED 302
#define LXLD 303
#define LXST 304
#define LXOP 305
#define LXMV 306
#define LRLWM 307
#define LMOVMW 308
#define LMOVEM 309
#define LMOVFL 310
#define LMTFSB 311
#define LMA 312
#define LFCONST 313
#define LSCONST 314
#define LNAME 315
#define LLAB 316
#define LVAR 317
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 38 "a.y"
{
Sym *sym;
vlong lval;
double dval;
char sval[8];
Addr addr;
}
/* Line 1529 of yacc.c. */
#line 181 "y.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE yylval;

5
src/cmd/9c/Makefile Normal file
View File

@@ -0,0 +1,5 @@
# Copyright 2012 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
include ../../Make.dist

14
src/cmd/9c/Notes Normal file
View File

@@ -0,0 +1,14 @@
- effect of register expansion on 32-bit shifts and masks etc
9c
- multab
- floating-point conversions
- conversions of constants
- nodtype for loads
- sign-extension instruction (32-64) when in register?
- double indexing
- SLW (eg, in cat)
- scheduling
9l
- D_QCONST, DWORD
- maskgen

1147
src/cmd/9c/cgen.c Normal file

File diff suppressed because it is too large Load Diff

17
src/cmd/9c/doc.go Normal file
View File

@@ -0,0 +1,17 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
9c is a version of the Plan 9 C compiler. The original is documented at
http://plan9.bell-labs.com/magic/man2html/1/8c
Its target architecture is the Power64, referred to by these tools as
power64 (big endian) or power64le (little endian).
*/
package main

350
src/cmd/9c/gc.h Normal file
View File

@@ -0,0 +1,350 @@
// cmd/9c/gc.h from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include "../cc/cc.h"
#include "../9l/9.out.h"
/*
* 9c/powerpc64
*/
#define SZ_CHAR 1
#define SZ_SHORT 2
#define SZ_INT 4
#define SZ_LONG 4
#define SZ_IND 8
#define SZ_FLOAT 4
#define SZ_VLONG 8
#define SZ_DOUBLE 8
#define FNX 100
typedef struct Case Case;
typedef struct C1 C1;
typedef struct Multab Multab;
typedef struct Hintab Hintab;
typedef struct Reg Reg;
typedef struct Rgn Rgn;
#define A ((Adr*)0)
#define INDEXED 9
#define P ((Prog*)0)
struct Case
{
Case* link;
vlong val;
int32 label;
char def;
char isv;
};
#define C ((Case*)0)
struct C1
{
vlong val;
int32 label;
};
struct Multab
{
int32 val;
char code[20];
};
struct Hintab
{
ushort val;
char hint[10];
};
struct Reg
{
int32 pc;
int32 rpo; /* reverse post ordering */
Bits set;
Bits use1;
Bits use2;
Bits refbehind;
Bits refahead;
Bits calbehind;
Bits calahead;
Bits regdiff;
Bits act;
int32 regu;
int32 loop; /* could be shorter */
union
{
Reg* log5;
int32 active;
};
Reg* p1;
Reg* p2;
Reg* p2link;
Reg* s1;
Reg* s2;
Reg* link;
Prog* prog;
};
#define R ((Reg*)0)
#define NRGN 600
struct Rgn
{
Reg* enter;
short cost;
short varno;
short regno;
};
EXTERN int32 breakpc;
EXTERN int32 nbreak;
EXTERN Case* cases;
EXTERN Node constnode;
EXTERN Node fconstnode;
EXTERN Node vconstnode;
EXTERN int32 continpc;
EXTERN int32 curarg;
EXTERN int32 cursafe;
EXTERN Prog* lastp;
extern int hintabsize;
EXTERN int32 maxargsafe;
EXTERN Multab multab[20];
EXTERN int mnstring;
EXTERN Node* nodrat;
EXTERN Node* nodret;
EXTERN Node* nodsafe;
EXTERN int32 nrathole;
EXTERN int32 nstring;
EXTERN Prog* p;
EXTERN int32 pc;
EXTERN Node regnode;
EXTERN Node qregnode;
EXTERN char string[NSNAME];
EXTERN Sym* symrathole;
EXTERN Node znode;
EXTERN Prog zprog;
EXTERN int reg[NREG+NREG];
EXTERN int32 exregoffset;
EXTERN int32 exfregoffset;
EXTERN uchar typechlpv[NTYPE];
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
#define CLOAD 5
#define CREF 5
#define CINF 1000
#define LOOP 3
EXTERN Rgn region[NRGN];
EXTERN Rgn* rgp;
EXTERN int nregion;
EXTERN int nvar;
EXTERN Bits externs;
EXTERN Bits params;
EXTERN Bits consts;
EXTERN Bits addrs;
EXTERN int32 regbits;
EXTERN int32 exregbits;
EXTERN int change;
EXTERN int suppress;
EXTERN Reg* firstr;
EXTERN Reg* lastr;
EXTERN Reg zreg;
EXTERN Reg* freer;
EXTERN Var var[NVAR];
EXTERN int32* idom;
EXTERN Reg** rpo2r;
EXTERN int32 maxnr;
#define R0ISZERO (debug['0']==0)
extern char* anames[];
extern Hintab hintab[];
/*
* sgen.c
*/
void codgen(Node*, Node*);
void gen(Node*);
void usedset(Node*, int);
void noretval(int);
void xcom(Node*);
int bcomplex(Node*, Node*);
Prog* gtext(Sym*, int32);
vlong argsize(int);
/*
* cgen.c
*/
void cgen(Node*, Node*);
void reglcgen(Node*, Node*, Node*);
void lcgen(Node*, Node*);
void bcgen(Node*, int);
void boolgen(Node*, int, Node*);
void sugen(Node*, Node*, int32);
void layout(Node*, Node*, int, int, Node*);
/*
* txt.c
*/
void ginit(void);
void gclean(void);
void nextpc(void);
void gargs(Node*, Node*, Node*);
void garg1(Node*, Node*, Node*, int, Node**);
Node* nodconst(int32);
Node* nod32const(vlong);
Node* nodfconst(double);
Node* nodgconst(vlong v, Type *t);
void nodreg(Node*, Node*, int);
void regret(Node*, Node*, Type*, int);
void regalloc(Node*, Node*, Node*);
void regfree(Node*);
void regialloc(Node*, Node*, Node*);
void regsalloc(Node*, Node*);
void regaalloc1(Node*, Node*);
void regaalloc(Node*, Node*);
void regind(Node*, Node*);
void gprep(Node*, Node*);
void raddr(Node*, Prog*);
void naddr(Node*, Addr*);
void gmove(Node*, Node*);
void gins(int a, Node*, Node*);
void gopcode(int, Node*, Node*, Node*);
int samaddr(Node*, Node*);
void gbranch(int);
int immconst(Node*);
void patch(Prog*, int32);
int sconst(Node*);
int sval(int32);
int uconst(Node*);
void gpseudo(int, Sym*, Node*);
void gprefetch(Node*);
void gpcdata(int, int);
/*
* swt.c
*/
int swcmp(const void*, const void*);
void doswit(Node*);
void swit1(C1*, int, int32, Node*);
void swit2(C1*, int, int32, Node*, Node*);
void newcase(void);
void bitload(Node*, Node*, Node*, Node*, Node*);
void bitstore(Node*, Node*, Node*, Node*, Node*);
int32 outstring(char*, int32);
int mulcon(Node*, Node*);
Multab* mulcon0(Node*, int32);
int mulcon1(Node*, int32, Node*);
void nullwarn(Node*, Node*);
void sextern(Sym*, Node*, int32, int32);
void gextern(Sym*, Node*, int32, int32);
void outcode(void);
/*
* list
*/
void listinit(void);
int Pconv(Fmt*);
int Aconv(Fmt*);
int Dconv(Fmt*);
int Sconv(Fmt*);
int Nconv(Fmt*);
int Bconv(Fmt*);
/*
* reg.c
*/
Reg* rega(void);
int rcmp(const void*, const void*);
void regopt(Prog*);
void addmove(Reg*, int, int, int);
Bits mkvar(Addr*, int);
void prop(Reg*, Bits, Bits);
void loopit(Reg*, int32);
void synch(Reg*, Bits);
uint32 allreg(uint32, Rgn*);
void paint1(Reg*, int);
uint32 paint2(Reg*, int);
void paint3(Reg*, int, int32, int);
void addreg(Addr*, int);
/*
* peep.c
*/
void peep(void);
void excise(Reg*);
Reg* uniqp(Reg*);
Reg* uniqs(Reg*);
int regtyp(Addr*);
int regzer(Addr*);
int anyvar(Addr*);
int subprop(Reg*);
int copyprop(Reg*);
int copy1(Addr*, Addr*, Reg*, int);
int copyu(Prog*, Addr*, Addr*);
int copyas(Addr*, Addr*);
int copyau(Addr*, Addr*);
int copyau1(Prog*, Addr*);
int copysub(Addr*, Addr*, Addr*, int);
int copysub1(Prog*, Addr*, Addr*, int);
int32 RtoB(int);
int32 FtoB(int);
int BtoR(int32);
int BtoF(int32);
/*
* com64.c
*/
int com64(Node*);
void com64init(void);
void bool64(Node*);
#pragma varargck type "A" int
#pragma varargck type "B" Bits
#pragma varargck type "D" Addr*
#pragma varargck type "N" Addr*
#pragma varargck type "P" Prog*
#pragma varargck type "S" char*

37
src/cmd/9c/list.c Normal file
View File

@@ -0,0 +1,37 @@
// cmd/9c/list.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#define EXTERN
#include "gc.h"
void
listinit(void)
{
listinit9();
}

105
src/cmd/9c/machcap.c Normal file
View File

@@ -0,0 +1,105 @@
// cmd/9c/machcap.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "gc.h"
int
machcap(Node *n)
{
if(n == Z)
return 1; /* test */
switch(n->op) {
case OMUL:
case OLMUL:
case OASMUL:
case OASLMUL:
if(typechlv[n->type->etype])
return 1;
break;
case OADD:
case OAND:
case OOR:
case OSUB:
case OXOR:
case OASHL:
case OLSHR:
case OASHR:
if(typechlv[n->left->type->etype])
return 1;
break;
case OCAST:
return 1;
case OCOND:
case OCOMMA:
case OLIST:
case OANDAND:
case OOROR:
case ONOT:
return 1;
case OASADD:
case OASSUB:
case OASAND:
case OASOR:
case OASXOR:
return 1;
case OASASHL:
case OASASHR:
case OASLSHR:
return 1;
case OPOSTINC:
case OPOSTDEC:
case OPREINC:
case OPREDEC:
return 1;
case OEQ:
case ONE:
case OLE:
case OGT:
case OLT:
case OGE:
case OHI:
case OHS:
case OLO:
case OLS:
return 1;
case ONEG:
case OCOM:
break;
}
return 0;
}

638
src/cmd/9c/mul.c Normal file
View File

@@ -0,0 +1,638 @@
// cmd/9c/mul.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "gc.h"
/*
* code sequences for multiply by constant.
* [a-l][0-3]
* lsl $(A-'a'),r0,r1
* [+][0-7]
* add r0,r1,r2
* [-][0-7]
* sub r0,r1,r2
*/
static int multabp;
static int32 mulval;
static char* mulcp;
static int32 valmax;
static int shmax;
static int docode(char *hp, char *cp, int r0, int r1);
static int gen1(int len);
static int gen2(int len, int32 r1);
static int gen3(int len, int32 r0, int32 r1, int flag);
enum
{
SR1 = 1<<0, /* r1 has been shifted */
SR0 = 1<<1, /* r0 has been shifted */
UR1 = 1<<2, /* r1 has not been used */
UR0 = 1<<3, /* r0 has not been used */
};
Multab*
mulcon0(Node *n, int32 v)
{
int a1, a2, g;
Multab *m, *m1;
char hint[10];
if(v < 0)
v = -v;
/*
* look in cache
*/
m = multab;
for(g=0; g<nelem(multab); g++) {
if(m->val == v) {
if(m->code[0] == 0)
return 0;
return m;
}
m++;
}
/*
* select a spot in cache to overwrite
*/
multabp++;
if(multabp < 0 || multabp >= nelem(multab))
multabp = 0;
m = multab+multabp;
m->val = v;
mulval = v;
/*
* look in execption hint table
*/
a1 = 0;
a2 = hintabsize;
for(;;) {
if(a1 >= a2)
goto no;
g = (a2 + a1)/2;
if(v < hintab[g].val) {
a2 = g;
continue;
}
if(v > hintab[g].val) {
a1 = g+1;
continue;
}
break;
}
if(docode(hintab[g].hint, m->code, 1, 0))
return m;
print("%L: multiply table failure %ld\n", n->lineno, v);
m->code[0] = 0;
return 0;
no:
/*
* try to search
*/
hint[0] = 0;
for(g=1; g<=6; g++) {
if(g >= 6 && v >= 65535)
break;
mulcp = hint+g;
*mulcp = 0;
if(gen1(g)) {
if(docode(hint, m->code, 1, 0))
return m;
print("%L: multiply table failure (g=%d h=%s) %ld\n",
n->lineno, g, hint, v);
break;
}
}
/*
* try a recur followed by a shift
*/
g = 0;
while(!(v & 1)) {
g++;
v >>= 1;
}
if(g) {
m1 = mulcon0(n, v);
if(m1) {
strcpy(m->code, m1->code);
sprint(strchr(m->code, 0), "%c0", g+'a');
return m;
}
}
m->code[0] = 0;
return 0;
}
static int
docode(char *hp, char *cp, int r0, int r1)
{
int c, i;
c = *hp++;
*cp = c;
cp += 2;
switch(c) {
default:
c -= 'a';
if(c < 1 || c >= 30)
break;
for(i=0; i<4; i++) {
switch(i) {
case 0:
if(docode(hp, cp, r0<<c, r1))
goto out;
break;
case 1:
if(docode(hp, cp, r1<<c, r1))
goto out;
break;
case 2:
if(docode(hp, cp, r0, r0<<c))
goto out;
break;
case 3:
if(docode(hp, cp, r0, r1<<c))
goto out;
break;
}
}
break;
case '+':
for(i=0; i<8; i++) {
cp[-1] = i+'0';
switch(i) {
case 1:
if(docode(hp, cp, r0+r1, r1))
goto out;
break;
case 5:
if(docode(hp, cp, r0, r0+r1))
goto out;
break;
}
}
break;
case '-':
for(i=0; i<8; i++) {
cp[-1] = i+'0';
switch(i) {
case 1:
if(docode(hp, cp, r0-r1, r1))
goto out;
break;
case 2:
if(docode(hp, cp, r1-r0, r1))
goto out;
break;
case 5:
if(docode(hp, cp, r0, r0-r1))
goto out;
break;
case 6:
if(docode(hp, cp, r0, r1-r0))
goto out;
break;
}
}
break;
case 0:
if(r0 == mulval)
return 1;
}
return 0;
out:
cp[-1] = i+'0';
return 1;
}
static int
gen1(int len)
{
int i;
for(shmax=1; shmax<30; shmax++) {
valmax = 1<<shmax;
if(valmax >= mulval)
break;
}
if(mulval == 1)
return 1;
len--;
for(i=1; i<=shmax; i++)
if(gen2(len, 1<<i)) {
*--mulcp = 'a'+i;
return 1;
}
return 0;
}
static int
gen2(int len, int32 r1)
{
int i;
if(len <= 0) {
if(r1 == mulval)
return 1;
return 0;
}
len--;
if(len == 0)
goto calcr0;
if(gen3(len, r1, r1+1, UR1)) {
i = '+';
goto out;
}
if(gen3(len, r1-1, r1, UR0)) {
i = '-';
goto out;
}
if(gen3(len, 1, r1+1, UR1)) {
i = '+';
goto out;
}
if(gen3(len, 1, r1-1, UR1)) {
i = '-';
goto out;
}
return 0;
calcr0:
if(mulval == r1+1) {
i = '+';
goto out;
}
if(mulval == r1-1) {
i = '-';
goto out;
}
return 0;
out:
*--mulcp = i;
return 1;
}
static int
gen3(int len, int32 r0, int32 r1, int flag)
{
int i, f1, f2;
int32 x;
if(r0 <= 0 ||
r0 >= r1 ||
r1 > valmax)
return 0;
len--;
if(len == 0)
goto calcr0;
if(!(flag & UR1)) {
f1 = UR1|SR1;
for(i=1; i<=shmax; i++) {
x = r0<<i;
if(x > valmax)
break;
if(gen3(len, r0, x, f1)) {
i += 'a';
goto out;
}
}
}
if(!(flag & UR0)) {
f1 = UR1|SR1;
for(i=1; i<=shmax; i++) {
x = r1<<i;
if(x > valmax)
break;
if(gen3(len, r1, x, f1)) {
i += 'a';
goto out;
}
}
}
if(!(flag & SR1)) {
f1 = UR1|SR1|(flag&UR0);
for(i=1; i<=shmax; i++) {
x = r1<<i;
if(x > valmax)
break;
if(gen3(len, r0, x, f1)) {
i += 'a';
goto out;
}
}
}
if(!(flag & SR0)) {
f1 = UR0|SR0|(flag&(SR1|UR1));
f2 = UR1|SR1;
if(flag & UR1)
f2 |= UR0;
if(flag & SR1)
f2 |= SR0;
for(i=1; i<=shmax; i++) {
x = r0<<i;
if(x > valmax)
break;
if(x > r1) {
if(gen3(len, r1, x, f2)) {
i += 'a';
goto out;
}
} else
if(gen3(len, x, r1, f1)) {
i += 'a';
goto out;
}
}
}
x = r1+r0;
if(gen3(len, r0, x, UR1)) {
i = '+';
goto out;
}
if(gen3(len, r1, x, UR1)) {
i = '+';
goto out;
}
x = r1-r0;
if(gen3(len, x, r1, UR0)) {
i = '-';
goto out;
}
if(x > r0) {
if(gen3(len, r0, x, UR1)) {
i = '-';
goto out;
}
} else
if(gen3(len, x, r0, UR0)) {
i = '-';
goto out;
}
return 0;
calcr0:
f1 = flag & (UR0|UR1);
if(f1 == UR1) {
for(i=1; i<=shmax; i++) {
x = r1<<i;
if(x >= mulval) {
if(x == mulval) {
i += 'a';
goto out;
}
break;
}
}
}
if(mulval == r1+r0) {
i = '+';
goto out;
}
if(mulval == r1-r0) {
i = '-';
goto out;
}
return 0;
out:
*--mulcp = i;
return 1;
}
/*
* hint table has numbers that
* the search algorithm fails on.
* <1000:
* all numbers
* <5000:
* ÷ by 5
* <10000:
* ÷ by 50
* <65536:
* ÷ by 250
*/
Hintab hintab[] =
{
683, "b++d+e+",
687, "b+e++e-",
691, "b++d+e+",
731, "b++d+e+",
811, "b++d+i+",
821, "b++e+e+",
843, "b+d++e+",
851, "b+f-+e-",
853, "b++e+e+",
877, "c++++g-",
933, "b+c++g-",
981, "c-+e-d+",
1375, "b+c+b+h-",
1675, "d+b++h+",
2425, "c++f-e+",
2675, "c+d++f-",
2750, "b+d-b+h-",
2775, "c-+g-e-",
3125, "b++e+g+",
3275, "b+c+g+e+",
3350, "c++++i+",
3475, "c-+e-f-",
3525, "c-+d+g-",
3625, "c-+e-j+",
3675, "b+d+d+e+",
3725, "b+d-+h+",
3925, "b+d+f-d-",
4275, "b+g++e+",
4325, "b+h-+d+",
4425, "b+b+g-j-",
4525, "b+d-d+f+",
4675, "c++d-g+",
4775, "b+d+b+g-",
4825, "c+c-+i-",
4850, "c++++i-",
4925, "b++e-g-",
4975, "c+f++e-",
5500, "b+g-c+d+",
6700, "d+b++i+",
9700, "d++++j-",
11000, "b+f-c-h-",
11750, "b+d+g+j-",
12500, "b+c+e-k+",
13250, "b+d+e-f+",
13750, "b+h-c-d+",
14250, "b+g-c+e-",
14500, "c+f+j-d-",
14750, "d-g--f+",
16750, "b+e-d-n+",
17750, "c+h-b+e+",
18250, "d+b+h-d+",
18750, "b+g-++f+",
19250, "b+e+b+h+",
19750, "b++h--f-",
20250, "b+e-l-c+",
20750, "c++bi+e-",
21250, "b+i+l+c+",
22000, "b+e+d-g-",
22250, "b+d-h+k-",
22750, "b+d-e-g+",
23250, "b+c+h+e-",
23500, "b+g-c-g-",
23750, "b+g-b+h-",
24250, "c++g+m-",
24750, "b+e+e+j-",
25000, "b++dh+g+",
25250, "b+e+d-g-",
25750, "b+e+b+j+",
26250, "b+h+c+e+",
26500, "b+h+c+g+",
26750, "b+d+e+g-",
27250, "b+e+e+f+",
27500, "c-i-c-d+",
27750, "b+bd++j+",
28250, "d-d-++i-",
28500, "c+c-h-e-",
29000, "b+g-d-f+",
29500, "c+h+++e-",
29750, "b+g+f-c+",
30250, "b+f-g-c+",
33500, "c-f-d-n+",
33750, "b+d-b+j-",
34250, "c+e+++i+",
35250, "e+b+d+k+",
35500, "c+e+d-g-",
35750, "c+i-++e+",
36250, "b+bh-d+e+",
36500, "c+c-h-e-",
36750, "d+e--i+",
37250, "b+g+g+b+",
37500, "b+h-b+f+",
37750, "c+be++j-",
38500, "b+e+b+i+",
38750, "d+i-b+d+",
39250, "b+g-l-+d+",
39500, "b+g-c+g-",
39750, "b+bh-c+f-",
40250, "b+bf+d+g-",
40500, "b+g-c+g+",
40750, "c+b+i-e+",
41250, "d++bf+h+",
41500, "b+j+c+d-",
41750, "c+f+b+h-",
42500, "c+h++g+",
42750, "b+g+d-f-",
43250, "b+l-e+d-",
43750, "c+bd+h+f-",
44000, "b+f+g-d-",
44250, "b+d-g--f+",
44500, "c+e+c+h+",
44750, "b+e+d-h-",
45250, "b++g+j-g+",
45500, "c+d+e-g+",
45750, "b+d-h-e-",
46250, "c+bd++j+",
46500, "b+d-c-j-",
46750, "e-e-b+g-",
47000, "b+c+d-j-",
47250, "b+e+e-g-",
47500, "b+g-c-h-",
47750, "b+f-c+h-",
48250, "d--h+n-",
48500, "b+c-g+m-",
48750, "b+e+e-g+",
49500, "c-f+e+j-",
49750, "c+c+g++f-",
50000, "b+e+e+k+",
50250, "b++i++g+",
50500, "c+g+f-i+",
50750, "b+e+d+k-",
51500, "b+i+c-f+",
51750, "b+bd+g-e-",
52250, "b+d+g-j+",
52500, "c+c+f+g+",
52750, "b+c+e+i+",
53000, "b+i+c+g+",
53500, "c+g+g-n+",
53750, "b+j+d-c+",
54250, "b+d-g-j-",
54500, "c-f+e+f+",
54750, "b+f-+c+g+",
55000, "b+g-d-g-",
55250, "b+e+e+g+",
55500, "b+cd++j+",
55750, "b+bh-d-f-",
56250, "c+d-b+j-",
56500, "c+d+c+i+",
56750, "b+e+d++h-",
57000, "b+d+g-f+",
57250, "b+f-m+d-",
57750, "b+i+c+e-",
58000, "b+e+d+h+",
58250, "c+b+g+g+",
58750, "d-e-j--e+",
59000, "d-i-+e+",
59250, "e--h-m+",
59500, "c+c-h+f-",
59750, "b+bh-e+i-",
60250, "b+bh-e-e-",
60500, "c+c-g-g-",
60750, "b+e-l-e-",
61250, "b+g-g-c+",
61750, "b+g-c+g+",
62250, "f--+c-i-",
62750, "e+f--+g+",
64750, "b+f+d+p-",
};
int hintabsize = nelem(hintab);

1076
src/cmd/9c/peep.c Normal file

File diff suppressed because it is too large Load Diff

1163
src/cmd/9c/reg.c Normal file

File diff suppressed because it is too large Load Diff

291
src/cmd/9c/sgen.c Normal file
View File

@@ -0,0 +1,291 @@
// cmd/9c/sgen.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "gc.h"
Prog*
gtext(Sym *s, int32 stkoff)
{
vlong v;
v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
if((textflag & NOSPLIT) && stkoff >= 128)
yyerror("stack frame too large for NOSPLIT function");
gpseudo(ATEXT, s, nodgconst(v, types[TVLONG]));
return p;
}
void
noretval(int n)
{
if(n & 1) {
gins(ANOP, Z, Z);
p->to.type = D_REG;
p->to.reg = REGRET;
}
if(n & 2) {
gins(ANOP, Z, Z);
p->to.type = D_FREG;
p->to.reg = FREGRET;
}
}
/*
* calculate addressability as follows
* CONST ==> 20 $value
* NAME ==> 10 name
* REGISTER ==> 11 register
* INDREG ==> 12 *[(reg)+offset]
* &10 ==> 2 $name
* ADD(2, 20) ==> 2 $name+offset
* ADD(3, 20) ==> 3 $(reg)+offset
* &12 ==> 3 $(reg)+offset
* *11 ==> 11 ??
* *2 ==> 10 name
* *3 ==> 12 *(reg)+offset
* calculate complexity (number of registers)
*/
void
xcom(Node *n)
{
Node *l, *r;
int v;
if(n == Z)
return;
l = n->left;
r = n->right;
n->addable = 0;
n->complex = 0;
switch(n->op) {
case OCONST:
n->addable = 20;
return;
case OREGISTER:
n->addable = 11;
return;
case OINDREG:
n->addable = 12;
return;
case ONAME:
n->addable = 10;
return;
case OADDR:
xcom(l);
if(l->addable == 10)
n->addable = 2;
if(l->addable == 12)
n->addable = 3;
break;
case OIND:
xcom(l);
if(l->addable == 11)
n->addable = 12;
if(l->addable == 3)
n->addable = 12;
if(l->addable == 2)
n->addable = 10;
break;
case OADD:
xcom(l);
xcom(r);
if(l->addable == 20) {
if(r->addable == 2)
n->addable = 2;
if(r->addable == 3)
n->addable = 3;
}
if(r->addable == 20) {
if(l->addable == 2)
n->addable = 2;
if(l->addable == 3)
n->addable = 3;
}
break;
case OASMUL:
case OASLMUL:
xcom(l);
xcom(r);
v = vlog(r);
if(v >= 0) {
n->op = OASASHL;
r->vconst = v;
r->type = types[TINT];
}
break;
case OMUL:
case OLMUL:
xcom(l);
xcom(r);
v = vlog(r);
if(v >= 0) {
n->op = OASHL;
r->vconst = v;
r->type = types[TINT];
}
v = vlog(l);
if(v >= 0) {
n->op = OASHL;
n->left = r;
n->right = l;
r = l;
l = n->left;
r->vconst = v;
r->type = types[TINT];
simplifyshift(n);
}
break;
case OASLDIV:
xcom(l);
xcom(r);
v = vlog(r);
if(v >= 0) {
n->op = OASLSHR;
r->vconst = v;
r->type = types[TINT];
}
break;
case OLDIV:
xcom(l);
xcom(r);
v = vlog(r);
if(v >= 0) {
n->op = OLSHR;
r->vconst = v;
r->type = types[TINT];
simplifyshift(n);
}
break;
case OASLMOD:
xcom(l);
xcom(r);
v = vlog(r);
if(v >= 0) {
n->op = OASAND;
r->vconst--;
}
break;
case OLMOD:
xcom(l);
xcom(r);
v = vlog(r);
if(v >= 0) {
n->op = OAND;
r->vconst--;
}
break;
case OLSHR:
case OASHL:
case OASHR:
xcom(l);
xcom(r);
simplifyshift(n);
break;
default:
if(l != Z)
xcom(l);
if(r != Z)
xcom(r);
break;
}
if(n->addable >= 10)
return;
if(l != Z)
n->complex = l->complex;
if(r != Z) {
if(r->complex == n->complex)
n->complex = r->complex+1;
else
if(r->complex > n->complex)
n->complex = r->complex;
}
if(n->complex == 0)
n->complex++;
// if(com64(n))
// return;
switch(n->op) {
case OFUNC:
n->complex = FNX;
break;
case OEQ:
case ONE:
case OLE:
case OLT:
case OGE:
case OGT:
case OHI:
case OHS:
case OLO:
case OLS:
/*
* immediate operators, make const on right
*/
if(l->op == OCONST) {
n->left = r;
n->right = l;
n->op = invrel[relindex(n->op)];
}
break;
case OADD:
case OXOR:
case OAND:
case OOR:
/*
* immediate operators, make const on right
*/
if(l->op == OCONST) {
n->left = r;
n->right = l;
}
break;
}
}

407
src/cmd/9c/swt.c Normal file
View File

@@ -0,0 +1,407 @@
// cmd/9c/swt.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "gc.h"
void
swit1(C1 *q, int nc, int32 def, Node *n)
{
Node tn, nod;
regalloc(&nod, n, Z);
/* always signed */
if(typev[n->type->etype])
nod.type = types[TVLONG];
else
nod.type = types[TLONG];
cgen(n, &nod);
regalloc(&tn, &regnode, Z);
swit2(q, nc, def, &nod, &tn);
regfree(&tn);
regfree(&nod);
}
void
swit2(C1 *q, int nc, int32 def, Node *n, Node *tn)
{
C1 *r;
int i;
Prog *sp;
if(nc < 5) {
for(i=0; i<nc; i++) {
if(sval(q->val)) {
gopcode(OEQ, n, Z, nodconst(q->val));
} else {
gopcode(OSUB, nodconst(q->val), n, tn);
gopcode(OEQ, tn, Z, nodconst(0));
}
patch(p, q->label);
q++;
}
gbranch(OGOTO);
patch(p, def);
return;
}
i = nc / 2;
r = q+i;
if(sval(r->val)) {
gopcode(OGT, n, Z, nodconst(r->val));
sp = p;
} else {
gopcode(OSUB, nodconst(r->val), n, tn);
gopcode(OGT, tn, Z, nodconst(0));
sp = p;
}
gbranch(OGOTO);
p->as = ABEQ;
patch(p, r->label);
swit2(q, i, def, n, tn);
patch(sp, pc);
swit2(r+1, nc-i-1, def, n, tn);
}
void
bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
{
int sh;
int32 v;
Node *l;
/*
* n1 gets adjusted/masked value
* n2 gets address of cell
* n3 gets contents of cell
*/
l = b->left;
if(n2 != Z) {
regalloc(n1, l, nn);
reglcgen(n2, l, Z);
regalloc(n3, l, Z);
gopcode(OAS, n2, Z, n3);
gopcode(OAS, n3, Z, n1);
} else {
regalloc(n1, l, nn);
cgen(l, n1);
}
if(b->type->shift == 0 && typeu[b->type->etype]) {
v = ~0 + (1L << b->type->nbits);
gopcode(OAND, nodconst(v), Z, n1);
} else {
sh = 32 - b->type->shift - b->type->nbits;
if(sh > 0)
gopcode(OASHL, nodconst(sh), Z, n1);
sh += b->type->shift;
if(sh > 0)
if(typeu[b->type->etype])
gopcode(OLSHR, nodconst(sh), Z, n1);
else
gopcode(OASHR, nodconst(sh), Z, n1);
}
}
void
bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
{
int32 v;
Node nod, *l;
int sh;
/*
* n1 has adjusted/masked value
* n2 has address of cell
* n3 has contents of cell
*/
l = b->left;
regalloc(&nod, l, Z);
v = ~0 + (1L << b->type->nbits);
gopcode(OAND, nodconst(v), Z, n1);
gopcode(OAS, n1, Z, &nod);
if(nn != Z)
gopcode(OAS, n1, Z, nn);
sh = b->type->shift;
if(sh > 0)
gopcode(OASHL, nodconst(sh), Z, &nod);
v <<= sh;
gopcode(OAND, nodconst(~v), Z, n3);
gopcode(OOR, n3, Z, &nod);
gopcode(OAS, &nod, Z, n2);
regfree(&nod);
regfree(n1);
regfree(n2);
regfree(n3);
}
int32
outstring(char *s, int32 n)
{
int32 r;
if(suppress)
return nstring;
r = nstring;
while(n) {
string[mnstring] = *s++;
mnstring++;
nstring++;
if(mnstring >= NSNAME) {
gpseudo(ADATA, symstring, nodconst(0L));
p->from.offset += nstring - NSNAME;
p->reg = NSNAME;
p->to.type = D_SCONST;
memmove(p->to.u.sval, string, NSNAME);
mnstring = 0;
}
n--;
}
return r;
}
int
mulcon(Node *n, Node *nn)
{
Node *l, *r, nod1, nod2;
Multab *m;
int32 v;
int o;
char code[sizeof(m->code)+2], *p;
if(typefd[n->type->etype])
return 0;
l = n->left;
r = n->right;
if(l->op == OCONST) {
l = r;
r = n->left;
}
if(r->op != OCONST)
return 0;
v = convvtox(r->vconst, n->type->etype);
if(v != r->vconst) {
if(debug['M'])
print("%L multiply conv: %lld\n", n->lineno, r->vconst);
return 0;
}
m = mulcon0(n, v);
if(!m) {
if(debug['M'])
print("%L multiply table: %lld\n", n->lineno, r->vconst);
return 0;
}
memmove(code, m->code, sizeof(m->code));
code[sizeof(m->code)] = 0;
p = code;
if(p[1] == 'i')
p += 2;
regalloc(&nod1, n, nn);
cgen(l, &nod1);
if(v < 0)
gopcode(ONEG, &nod1, Z, &nod1);
regalloc(&nod2, n, Z);
loop:
switch(*p) {
case 0:
regfree(&nod2);
gopcode(OAS, &nod1, Z, nn);
regfree(&nod1);
return 1;
case '+':
o = OADD;
goto addsub;
case '-':
o = OSUB;
addsub: /* number is r,n,l */
v = p[1] - '0';
r = &nod1;
if(v&4)
r = &nod2;
n = &nod1;
if(v&2)
n = &nod2;
l = &nod1;
if(v&1)
l = &nod2;
gopcode(o, l, n, r);
break;
default: /* op is shiftcount, number is r,l */
v = p[1] - '0';
r = &nod1;
if(v&2)
r = &nod2;
l = &nod1;
if(v&1)
l = &nod2;
v = *p - 'a';
if(v < 0 || v >= 32) {
diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
break;
}
gopcode(OASHL, nodconst(v), l, r);
break;
}
p += 2;
goto loop;
}
void
sextern(Sym *s, Node *a, int32 o, int32 w)
{
int32 e, lw;
for(e=0; e<w; e+=NSNAME) {
lw = NSNAME;
if(w-e < lw)
lw = w-e;
gpseudo(ADATA, s, nodconst(0));
p->from.offset += o+e;
p->reg = lw;
p->to.type = D_SCONST;
memmove(p->to.u.sval, a->cstring+e, lw);
}
}
void
gextern(Sym *s, Node *a, int32 o, int32 w)
{
gpseudo(ADATA, s, a);
p->from.offset += o;
p->reg = w;
if(p->to.type == D_OREG)
p->to.type = D_CONST;
}
void
outcode(void)
{
Bprint(&outbuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
if(pragcgobuf.to > pragcgobuf.start) {
Bprint(&outbuf, "\n");
Bprint(&outbuf, "$$ // exports\n\n");
Bprint(&outbuf, "$$ // local types\n\n");
Bprint(&outbuf, "$$ // cgo\n");
Bprint(&outbuf, "%s", fmtstrflush(&pragcgobuf));
Bprint(&outbuf, "\n$$\n\n");
}
Bprint(&outbuf, "!\n");
writeobj(ctxt, &outbuf);
lastp = nil;
}
int32
align(int32 i, Type *t, int op, int32 *maxalign)
{
int32 o;
Type *v;
int w, packw;
o = i;
w = 1;
packw = 0;
switch(op) {
default:
diag(Z, "unknown align opcode %d", op);
break;
case Asu2: /* padding at end of a struct */
w = *maxalign;
if(w < 1)
w = 1;
if(packflg)
packw = packflg;
break;
case Ael1: /* initial allign of struct element */
for(v=t; v->etype==TARRAY; v=v->link)
;
if(v->etype == TSTRUCT || v->etype == TUNION)
w = v->align;
else
w = ewidth[v->etype];
if(w < 1 || w > SZ_VLONG)
fatal(Z, "align");
if(packflg)
packw = packflg;
break;
case Ael2: /* width of a struct element */
o += t->width;
break;
case Aarg0: /* initial passbyptr argument in arg list */
if(typesu[t->etype]) {
o = align(o, types[TIND], Aarg1, nil);
o = align(o, types[TIND], Aarg2, nil);
}
break;
case Aarg1: /* initial align of parameter */
w = ewidth[t->etype];
if(w <= 0 || w >= SZ_VLONG) {
w = SZ_VLONG;
break;
}
w = 1;
break;
case Aarg2: /* width of a parameter */
o += t->width;
w = t->width;
if(w > SZ_VLONG)
w = SZ_VLONG;
break;
case Aaut3: /* total align of automatic */
o = align(o, t, Ael1, nil);
o = align(o, t, Ael2, nil);
break;
}
if(packw != 0 && xround(o, w) != xround(o, packw))
diag(Z, "#pragma pack changes offset of %T", t);
o = xround(o, w);
if(maxalign && *maxalign < w)
*maxalign = w;
if(debug['A'])
print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
return o;
}
int32
maxround(int32 max, int32 v)
{
v = xround(v, SZ_VLONG);
if(v > max)
return v;
return max;
}

1537
src/cmd/9c/txt.c Normal file

File diff suppressed because it is too large Load Diff

1763
src/cmd/9g/cgen.c Normal file

File diff suppressed because it is too large Load Diff

16
src/cmd/9g/doc.go Normal file
View File

@@ -0,0 +1,16 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
9g is the version of the gc compiler for the Power64.
The $GOARCH for these tools is power64 (big endian) or
power64le (little endian).
It reads .go files and outputs .9 files. The flags are documented in ../gc/doc.go.
*/
package main

54
src/cmd/9g/galign.c Normal file
View File

@@ -0,0 +1,54 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <u.h>
#include <libc.h>
#include "gg.h"
int thechar = '9';
char* thestring = "power64";
LinkArch* thelinkarch;
void
linkarchinit(void)
{
thestring = getgoarch();
if(strcmp(thestring, "power64le") == 0)
thelinkarch = &linkpower64le;
else
thelinkarch = &linkpower64;
}
vlong MAXWIDTH = 1LL<<50;
/*
* go declares several platform-specific type aliases:
* int, uint, float, and uintptr
*/
Typedef typedefs[] =
{
{"int", TINT, TINT64},
{"uint", TUINT, TUINT64},
{"uintptr", TUINTPTR, TUINT64},
{0}
};
void
betypeinit(void)
{
widthptr = 8;
widthint = 8;
widthreg = 8;
zprog.link = P;
zprog.as = AGOK;
zprog.reg = NREG;
zprog.from.name = D_NONE;
zprog.from.type = D_NONE;
zprog.from.reg = NREG;
zprog.to = zprog.from;
zprog.from3 = zprog.from;
listinit9();
}

117
src/cmd/9g/gg.h Normal file
View File

@@ -0,0 +1,117 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#ifndef EXTERN
#define EXTERN extern
#endif
#include "../gc/go.h"
#include "../9l/9.out.h"
// TODO(minux): Remove when no longer used.
#define noimpl sysfatal("%s not implemented (%s:%d).", __func__, __FILE__, __LINE__)
#define TEXTFLAG reg
EXTERN int32 dynloc;
EXTERN uchar reg[NREG+NFREG];
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
EXTERN Prog zprog;
EXTERN Node* newproc;
EXTERN Node* deferproc;
EXTERN Node* deferreturn;
EXTERN Node* panicindex;
EXTERN Node* panicslice;
EXTERN Node* panicdiv;
EXTERN Node* throwreturn;
extern vlong unmappedzero;
/*
* ggen.c
*/
void compile(Node*);
void gen(Node*);
Node* lookdot(Node*, Node*, int);
void cgen_as(Node*, Node*);
void cgen_callmeth(Node*, int);
void cgen_callinter(Node*, Node*, int);
void cgen_proc(Node*, int);
void cgen_callret(Node*, Node*);
void cgen_div(int, Node*, Node*, Node*);
void cgen_hmul(Node*, Node*, Node*);
void cgen_shift(int, int, Node*, Node*, Node*);
void cgen_dcl(Node*);
int needconvert(Type*, Type*);
void genconv(Type*, Type*);
void allocparams(void);
void checklabels(void);
void ginscall(Node*, int);
int gen_as_init(Node*);
/*
* cgen.c
*/
void agen(Node*, Node*);
void agenr(Node*, Node*, Node*);
void cgenr(Node*, Node*, Node*);
void igen(Node*, Node*, Node*);
vlong fieldoffset(Type*, Node*);
void sgen(Node*, Node*, int64);
void gmove(Node*, Node*);
Prog* gins(int, Node*, Node*);
void naddr(Node*, Addr*, int);
void cgen_aret(Node*, Node*);
int componentgen(Node*, Node*);
/*
* gsubr.c
*/
void clearp(Prog*);
Prog* gbranch(int, Type*, int);
Prog* prog(int);
void gconv(int, int);
int conv2pt(Type*);
vlong convvtox(vlong, int);
void fnparam(Type*, int, int);
Prog* gop(int, Node*, Node*, Node*);
int optoas(int, Type*);
void ginit(void);
void gclean(void);
void regalloc(Node*, Type*, Node*);
void regfree(Node*);
Node* nodarg(Type*, int);
void nodreg(Node*, Type*, int);
void nodindreg(Node*, Type*, int);
void ginscon(int, vlong, Node*);
void ginscon2(int, Node*, vlong);
void buildtxt(void);
Plist* newplist(void);
int isfat(Type*);
void sudoclean(void);
int sudoaddable(int, Node*, Addr*);
void afunclit(Addr*, Node*);
void nodfconst(Node*, Type*, Mpflt*);
void gtrack(Sym*);
void fixlargeoffset(Node *n);
/*
* cplx.c
*/
int complexop(Node*, Node*);
void complexmove(Node*, Node*);
void complexgen(Node*, Node*);
/*
* gobj.c
*/
void datastring(char*, int, Addr*);
void datagostring(Strlit*, Addr*);
/*
* list.c
*/
void listinit(void);
void zaddr(Biobuf*, Addr*, int, int);

1040
src/cmd/9g/ggen.c Normal file

File diff suppressed because it is too large Load Diff

240
src/cmd/9g/gobj.c Normal file
View File

@@ -0,0 +1,240 @@
// Derived from Inferno utils/6c/swt.c
// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
int
dsname(Sym *s, int off, char *t, int n)
{
Prog *p;
p = gins(ADATA, N, N);
p->from.type = D_OREG;
p->from.name = D_EXTERN;
p->from.offset = off;
p->from.reg = NREG;
p->from.sym = linksym(s);
p->reg = n;
p->to.type = D_SCONST;
p->to.name = D_NONE;
p->to.reg = NREG;
p->to.offset = 0;
memmove(p->to.u.sval, t, n);
return off + n;
}
/*
* make a refer to the data s, s+len
* emitting DATA if needed.
*/
void
datastring(char *s, int len, Addr *a)
{
Sym *sym;
sym = stringsym(s, len);
a->type = D_OREG;
a->name = D_EXTERN;
a->etype = simtype[TINT];
a->offset = widthptr+widthint; // skip header
a->reg = NREG;
a->sym = linksym(sym);
a->node = sym->def;
}
/*
* make a refer to the string sval,
* emitting DATA if needed.
*/
void
datagostring(Strlit *sval, Addr *a)
{
Sym *sym;
sym = stringsym(sval->s, sval->len);
a->type = D_OREG;
a->name = D_EXTERN;
a->sym = linksym(sym);
a->reg = NREG;
a->node = sym->def;
a->offset = 0; // header
a->etype = TSTRING;
}
void
gdata(Node *nam, Node *nr, int wid)
{
Prog *p;
if(nr->op == OLITERAL) {
switch(nr->val.ctype) {
case CTCPLX:
gdatacomplex(nam, nr->val.u.cval);
return;
case CTSTR:
gdatastring(nam, nr->val.u.sval);
return;
}
}
p = gins(ADATA, nam, nr);
p->reg = wid;
}
void
gdatacomplex(Node *nam, Mpcplx *cval)
{
Prog *p;
int w;
w = cplxsubtype(nam->type->etype);
w = types[w]->width;
p = gins(ADATA, nam, N);
p->reg = w;
p->to.type = D_FCONST;
p->to.u.dval = mpgetflt(&cval->real);
p = gins(ADATA, nam, N);
p->reg = w;
p->from.offset += w;
p->to.type = D_FCONST;
p->to.u.dval = mpgetflt(&cval->imag);
}
void
gdatastring(Node *nam, Strlit *sval)
{
Prog *p;
Node nod1;
p = gins(ADATA, nam, N);
datastring(sval->s, sval->len, &p->to);
p->reg = types[tptr]->width;
p->to.type = D_CONST;
p->to.etype = simtype[tptr];
nodconst(&nod1, types[TINT], sval->len);
p = gins(ADATA, nam, &nod1);
p->reg = widthint;
p->from.offset += widthptr;
}
int
dstringptr(Sym *s, int off, char *str)
{
Prog *p;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = D_OREG;
p->from.name = D_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->reg = widthptr;
datastring(str, strlen(str)+1, &p->to);
p->to.type = D_CONST;
p->to.etype = simtype[TINT];
off += widthptr;
return off;
}
int
dgostrlitptr(Sym *s, int off, Strlit *lit)
{
Prog *p;
if(lit == nil)
return duintptr(s, off, 0);
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = D_OREG;
p->from.name = D_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->reg = widthptr;
datagostring(lit, &p->to);
p->to.type = D_CONST;
p->to.etype = simtype[TINT];
off += widthptr;
return off;
}
int
dgostringptr(Sym *s, int off, char *str)
{
int n;
Strlit *lit;
if(str == nil)
return duintptr(s, off, 0);
n = strlen(str);
lit = mal(sizeof *lit + n);
strcpy(lit->s, str);
lit->len = n;
return dgostrlitptr(s, off, lit);
}
int
dsymptr(Sym *s, int off, Sym *x, int xoff)
{
Prog *p;
off = rnd(off, widthptr);
p = gins(ADATA, N, N);
p->from.type = D_OREG;
p->from.name = D_EXTERN;
p->from.sym = linksym(s);
p->from.offset = off;
p->reg = widthptr;
p->to.type = D_CONST;
p->to.name = D_EXTERN;
p->to.sym = linksym(x);
p->to.offset = xoff;
off += widthptr;
return off;
}
void
nopout(Prog *p)
{
p->as = ANOP;
}

1707
src/cmd/9g/gsubr.c Normal file

File diff suppressed because it is too large Load Diff

234
src/cmd/9g/opt.h Normal file
View File

@@ -0,0 +1,234 @@
// Derived from Inferno utils/6c/gc.h
// http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "../gc/popt.h"
#define Z N
#define Adr Addr
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
#define CLOAD 5
#define CREF 5
#define CINF 1000
#define LOOP 3
typedef struct Reg Reg;
typedef struct Rgn Rgn;
/*c2go
extern Node *Z;
enum
{
CLOAD = 5,
CREF = 5,
CINF = 1000,
LOOP = 3,
};
uint32 BLOAD(Reg*);
uint32 BSTORE(Reg*);
uint32 LOAD(Reg*);
uint32 STORE(Reg*);
*/
// A Reg is a wrapper around a single Prog (one instruction) that holds
// register optimization information while the optimizer runs.
// r->prog is the instruction.
// r->prog->opt points back to r.
struct Reg
{
Flow f;
Bits set; // regopt variables written by this instruction.
Bits use1; // regopt variables read by prog->from.
Bits use2; // regopt variables read by prog->to.
// refahead/refbehind are the regopt variables whose current
// value may be used in the following/preceding instructions
// up to a CALL (or the value is clobbered).
Bits refbehind;
Bits refahead;
// calahead/calbehind are similar, but for variables in
// instructions that are reachable after hitting at least one
// CALL.
Bits calbehind;
Bits calahead;
Bits regdiff;
Bits act;
uint64 regu; // register used bitmap
};
#define R ((Reg*)0)
/*c2go extern Reg *R; */
#define NRGN 600
/*c2go enum { NRGN = 600 }; */
// A Rgn represents a single regopt variable over a region of code
// where a register could potentially be dedicated to that variable.
// The code encompassed by a Rgn is defined by the flow graph,
// starting at enter, flood-filling forward while varno is refahead
// and backward while varno is refbehind, and following branches. A
// single variable may be represented by multiple disjoint Rgns and
// each Rgn may choose a different register for that variable.
// Registers are allocated to regions greedily in order of descending
// cost.
struct Rgn
{
Reg* enter;
short cost;
short varno;
short regno;
};
EXTERN int32 exregoffset; // not set
EXTERN int32 exfregoffset; // not set
EXTERN Reg zreg;
EXTERN Rgn region[NRGN];
EXTERN Rgn* rgp;
EXTERN int nregion;
EXTERN int nvar;
EXTERN int32 regbits;
EXTERN int32 exregbits; // TODO(austin) not used; remove
EXTERN Bits externs;
EXTERN Bits params;
EXTERN Bits consts;
EXTERN Bits addrs;
EXTERN Bits ivar;
EXTERN Bits ovar;
EXTERN int change;
EXTERN int32 maxnr;
EXTERN struct
{
int32 ncvtreg;
int32 nspill;
int32 ndelmov;
int32 nvar;
} ostats;
/*
* reg.c
*/
int rcmp(const void*, const void*);
void regopt(Prog*);
void addmove(Reg*, int, int, int);
Bits mkvar(Reg*, Adr*);
void prop(Reg*, Bits, Bits);
void synch(Reg*, Bits);
uint64 allreg(uint64, Rgn*);
void paint1(Reg*, int);
uint64 paint2(Reg*, int, int);
void paint3(Reg*, int, uint64, int);
void addreg(Adr*, int);
void dumpone(Flow*, int);
void dumpit(char*, Flow*, int);
/*
* peep.c
*/
void peep(Prog*);
void excise(Flow*);
int copyu(Prog*, Adr*, Adr*);
uint64 RtoB(int);
uint64 FtoB(int);
int BtoR(uint64);
int BtoF(uint64);
/*
* prog.c
*/
typedef struct ProgInfo ProgInfo;
struct ProgInfo
{
uint32 flags; // the bits below
uint64 reguse; // registers implicitly used by this instruction
uint64 regset; // registers implicitly set by this instruction
uint64 regindex; // registers used by addressing mode
};
enum
{
// Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
Pseudo = 1<<1,
// There's nothing to say about the instruction,
// but it's still okay to see.
OK = 1<<2,
// Size of right-side write, or right-side read if no write.
SizeB = 1<<3,
SizeW = 1<<4,
SizeL = 1<<5,
SizeQ = 1<<6,
SizeF = 1<<7, // float aka float32
SizeD = 1<<8, // double aka float64
// Left side (Prog.from): address taken, read, write.
LeftAddr = 1<<9,
LeftRead = 1<<10,
LeftWrite = 1<<11,
// Register in middle (Prog.reg); only ever read.
RegRead = 1<<12,
CanRegRead = 1<<13,
// Right side (Prog.to): address taken, read, write.
RightAddr = 1<<14,
RightRead = 1<<15,
RightWrite = 1<<16,
// Instruction updates whichever of from/to is type D_OREG
PostInc = 1<<17,
// Instruction kinds
Move = 1<<18, // straight move
Conv = 1<<19, // size conversion
Cjmp = 1<<20, // conditional jump
Break = 1<<21, // breaks control flow (no fallthrough)
Call = 1<<22, // function call
Jump = 1<<23, // jump
Skip = 1<<24, // data instruction
};
void proginfo(ProgInfo*, Prog*);
// To allow use of AJMP, ACALL, ARET in ../gc/popt.c.
enum
{
AJMP = ABR,
ACALL = ABL,
ARET = ARETURN,
};

96
src/cmd/9g/peep.c Normal file
View File

@@ -0,0 +1,96 @@
// Derived from Inferno utils/6c/peep.c
// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "opt.h"
void
peep(Prog *p)
{
USED(p);
// TODO(minux)
return;
}
void
excise(Flow *r)
{
Prog *p, *l;
p = r->prog;
if(debug['P'] && debug['v'])
print("%P ===delete===\n", p);
l = p->link;
*p = zprog;
p->as = ANOP;
p->link = l;
ostats.ndelmov++;
}
int
regtyp(Adr *a)
{
switch(a->type) {
default:
return 0;
case D_REG:
case D_FREG:
return 1;
}
}
int
sameaddr(Addr *a, Addr *v)
{
if(a->type != v->type)
return 0;
if(regtyp(v) && a->reg == v->reg)
return 1;
if(v->type == D_AUTO || v->type == D_PARAM)
if(v->offset == a->offset)
return 1;
return 0;
}
int
smallindir(Addr *a, Addr *reg)
{
return reg->type == D_REG && a->type == D_OREG &&
a->reg == reg->reg &&
0 <= a->offset && a->offset < 4096;
}
int
stackaddr(Addr *a)
{
return a->type == D_REG && a->reg == REGSP;
}

144
src/cmd/9g/prog.c Normal file
View File

@@ -0,0 +1,144 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <u.h>
#include <libc.h>
#include "gg.h"
#include "opt.h"
enum {
LeftRdwr = LeftRead | LeftWrite,
RightRdwr = RightRead | RightWrite,
};
// This table gives the basic information about instruction
// generated by the compiler and processed in the optimizer.
// See opt.h for bit definitions.
//
// Instructions not generated need not be listed.
// As an exception to that rule, we typically write down all the
// size variants of an operation even if we just use a subset.
//
// The table is formatted for 8-space tabs.
static ProgInfo progtable[ALAST] = {
[ATYPE]= {Pseudo | Skip},
[ATEXT]= {Pseudo},
[AFUNCDATA]= {Pseudo},
[APCDATA]= {Pseudo},
[AUNDEF]= {Break},
[AUSEFIELD]= {OK},
[ACHECKNIL]= {LeftRead},
[AVARDEF]= {Pseudo | RightWrite},
[AVARKILL]= {Pseudo | RightWrite},
// NOP is an internal no-op that also stands
// for USED and SET annotations, not the Power opcode.
[ANOP]= {LeftRead | RightWrite},
// Integer
[AADD]= {SizeQ | LeftRead | RegRead | RightWrite},
[ASUB]= {SizeQ | LeftRead | RegRead | RightWrite},
[ANEG]= {SizeQ | LeftRead | RegRead | RightWrite},
[AAND]= {SizeQ | LeftRead | RegRead | RightWrite},
[AOR]= {SizeQ | LeftRead | RegRead | RightWrite},
[AXOR]= {SizeQ | LeftRead | RegRead | RightWrite},
[AMULLD]= {SizeQ | LeftRead | RegRead | RightWrite},
[AMULLW]= {SizeL | LeftRead | RegRead | RightWrite},
[AMULHD]= {SizeL | LeftRead | RegRead | RightWrite},
[AMULHDU]= {SizeL | LeftRead | RegRead | RightWrite},
[ADIVD]= {SizeQ | LeftRead | RegRead | RightWrite},
[ADIVDU]= {SizeQ | LeftRead | RegRead | RightWrite},
[ASLD]= {SizeQ | LeftRead | RegRead | RightWrite},
[ASRD]= {SizeQ | LeftRead | RegRead | RightWrite},
[ASRAD]= {SizeQ | LeftRead | RegRead | RightWrite},
[ACMP]= {SizeQ | LeftRead | RightRead},
[ACMPU]= {SizeQ | LeftRead | RightRead},
[ATD]= {SizeQ | RightRead},
// Floating point.
[AFADD]= {SizeD | LeftRead | RegRead | RightWrite},
[AFADDS]= {SizeF | LeftRead | RegRead | RightWrite},
[AFSUB]= {SizeD | LeftRead | RegRead | RightWrite},
[AFSUBS]= {SizeF | LeftRead | RegRead | RightWrite},
[AFMUL]= {SizeD | LeftRead | RegRead | RightWrite},
[AFMULS]= {SizeF | LeftRead | RegRead | RightWrite},
[AFDIV]= {SizeD | LeftRead | RegRead | RightWrite},
[AFDIVS]= {SizeF | LeftRead | RegRead | RightWrite},
[AFCTIDZ]= {SizeF | LeftRead | RegRead | RightWrite},
[AFCFID]= {SizeF | LeftRead | RegRead | RightWrite},
[AFCMPU]= {SizeD | LeftRead | RightRead},
[AFRSP]= {SizeD | LeftRead | RightWrite | Conv},
// Moves
[AMOVB]= {SizeB | LeftRead | RightWrite | Move | Conv},
[AMOVBU]= {SizeB | LeftRead | RightWrite | Move | Conv | PostInc},
[AMOVBZ]= {SizeB | LeftRead | RightWrite | Move | Conv},
[AMOVH]= {SizeW | LeftRead | RightWrite | Move | Conv},
[AMOVHU]= {SizeW | LeftRead | RightWrite | Move | Conv | PostInc},
[AMOVHZ]= {SizeW | LeftRead | RightWrite | Move | Conv},
[AMOVW]= {SizeL | LeftRead | RightWrite | Move | Conv},
// there is no AMOVWU.
[AMOVWZU]= {SizeL | LeftRead | RightWrite | Move | Conv | PostInc},
[AMOVWZ]= {SizeL | LeftRead | RightWrite | Move | Conv},
[AMOVD]= {SizeQ | LeftRead | RightWrite | Move},
[AMOVDU]= {SizeQ | LeftRead | RightWrite | Move | PostInc},
[AFMOVS]= {SizeF | LeftRead | RightWrite | Move | Conv},
[AFMOVD]= {SizeD | LeftRead | RightWrite | Move},
// Jumps
[ABR]= {Jump | Break},
[ABL]= {Call},
[ABEQ]= {Cjmp},
[ABNE]= {Cjmp},
[ABGE]= {Cjmp},
[ABLT]= {Cjmp},
[ABGT]= {Cjmp},
[ABLE]= {Cjmp},
[ARETURN]= {Break},
[ADUFFZERO]= {Call},
[ADUFFCOPY]= {Call},
};
void
proginfo(ProgInfo *info, Prog *p)
{
*info = progtable[p->as];
if(info->flags == 0) {
*info = progtable[AADD];
fatal("proginfo: unknown instruction %P", p);
}
if((info->flags & RegRead) && p->reg == NREG) {
info->flags &= ~RegRead;
info->flags |= /*CanRegRead |*/ RightRead;
}
if((p->from.type == D_OREG || p->from.type == D_CONST) && p->from.reg != NREG) {
info->regindex |= RtoB(p->from.reg);
if(info->flags & PostInc) {
info->regset |= RtoB(p->from.reg);
}
}
if((p->to.type == D_OREG || p->to.type == D_CONST) && p->to.reg != NREG) {
info->regindex |= RtoB(p->to.reg);
if(info->flags & PostInc) {
info->regset |= RtoB(p->to.reg);
}
}
if(p->from.type == D_CONST && p->from.sym != nil && (info->flags & LeftRead)) {
info->flags &= ~LeftRead;
info->flags |= LeftAddr;
}
if(p->as == ADUFFZERO) {
info->reguse |= RtoB(0) | RtoB(2);
info->regset |= RtoB(2);
}
if(p->as == ADUFFCOPY) {
info->reguse |= RtoB(0) | RtoB(2) | RtoB(3);
info->regset |= RtoB(2) | RtoB(3);
}
}

1346
src/cmd/9g/reg.c Normal file

File diff suppressed because it is too large Load Diff

516
src/cmd/9l/9.out.h Normal file
View File

@@ -0,0 +1,516 @@
// cmd/9c/9.out.h from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
/*
* powerpc 64
*/
#define NSNAME 8
#define NSYM 50
#define NREG 32 /* number of general registers */
#define NFREG 32 /* number of floating point registers */
#include "../ld/textflag.h"
enum
{
REGZERO = 0, /* set to zero */
REGSP = 1,
REGSB = 2,
REGRET = 3,
REGARG = -1, /* -1 disables passing the first argument in register */
REGRT1 = 3, /* reserved for runtime, duffzero and duffcopy */
REGRT2 = 4, /* reserved for runtime, duffcopy */
REGMIN = 7, /* register variables allocated from here to REGMAX */
REGENV = 11, /* environment for closures */
REGMAX = 27,
REGEXT = 30, /* external registers allocated from here down */
REGG = 30, /* G */
REGTMP = 31, /* used by the linker */
FREGRET = 0,
FREGMIN = 17, /* first register variable */
FREGMAX = 26, /* last register variable for 9g only */
FREGEXT = 26, /* first external register */
FREGCVI = 27, /* floating conversion constant */
FREGZERO = 28, /* both float and double */
FREGHALF = 29, /* double */
FREGONE = 30, /* double */
FREGTWO = 31 /* double */
/*
* GENERAL:
*
* compiler allocates R3 up as temps
* compiler allocates register variables R7-R27
* compiler allocates external registers R30 down
*
* compiler allocates register variables F17-F26
* compiler allocates external registers F26 down
*/
};
enum {
BIG = 32768-8,
};
enum {
/* mark flags */
LABEL = 1<<0,
LEAF = 1<<1,
FLOAT = 1<<2,
BRANCH = 1<<3,
LOAD = 1<<4,
FCMP = 1<<5,
SYNC = 1<<6,
LIST = 1<<7,
FOLL = 1<<8,
NOSCHED = 1<<9,
};
enum
{
C_NONE,
C_REG,
C_FREG,
C_CREG,
C_SPR, /* special processor register */
C_ZCON,
C_SCON, /* 16 bit signed */
C_UCON, /* low 16 bits 0 */
C_ADDCON, /* -0x8000 <= v < 0 */
C_ANDCON, /* 0 < v <= 0xFFFF */
C_LCON, /* other 32 */
C_DCON, /* other 64 (could subdivide further) */
C_SACON,
C_SECON,
C_LACON,
C_LECON,
C_SBRA,
C_LBRA,
C_SAUTO,
C_LAUTO,
C_SEXT,
C_LEXT,
C_ZOREG,
C_SOREG,
C_LOREG,
C_FPSCR,
C_MSR,
C_XER,
C_LR,
C_CTR,
C_ANY,
C_GOK,
C_ADDR,
C_NCLASS, /* must be the last */
};
enum
{
AXXX,
AADD,
AADDCC,
AADDV,
AADDVCC,
AADDC,
AADDCCC,
AADDCV,
AADDCVCC,
AADDME,
AADDMECC,
AADDMEVCC,
AADDMEV,
AADDE,
AADDECC,
AADDEVCC,
AADDEV,
AADDZE,
AADDZECC,
AADDZEVCC,
AADDZEV,
AAND,
AANDCC,
AANDN,
AANDNCC,
ABC,
ABCL,
ABEQ,
ABGE,
ABGT,
ABL,
ABLE,
ABLT,
ABNE,
ABR,
ABVC,
ABVS,
ACMP,
ACMPU,
ACNTLZW,
ACNTLZWCC,
ACRAND,
ACRANDN,
ACREQV,
ACRNAND,
ACRNOR,
ACROR,
ACRORN,
ACRXOR,
ADIVW,
ADIVWCC,
ADIVWVCC,
ADIVWV,
ADIVWU,
ADIVWUCC,
ADIVWUVCC,
ADIVWUV,
AEQV,
AEQVCC,
AEXTSB,
AEXTSBCC,
AEXTSH,
AEXTSHCC,
AFABS,
AFABSCC,
AFADD,
AFADDCC,
AFADDS,
AFADDSCC,
AFCMPO,
AFCMPU,
AFCTIW,
AFCTIWCC,
AFCTIWZ,
AFCTIWZCC,
AFDIV,
AFDIVCC,
AFDIVS,
AFDIVSCC,
AFMADD,
AFMADDCC,
AFMADDS,
AFMADDSCC,
AFMOVD,
AFMOVDCC,
AFMOVDU,
AFMOVS,
AFMOVSU,
AFMSUB,
AFMSUBCC,
AFMSUBS,
AFMSUBSCC,
AFMUL,
AFMULCC,
AFMULS,
AFMULSCC,
AFNABS,
AFNABSCC,
AFNEG,
AFNEGCC,
AFNMADD,
AFNMADDCC,
AFNMADDS,
AFNMADDSCC,
AFNMSUB,
AFNMSUBCC,
AFNMSUBS,
AFNMSUBSCC,
AFRSP,
AFRSPCC,
AFSUB,
AFSUBCC,
AFSUBS,
AFSUBSCC,
AMOVMW,
ALSW,
ALWAR,
AMOVWBR,
AMOVB,
AMOVBU,
AMOVBZ,
AMOVBZU,
AMOVH,
AMOVHBR,
AMOVHU,
AMOVHZ,
AMOVHZU,
AMOVW,
AMOVWU,
AMOVFL,
AMOVCRFS,
AMTFSB0,
AMTFSB0CC,
AMTFSB1,
AMTFSB1CC,
AMULHW,
AMULHWCC,
AMULHWU,
AMULHWUCC,
AMULLW,
AMULLWCC,
AMULLWVCC,
AMULLWV,
ANAND,
ANANDCC,
ANEG,
ANEGCC,
ANEGVCC,
ANEGV,
ANOR,
ANORCC,
AOR,
AORCC,
AORN,
AORNCC,
AREM,
AREMCC,
AREMV,
AREMVCC,
AREMU,
AREMUCC,
AREMUV,
AREMUVCC,
ARFI,
ARLWMI,
ARLWMICC,
ARLWNM,
ARLWNMCC,
ASLW,
ASLWCC,
ASRW,
ASRAW,
ASRAWCC,
ASRWCC,
ASTSW,
ASTWCCC,
ASUB,
ASUBCC,
ASUBVCC,
ASUBC,
ASUBCCC,
ASUBCV,
ASUBCVCC,
ASUBME,
ASUBMECC,
ASUBMEVCC,
ASUBMEV,
ASUBV,
ASUBE,
ASUBECC,
ASUBEV,
ASUBEVCC,
ASUBZE,
ASUBZECC,
ASUBZEVCC,
ASUBZEV,
ASYNC,
AXOR,
AXORCC,
ADCBF,
ADCBI,
ADCBST,
ADCBT,
ADCBTST,
ADCBZ,
AECIWX,
AECOWX,
AEIEIO,
AICBI,
AISYNC,
APTESYNC,
ATLBIE,
ATLBIEL,
ATLBSYNC,
ATW,
ASYSCALL,
ADATA,
AGLOBL,
AGOK,
AHISTORY,
ANAME,
ANOP,
ARETURN,
ATEXT,
AWORD,
AEND,
ADYNT,
AINIT,
ASIGNAME,
ARFCI,
/* optional on 32-bit */
AFRES,
AFRESCC,
AFRSQRTE,
AFRSQRTECC,
AFSEL,
AFSELCC,
AFSQRT,
AFSQRTCC,
AFSQRTS,
AFSQRTSCC,
/* 64-bit */
ACNTLZD,
ACNTLZDCC,
ACMPW, /* CMP with L=0 */
ACMPWU,
ADIVD,
ADIVDCC,
ADIVDVCC,
ADIVDV,
ADIVDU,
ADIVDUCC,
ADIVDUVCC,
ADIVDUV,
AEXTSW,
AEXTSWCC,
/* AFCFIW; AFCFIWCC */
AFCFID,
AFCFIDCC,
AFCTID,
AFCTIDCC,
AFCTIDZ,
AFCTIDZCC,
ALDAR,
AMOVD,
AMOVDU,
AMOVWZ,
AMOVWZU,
AMULHD,
AMULHDCC,
AMULHDU,
AMULHDUCC,
AMULLD,
AMULLDCC,
AMULLDVCC,
AMULLDV,
ARFID,
ARLDMI,
ARLDMICC,
ARLDC,
ARLDCCC,
ARLDCR,
ARLDCRCC,
ARLDCL,
ARLDCLCC,
ASLBIA,
ASLBIE,
ASLBMFEE,
ASLBMFEV,
ASLBMTE,
ASLD,
ASLDCC,
ASRD,
ASRAD,
ASRADCC,
ASRDCC,
ASTDCCC,
ATD,
/* 64-bit pseudo operation */
ADWORD,
AREMD,
AREMDCC,
AREMDV,
AREMDVCC,
AREMDU,
AREMDUCC,
AREMDUV,
AREMDUVCC,
/* more 64-bit operations */
AHRFID,
AUNDEF,
AUSEFIELD,
ATYPE,
AFUNCDATA,
APCDATA,
ACHECKNIL,
AVARDEF,
AVARKILL,
ADUFFCOPY,
ADUFFZERO,
ALAST
};
/* type/name */
enum
{
D_GOK = 0,
D_NONE,
/* name */
D_EXTERN,
D_STATIC,
D_AUTO,
D_PARAM,
/* type */
D_BRANCH,
D_OREG,
D_CONST,
D_FCONST,
D_SCONST,
D_REG,
D_FPSCR,
D_MSR,
D_FREG,
D_CREG,
D_SPR,
D_OPT, /* branch/trap option */
D_FILE,
D_FILE1,
D_DCR, /* device control register */
D_DCONST,
D_ADDR, // not used, use D_CONST with non-empty sym.
D_LAST,
/* reg names for 9g OREGISTER */
D_R0 = 0, // type is D_REG
D_F0 = D_R0+NREG, // type is D_FREG
/* reg names in offset field iff type is D_SPR */
D_XER = 1,
D_LR = 8,
D_CTR = 9
/* and many supervisor level registers */
};
/*
* this is the ranlib header
*/
#define SYMDEF "__.GOSYMDEF"

5
src/cmd/9l/Makefile Normal file
View File

@@ -0,0 +1,5 @@
# Copyright 2012 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
include ../../Make.dist

338
src/cmd/9l/asm.c Normal file
View File

@@ -0,0 +1,338 @@
// Inferno utils/5l/asm.c
// http://code.google.com/p/inferno-os/source/browse/utils/5l/asm.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Writing object files.
#include "l.h"
#include "../ld/lib.h"
#include "../ld/elf.h"
#include "../ld/dwarf.h"
char linuxdynld[] = "/lib64/ld64.so.1";
char freebsddynld[] = "XXX";
char openbsddynld[] = "XXX";
char netbsddynld[] = "XXX";
char dragonflydynld[] = "XXX";
char solarisdynld[] = "XXX";
static int
needlib(char *name)
{
char *p;
LSym *s;
if(*name == '\0')
return 0;
/* reuse hash code in symbol table */
p = smprint(".dynlib.%s", name);
s = linklookup(ctxt, p, 0);
free(p);
if(s->type == 0) {
s->type = 100; // avoid SDATA, etc.
return 1;
}
return 0;
}
int nelfsym = 1;
// b is the addresses, a is the I-form branch instruction template, peform
// addition so that the instruction jumps to address (offset) b.
static int32
braddoff(int32 a, int32 b)
{
return (((uint32)a) & 0xfc000003U) | (0x03fffffcU & (uint32)((a & 0x3fffffcU) + b));
}
void
adddynrela(LSym *rel, LSym *s, Reloc *r)
{
// TODO(minux)
USED(rel); USED(s); USED(r);
}
void
adddynrel(LSym *s, Reloc *r)
{
LSym *targ;
// TODO(minux)
targ = r->sym;
ctxt->cursym = s;
diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type);
}
int
elfreloc1(Reloc *r, vlong sectoff)
{
USED(r); USED(sectoff);
// TODO(minux)
return -1;
}
void
elfsetupplt(void)
{
// TODO(minux)
return;
}
int
machoreloc1(Reloc *r, vlong sectoff)
{
USED(r);
USED(sectoff);
return -1;
}
int
archreloc(Reloc *r, LSym *s, vlong *val)
{
uint32 o1, o2;
int32 t;
if(linkmode == LinkExternal) {
// TODO(minux): translate R_ADDRPOWER and R_CALLPOWER into standard ELF relocations.
// R_ADDRPOWER corresponds to R_PPC_ADDR16_HA and R_PPC_ADDR16_LO.
// R_CALLPOWER corresponds to R_PPC_REL24.
return -1;
}
switch(r->type) {
case R_CONST:
*val = r->add;
return 0;
case R_GOTOFF:
*val = symaddr(r->sym) + r->add - symaddr(linklookup(ctxt, ".got", 0));
return 0;
case R_ADDRPOWER:
// r->add is two power64 instructions holding an immediate 32-bit constant.
// We want to add r->sym's address to that constant.
// The encoding of the immediate x<<16 + y,
// where x is the low 16 bits of the first instruction and y is the low 16
// bits of the second. Both x and y are signed (int16, not uint16).
o1 = r->add >> 32;
o2 = r->add;
t = symaddr(r->sym);
if(t < 0) {
ctxt->diag("relocation for %s is too big (>=2G): %lld", s->name, symaddr(r->sym));
}
t += ((o1 & 0xffff) << 16) + ((int32)o2 << 16 >> 16);
if(t & 0x8000)
t += 0x10000;
o1 = (o1 & 0xffff0000) | ((t >> 16) & 0xffff);
o2 = (o2 & 0xffff0000) | (t & 0xffff);
// when laid out, the instruction order must always be o1, o2.
if(ctxt->arch->endian == BigEndian)
*val = ((vlong)o1 << 32) | o2;
else
*val = ((vlong)o2 << 32) | o1;
return 0;
case R_CALLPOWER:
*val = braddoff((uint32)r->add, (int32)(symaddr(r->sym) - (s->value + r->off)));
return 0;
}
return -1;
}
void
adddynsym(Link *ctxt, LSym *s)
{
USED(ctxt); USED(s);
// TODO(minux)
return;
}
void
adddynlib(char *lib)
{
LSym *s;
if(!needlib(lib))
return;
if(iself) {
s = linklookup(ctxt, ".dynstr", 0);
if(s->size == 0)
addstring(s, "");
elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, addstring(s, lib));
} else {
diag("adddynlib: unsupported binary format");
}
}
void
asmb(void)
{
uint32 symo;
Section *sect;
LSym *sym;
int i;
if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime());
Bflush(&bso);
if(iself)
asmbelfsetup();
sect = segtext.sect;
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
codeblk(sect->vaddr, sect->len);
for(sect = sect->next; sect != nil; sect = sect->next) {
cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
datblk(sect->vaddr, sect->len);
}
if(segrodata.filelen > 0) {
if(debug['v'])
Bprint(&bso, "%5.2f rodatblk\n", cputime());
Bflush(&bso);
cseek(segrodata.fileoff);
datblk(segrodata.vaddr, segrodata.filelen);
}
if(debug['v'])
Bprint(&bso, "%5.2f datblk\n", cputime());
Bflush(&bso);
cseek(segdata.fileoff);
datblk(segdata.vaddr, segdata.filelen);
/* output symbol table */
symsize = 0;
lcsize = 0;
symo = 0;
if(!debug['s']) {
// TODO: rationalize
if(debug['v'])
Bprint(&bso, "%5.2f sym\n", cputime());
Bflush(&bso);
switch(HEADTYPE) {
default:
if(iself)
goto ElfSym;
case Hplan9:
symo = segdata.fileoff+segdata.filelen;
break;
ElfSym:
symo = segdata.fileoff+segdata.filelen;
symo = rnd(symo, INITRND);
break;
}
cseek(symo);
switch(HEADTYPE) {
default:
if(iself) {
if(debug['v'])
Bprint(&bso, "%5.2f elfsym\n", cputime());
asmelfsym();
cflush();
cwrite(elfstrdat, elfstrsize);
if(debug['v'])
Bprint(&bso, "%5.2f dwarf\n", cputime());
dwarfemitdebugsections();
if(linkmode == LinkExternal)
elfemitreloc();
}
break;
case Hplan9:
asmplan9sym();
cflush();
sym = linklookup(ctxt, "pclntab", 0);
if(sym != nil) {
lcsize = sym->np;
for(i=0; i < lcsize; i++)
cput(sym->p[i]);
cflush();
}
break;
}
}
ctxt->cursym = nil;
if(debug['v'])
Bprint(&bso, "%5.2f header\n", cputime());
Bflush(&bso);
cseek(0L);
switch(HEADTYPE) {
default:
case Hplan9: /* plan 9 */
LPUT(0x647); /* magic */
LPUT(segtext.filelen); /* sizes */
LPUT(segdata.filelen);
LPUT(segdata.len - segdata.filelen);
LPUT(symsize); /* nsyms */
LPUT(entryvalue()); /* va of entry */
LPUT(0L);
LPUT(lcsize);
break;
case Hlinux:
case Hfreebsd:
case Hnetbsd:
case Hopenbsd:
case Hnacl:
asmbelf(symo);
break;
}
cflush();
if(debug['c']){
print("textsize=%ulld\n", segtext.filelen);
print("datsize=%ulld\n", segdata.filelen);
print("bsssize=%ulld\n", segdata.len - segdata.filelen);
print("symsize=%d\n", symsize);
print("lcsize=%d\n", lcsize);
print("total=%lld\n", segtext.filelen+segdata.len+symsize+lcsize);
}
}
vlong
rnd(vlong v, int32 r)
{
vlong c;
if(r <= 0)
return v;
v += r - 1;
c = v % r;
if(c < 0)
c += r;
v -= c;
return v;
}

16
src/cmd/9l/doc.go Normal file
View File

@@ -0,0 +1,16 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
9l is the linker for the Power64.
The $GOARCH for these tools is power64 (big endian) or
power64le (little endian).
The flags are documented in ../ld/doc.go.
*/
package main

100
src/cmd/9l/l.h Normal file
View File

@@ -0,0 +1,100 @@
// cmd/9l/l.h from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <link.h>
#include "9.out.h"
#ifndef EXTERN
#define EXTERN extern
#endif
enum
{
thechar = '9',
PtrSize = 8,
IntSize = 8,
RegSize = 8,
MaxAlign = 32, // max data alignment
FuncAlign = 8
};
#define P ((Prog*)0)
#define S ((LSym*)0)
enum
{
FPCHIP = 1,
STRINGSZ = 200,
MAXHIST = 20, /* limit of path elements for history symbols */
DATBLK = 1024,
NHASH = 10007,
NHUNK = 100000,
MINSIZ = 64,
NENT = 100,
NSCHED = 20,
MINLC = 4,
Roffset = 22, /* no. bits for offset in relocation address */
Rindex = 10 /* no. bits for index in relocation address */
};
EXTERN int32 autosize;
EXTERN LSym* datap;
EXTERN int debug[128];
EXTERN int32 lcsize;
EXTERN char literal[32];
EXTERN int nerrors;
EXTERN vlong instoffset;
EXTERN char* rpath;
EXTERN vlong pc;
EXTERN int32 symsize;
EXTERN int32 staticgen;
EXTERN Prog* lastp;
EXTERN vlong textsize;
void asmb(void);
void adddynlib(char *lib);
void adddynrel(LSym *s, Reloc *r);
void adddynsym(Link *ctxt, LSym *s);
int archreloc(Reloc *r, LSym *s, vlong *val);
void listinit(void);
vlong rnd(vlong, int32);
#define LPUT(a) (ctxt->arch->endian == BigEndian ? lputb(a):lputl(a))
#define WPUT(a) (ctxt->arch->endian == BigEndian ? wputb(a):wputl(a))
#define VPUT(a) (ctxt->arch->endian == BigEndian ? vputb(a):vputl(a))
/* Used by ../ld/dwarf.c */
enum
{
DWARFREGSP = 1
};

40
src/cmd/9l/list.c Normal file
View File

@@ -0,0 +1,40 @@
// Inferno utils/5l/list.h
// http://code.google.com/p/inferno-os/source/browse/utils/5l/list.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Printing.
#include "l.h"
#include "../ld/lib.h"
void
listinit(void)
{
listinit9();
}

108
src/cmd/9l/obj.c Normal file
View File

@@ -0,0 +1,108 @@
// Inferno utils/5l/obj.c
// http://code.google.com/p/inferno-os/source/browse/utils/5l/obj.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Reading object files.
#include "l.h"
#include "../ld/lib.h"
#include "../ld/elf.h"
#include "../ld/dwarf.h"
#include <ar.h>
char *thestring = "power64";
LinkArch *thelinkarch;
void
linkarchinit(void)
{
thestring = getgoarch();
if(strcmp(thestring, "power64le") == 0)
thelinkarch = &linkpower64le;
else
thelinkarch = &linkpower64;
}
void
archinit(void)
{
// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
// Go was built; see ../../make.bash.
if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0)
linkmode = LinkInternal;
switch(HEADTYPE) {
default:
if(linkmode == LinkAuto)
linkmode = LinkInternal;
if(linkmode == LinkExternal && strcmp(getgoextlinkenabled(), "1") != 0)
sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE));
break;
}
switch(HEADTYPE) {
default:
diag("unknown -H option");
errorexit();
case Hplan9: /* plan 9 */
HEADR = 32L;
if(INITTEXT == -1)
INITTEXT = 4128;
if(INITDAT == -1)
INITDAT = 0;
if(INITRND == -1)
INITRND = 4096;
break;
case Hlinux: /* power64 elf */
debug['d'] = 1; // TODO(minux): dynamic linking is not supported yet.
elfinit();
HEADR = ELFRESERVE;
if(INITTEXT == -1)
INITTEXT = 0x10000 + HEADR;
if(INITDAT == -1)
INITDAT = 0;
if(INITRND == -1)
INITRND = 0x10000;
break;
case Hnacl:
elfinit();
HEADR = 0x10000;
funcalign = 16;
if(INITTEXT == -1)
INITTEXT = 0x20000;
if(INITDAT == -1)
INITDAT = 0;
if(INITRND == -1)
INITRND = 0x10000;
break;
}
if(INITDAT != 0 && INITRND != 0)
print("warning: -D0x%ux is ignored because of -R0x%ux\n",
INITDAT, INITRND);
}

View File

@@ -220,6 +220,31 @@ slookup(char *s)
return lookup();
}
LSym *thetext;
void
settext(LSym *s)
{
thetext = s;
}
Sym*
labellookup(Sym *s)
{
char *p;
Sym *lab;
if(thetext == nil) {
s->labelname = s->name;
return s;
}
p = smprint("%s.%s", thetext->name, s->name);
lab = slookup(p);
free(p);
lab->labelname = s->name;
return lab;
}
Sym*
lookup(void)
{

View File

@@ -65,14 +65,14 @@ argsize(int doret)
}
//print(" %d %T\n", s, t);
}
if(thechar == '6')
if(thechar == '6' || thechar == '9')
s = (s+7) & ~7;
else
s = (s+3) & ~3;
if(doret && thisfn->link->etype != TVOID) {
s = align(s, thisfn->link, Aarg1, nil);
s = align(s, thisfn->link, Aarg2, nil);
if(thechar == '6')
if(thechar == '6' || thechar == '9')
s = (s+7) & ~7;
else
s = (s+3) & ~3;

View File

@@ -130,15 +130,23 @@ func usage() {
}
var ptrSizeMap = map[string]int64{
"386": 4,
"amd64": 8,
"arm": 4,
"386": 4,
"amd64": 8,
"arm": 4,
"ppc64": 8,
"ppc64le": 8,
"power64": 8,
"power64le": 8,
}
var intSizeMap = map[string]int64{
"386": 4,
"amd64": 8,
"arm": 4,
"386": 4,
"amd64": 8,
"arm": 4,
"ppc64": 8,
"ppc64le": 8,
"power64": 8,
"power64le": 8,
}
var cPrefix string

49
src/cmd/dist/build.c vendored
View File

@@ -39,7 +39,7 @@ static void dopack(char*, char*, char**, int);
static char *findgoversion(void);
// The known architecture letters.
static char *gochars = "5668";
static char *gochars = "566899";
// The known architectures.
static char *okgoarch[] = {
@@ -48,6 +48,8 @@ static char *okgoarch[] = {
"amd64",
"amd64p32",
"386",
"power64",
"power64le",
};
// The known operating systems.
@@ -344,6 +346,7 @@ static char *oldtool[] = {
"5a", "5c", "5g", "5l",
"6a", "6c", "6g", "6l",
"8a", "8c", "8g", "8l",
"9a", "9c", "9g", "9l",
"6cov",
"6nm",
"6prof",
@@ -521,6 +524,7 @@ static struct {
"anames5.c",
"anames6.c",
"anames8.c",
"anames9.c",
}},
{"cmd/cc", {
"-pgen.c",
@@ -549,6 +553,11 @@ static struct {
"../cc/pswt.c",
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
}},
{"cmd/9c", {
"../cc/pgen.c",
"../cc/pswt.c",
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
}},
{"cmd/5g", {
"../gc/cplx.c",
"../gc/pgen.c",
@@ -573,6 +582,14 @@ static struct {
"../gc/popt.h",
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libgc.a",
}},
{"cmd/9g", {
"../gc/cplx.c",
"../gc/pgen.c",
"../gc/plive.c",
"../gc/popt.c",
"../gc/popt.h",
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libgc.a",
}},
{"cmd/5l", {
"../ld/*",
}},
@@ -582,6 +599,9 @@ static struct {
{"cmd/8l", {
"../ld/*",
}},
{"cmd/9l", {
"../ld/*",
}},
{"cmd/go", {
"zdefaultcc.go",
}},
@@ -618,6 +638,7 @@ static struct {
{"anames5.c", mkanames},
{"anames6.c", mkanames},
{"anames8.c", mkanames},
{"anames9.c", mkanames},
{"zasm_", mkzasm},
{"zdefaultcc.go", mkzdefaultcc},
{"zsys_", mkzsys},
@@ -1163,12 +1184,26 @@ shouldbuild(char *file, char *dir)
// Check file name for GOOS or GOARCH.
name = lastelem(file);
for(i=0; i<nelem(okgoos); i++)
if(contains(name, okgoos[i]) && !streq(okgoos[i], goos))
for(i=0; i<nelem(okgoos); i++) {
if(streq(okgoos[i], goos))
continue;
p = xstrstr(name, okgoos[i]);
if(p == nil)
continue;
p += xstrlen(okgoos[i]);
if(*p == '.' || *p == '_' || *p == '\0')
return 0;
for(i=0; i<nelem(okgoarch); i++)
if(contains(name, okgoarch[i]) && !streq(okgoarch[i], goarch))
}
for(i=0; i<nelem(okgoarch); i++) {
if(streq(okgoarch[i], goarch))
continue;
p = xstrstr(name, okgoarch[i]);
if(p == nil)
continue;
p += xstrlen(okgoarch[i]);
if(*p == '.' || *p == '_' || *p == '\0')
return 0;
}
// Omit test files.
if(contains(name, "_test"))
@@ -1367,6 +1402,10 @@ static char *cleantab[] = {
"cmd/8c",
"cmd/8g",
"cmd/8l",
"cmd/9a",
"cmd/9c",
"cmd/9g",
"cmd/9l",
"cmd/cc",
"cmd/gc",
"cmd/go",

View File

@@ -63,22 +63,36 @@ gcopnames(char *dir, char *file)
vfree(&fields);
}
// mkanames reads [568].out.h and writes anames[568].c
static int
xatoi(char *s, char **end)
{
int val = 0;
for(; *s && *s >= '0' && *s <= '9'; ++s)
val = val * 10 + (*s - '0');
*end = s;
return val;
}
// mkanames reads [5689].out.h and writes anames[5689].c
// The format is much the same as the Go opcodes above.
// it also writes out cnames array for C_* constants.
// It also writes out cnames array for C_* constants and the dnames
// array for D_* constants.
void
mkanames(char *dir, char *file)
{
int i, j, ch;
int i, j, ch, n, unknown;
Buf in, b, out, out2;
Vec lines;
char *p;
char *p, *p2;
Vec dnames[128];
binit(&b);
binit(&in);
binit(&out);
binit(&out2);
vinit(&lines);
for(i=0; i<nelem(dnames); i++)
vinit(&dnames[i]);
ch = file[xstrlen(file)-3];
bprintf(&b, "%s/../cmd/%cl/%c.out.h", dir, ch, ch);
@@ -87,10 +101,12 @@ mkanames(char *dir, char *file)
// Include link.h so that the extern declaration there is
// checked against the non-extern declaration we are generating.
bwritestr(&out, bprintf(&b, "// auto generated by go tool dist\n"));
bwritestr(&out, bprintf(&b, "#include <u.h>\n"));
bwritestr(&out, bprintf(&b, "#include <libc.h>\n"));
bwritestr(&out, bprintf(&b, "#include <bio.h>\n"));
bwritestr(&out, bprintf(&b, "#include <link.h>\n"));
bwritestr(&out, bprintf(&b, "#include \"../cmd/%cl/%c.out.h\"\n", ch, ch));
bwritestr(&out, bprintf(&b, "\n"));
bwritestr(&out, bprintf(&b, "char* anames%c[] = {\n", ch));
@@ -127,6 +143,69 @@ mkanames(char *dir, char *file)
if(j>0)
bwriteb(&out, &out2);
j=unknown=0;
n=-1;
for(i=0; i<lines.len; i++) {
if(hasprefix(lines.p[i], "\tD_")) {
p = xstrstr(lines.p[i], ",");
if(p)
*p = '\0';
p = xstrstr(lines.p[i], "\n");
if(p)
*p = '\0';
// Parse explicit value, if any
p = xstrstr(lines.p[i], "=");
if(p) {
// Skip space after '='
p2 = p + 1;
while(*p2 == ' ' || *p2 == '\t')
p2++;
n = xatoi(p2, &p2);
// We can't do anything about
// non-numeric values or anything that
// follows
while(*p2 == ' ' || *p2 == '\t')
p2++;
if(*p2 != 0) {
unknown = 1;
continue;
}
// Truncate space before '='
while(*(p-1) == ' ' || *(p-1) == '\t')
p--;
*p = '\0';
unknown = 0;
} else {
n++;
}
if(unknown || n >= nelem(dnames))
continue;
p = lines.p[i] + 3;
if(xstrcmp(p, "LAST") == 0)
continue;
vadd(&dnames[n], p);
j++;
}
}
if(j>0){
bwritestr(&out, bprintf(&b, "char* dnames%c[D_LAST] = {\n", ch));
for(i=0; i<nelem(dnames); i++) {
if(dnames[i].len == 0)
continue;
bwritestr(&out, bprintf(&b, "\t[D_%s] = \"", dnames[i].p[0]));
for(j=0; j<dnames[i].len; j++) {
if(j != 0)
bwritestr(&out, "/");
bwritestr(&out, dnames[i].p[j]);
}
bwritestr(&out, "\",\n");
}
bwritestr(&out, "};\n");
}
writefile(&out, file, 0);
bfree(&b);
@@ -134,4 +213,6 @@ mkanames(char *dir, char *file)
bfree(&out);
bfree(&out2);
vfree(&lines);
for(i=0; i<nelem(dnames); i++)
vfree(&dnames[i]);
}

View File

@@ -148,6 +148,13 @@ static struct {
{"arm", "",
"#define LR R14\n"
},
{"power64", "",
"#define g R30\n"
},
{"power64le", "",
"#define g R30\n"
},
};
#define MAXWINCB 2000 /* maximum number of windows callbacks allowed */

4
src/cmd/dist/unix.c vendored
View File

@@ -708,6 +708,10 @@ main(int argc, char **argv)
gohostarch = "386";
else if(contains(u.machine, "arm"))
gohostarch = "arm";
else if(contains(u.machine, "ppc64le"))
gohostarch = "power64le";
else if(contains(u.machine, "ppc64"))
gohostarch = "power64";
else
fatal("unknown architecture: %s", u.machine);
}

View File

@@ -95,11 +95,11 @@ int
bnum(Bits a)
{
int i;
int32 b;
uint64 b;
for(i=0; i<BITS; i++)
if(b = a.b[i])
return 32*i + bitno(b);
return 64*i + bitno(b);
fatal("bad in bnum");
return 0;
}
@@ -110,27 +110,35 @@ blsh(uint n)
Bits c;
c = zbits;
c.b[n/32] = 1L << (n%32);
c.b[n/64] = 1LL << (n%64);
return c;
}
/*
int
bset(Bits a, uint n)
btest(Bits *a, uint n)
{
if(a.b[n/32] & (1L << (n%32)))
return 1;
return 0;
return (a->b[n/64] & (1LL << (n%64))) != 0;
}
void
biset(Bits *a, uint n)
{
a->b[n/64] |= 1LL << (n%64);
}
void
biclr(Bits *a, uint n)
{
a->b[n/64] &= ~(1LL << (n%64));
}
*/
int
bitno(int32 b)
bitno(uint64 b)
{
int i;
for(i=0; i<32; i++)
if(b & (1L<<i))
for(i=0; i<64; i++)
if(b & (1LL<<i))
return i;
fatal("bad in bitno");
return 0;
@@ -157,7 +165,7 @@ Qconv(Fmt *fp)
if(var[i].offset != 0)
fmtprint(fp, "%+lld", (vlong)var[i].offset);
}
bits.b[i/32] &= ~(1L << (i%32));
biclr(&bits, i);
}
return 0;
}

View File

@@ -704,13 +704,13 @@ enum
Ecomplit = 1<<11, // type in composite literal
};
#define BITS 5
#define NVAR (BITS*sizeof(uint32)*8)
#define BITS 3
#define NVAR (BITS*sizeof(uint64)*8)
typedef struct Bits Bits;
struct Bits
{
uint32 b[BITS];
uint64 b[BITS];
};
EXTERN Bits zbits;
@@ -1027,12 +1027,14 @@ int Qconv(Fmt *fp);
Bits band(Bits a, Bits b);
int bany(Bits *a);
int beq(Bits a, Bits b);
int bitno(int32 b);
int bitno(uint64 b);
Bits blsh(uint n);
Bits bnot(Bits a);
int bnum(Bits a);
Bits bor(Bits a, Bits b);
int bset(Bits a, uint n);
int btest(Bits *a, uint n);
void biset(Bits *a, uint n);
void biclr(Bits *a, uint n);
/*
* bv.c

View File

@@ -471,7 +471,7 @@ allocauto(Prog* ptxt)
stksize = rnd(stksize, n->type->align);
if(haspointers(n->type))
stkptrsize = stksize;
if(thechar == '5')
if(thechar == '5' || thechar == '9')
stksize = rnd(stksize, widthptr);
if(stksize >= (1ULL<<31)) {
setlineno(curfn);
@@ -528,7 +528,7 @@ cgen_checknil(Node *n)
dump("checknil", n);
fatal("bad checknil");
}
if((thechar == '5' && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
if(((thechar == '5' || thechar == '9') && n->op != OREGISTER) || !n->addable || n->op == OLITERAL) {
regalloc(&reg, types[tptr], n);
cgen(n, &reg);
gins(ACHECKNIL, &reg, N);

View File

@@ -3301,6 +3301,9 @@ walkrotate(Node **np)
int w, sl, sr, s;
Node *l, *r;
Node *n;
if(thechar == '9')
return;
n = *np;
@@ -3426,6 +3429,10 @@ walkdiv(Node **np, NodeList **init)
Type *twide;
Magic m;
// TODO(minux)
if(thechar == '9')
return;
n = *np;
if(n->right->op != OLITERAL)
return;

View File

@@ -445,11 +445,11 @@ blk(LSym *start, int64 addr, int64 size)
continue;
if(sym->value >= eaddr)
break;
ctxt->cursym = sym;
if(sym->value < addr) {
diag("phase error: addr=%#llx but sym=%#llx type=%d", (vlong)addr, (vlong)sym->value, sym->type);
errorexit();
}
ctxt->cursym = sym;
for(; addr < sym->value; addr++)
cput(0);
p = sym->p;
@@ -463,6 +463,8 @@ blk(LSym *start, int64 addr, int64 size)
diag("phase error: addr=%#llx value+size=%#llx", (vlong)addr, (vlong)sym->value+sym->size);
errorexit();
}
if(sym->value+sym->size >= eaddr)
break;
}
for(; addr < eaddr; addr++)

View File

@@ -10,8 +10,8 @@ Ld is the portable code for a modified version of the Plan 9 linker. The origin
http://plan9.bell-labs.com/magic/man2html/1/8l
It reads object files (.5, .6, or .8 files) and writes a binary named for the
architecture (5.out, 6.out, 8.out) by default (if $GOOS is windows, a .exe suffix
It reads object files (.5, .6, .8, .9 files) and writes a binary named for the
architecture (5.out, 6.out, 8.out, 9.out) by default (if $GOOS is windows, a .exe suffix
will be appended).
Major changes include:
@@ -22,7 +22,7 @@ Original options are listed on the manual page linked above.
Usage:
go tool 6l [flags] mainObj
Substitute 6l with 8l or 5l as appropriate.
Substitute 6l with 5l, 8l or 9l as appropriate.
Options new in this version:

View File

@@ -2189,7 +2189,7 @@ dwarfaddshstrings(LSym *shstrtab)
elfstrdbg[ElfStrDebugStr] = addstring(shstrtab, ".debug_str");
elfstrdbg[ElfStrGDBScripts] = addstring(shstrtab, ".debug_gdb_scripts");
if(linkmode == LinkExternal) {
if(thechar == '6') {
if(thechar == '6' || thechar == '9') {
elfstrdbg[ElfStrRelDebugInfo] = addstring(shstrtab, ".rela.debug_info");
elfstrdbg[ElfStrRelDebugAranges] = addstring(shstrtab, ".rela.debug_aranges");
elfstrdbg[ElfStrRelDebugLine] = addstring(shstrtab, ".rela.debug_line");
@@ -2244,7 +2244,7 @@ dwarfaddelfrelocheader(int elfstr, ElfShdr *shdata, vlong off, vlong size)
ElfShdr *sh;
sh = newElfShdr(elfstrdbg[elfstr]);
if(thechar == '6') {
if(thechar == '6' || thechar == '9') {
sh->type = SHT_RELA;
} else {
sh->type = SHT_REL;

View File

@@ -45,6 +45,7 @@ elfinit(void)
switch(thechar) {
// 64-bit architectures
case '6':
case '9':
elf64 = 1;
hdr.phoff = ELF64HDRSIZE; /* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */
hdr.shoff = ELF64HDRSIZE; /* Will move as we add PHeaders */
@@ -678,7 +679,7 @@ elfdynhash(void)
elfwritedynentsym(s, DT_VERSYM, linklookup(ctxt, ".gnu.version", 0));
}
if(thechar == '6') {
if(thechar == '6' || thechar == '9') {
sy = linklookup(ctxt, ".rela.plt", 0);
if(sy->size > 0) {
elfwritedynent(s, DT_PLTREL, DT_RELA);
@@ -804,7 +805,7 @@ elfshreloc(Section *sect)
if(strcmp(sect->name, ".shstrtab") == 0 || strcmp(sect->name, ".tbss") == 0)
return nil;
if(thechar == '6') {
if(thechar == '6' || thechar == '9') {
prefix = ".rela";
typ = SHT_RELA;
} else {
@@ -931,7 +932,7 @@ doelf(void)
debug['s'] = 0;
debug['d'] = 1;
if(thechar == '6') {
if(thechar == '6' || thechar == '9') {
addstring(shstrtab, ".rela.text");
addstring(shstrtab, ".rela.rodata");
addstring(shstrtab, ".rela.typelink");
@@ -954,7 +955,7 @@ doelf(void)
if(flag_shared) {
addstring(shstrtab, ".init_array");
if(thechar == '6')
if(thechar == '6' || thechar == '9')
addstring(shstrtab, ".rela.init_array");
else
addstring(shstrtab, ".rel.init_array");
@@ -975,7 +976,7 @@ doelf(void)
addstring(shstrtab, ".dynamic");
addstring(shstrtab, ".dynsym");
addstring(shstrtab, ".dynstr");
if(thechar == '6') {
if(thechar == '6' || thechar == '9') {
addstring(shstrtab, ".rela");
addstring(shstrtab, ".rela.plt");
} else {
@@ -990,7 +991,7 @@ doelf(void)
s = linklookup(ctxt, ".dynsym", 0);
s->type = SELFROSECT;
s->reachable = 1;
if(thechar == '6')
if(thechar == '6' || thechar == '9')
s->size += ELF64SYMSIZE;
else
s->size += ELF32SYMSIZE;
@@ -1004,7 +1005,7 @@ doelf(void)
dynstr = s;
/* relocation table */
if(thechar == '6')
if(thechar == '6' || thechar == '9')
s = linklookup(ctxt, ".rela", 0);
else
s = linklookup(ctxt, ".rel", 0);
@@ -1031,7 +1032,7 @@ doelf(void)
elfsetupplt();
if(thechar == '6')
if(thechar == '6' || thechar == '9')
s = linklookup(ctxt, ".rela.plt", 0);
else
s = linklookup(ctxt, ".rel.plt", 0);
@@ -1056,13 +1057,13 @@ doelf(void)
*/
elfwritedynentsym(s, DT_HASH, linklookup(ctxt, ".hash", 0));
elfwritedynentsym(s, DT_SYMTAB, linklookup(ctxt, ".dynsym", 0));
if(thechar == '6')
if(thechar == '6' || thechar == '9')
elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
else
elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
elfwritedynentsym(s, DT_STRTAB, linklookup(ctxt, ".dynstr", 0));
elfwritedynentsymsize(s, DT_STRSZ, linklookup(ctxt, ".dynstr", 0));
if(thechar == '6') {
if(thechar == '6' || thechar == '9') {
elfwritedynentsym(s, DT_RELA, linklookup(ctxt, ".rela", 0));
elfwritedynentsymsize(s, DT_RELASZ, linklookup(ctxt, ".rela", 0));
elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
@@ -1148,6 +1149,9 @@ asmbelf(vlong symo)
case '8':
eh->machine = EM_386;
break;
case '9':
eh->machine = EM_PPC64;
break;
}
startva = INITTEXT - HEADR;
@@ -1488,7 +1492,10 @@ elfobj:
eh->ident[EI_CLASS] = ELFCLASS64;
else
eh->ident[EI_CLASS] = ELFCLASS32;
eh->ident[EI_DATA] = ELFDATA2LSB;
if(ctxt->arch->endian == BigEndian)
eh->ident[EI_DATA] = ELFDATA2MSB;
else
eh->ident[EI_DATA] = ELFDATA2LSB;
eh->ident[EI_VERSION] = EV_CURRENT;
if(linkmode == LinkExternal)

View File

@@ -436,6 +436,12 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
return;
}
break;
case '9':
if(obj->machine != ElfMachPower64 || hdr->ident[4] != ElfClass64) {
diag("%s: elf object but not power64", pn);
return;
}
break;
}
// load section list into memory.

View File

@@ -594,6 +594,7 @@ hostlink(void)
argv[argc++] = "-m32";
break;
case '6':
case '9':
argv[argc++] = "-m64";
break;
case '5':
@@ -1033,7 +1034,7 @@ static LSym *newstack;
enum
{
HasLinkRegister = (thechar == '5'),
HasLinkRegister = (thechar == '5' || thechar == '9'),
};
// TODO: Record enough information in new object files to
@@ -1042,7 +1043,7 @@ enum
static int
callsize(void)
{
if(thechar == '5')
if(HasLinkRegister)
return 0;
return RegSize;
}
@@ -1052,7 +1053,7 @@ dostkcheck(void)
{
Chain ch;
LSym *s;
morestack = linklookup(ctxt, "runtime.morestack", 0);
newstack = linklookup(ctxt, "runtime.newstack", 0);
@@ -1076,19 +1077,19 @@ dostkcheck(void)
continue;
if(s->nosplit) {
ctxt->cursym = s;
ch.sym = s;
stkcheck(&ch, 0);
}
ctxt->cursym = s;
ch.sym = s;
stkcheck(&ch, 0);
}
}
for(s = ctxt->textp; s != nil; s = s->next) {
if(!s->nosplit) {
ctxt->cursym = s;
ch.sym = s;
stkcheck(&ch, 0);
ctxt->cursym = s;
ch.sym = s;
stkcheck(&ch, 0);
}
}
}
}
static int
stkcheck(Chain *up, int depth)
@@ -1106,7 +1107,7 @@ stkcheck(Chain *up, int depth)
// function at top of safe zone once.
if(limit == StackLimit-callsize()) {
if(s->stkcheck)
return 0;
return 0;
s->stkcheck = 1;
}
@@ -1154,6 +1155,7 @@ stkcheck(Chain *up, int depth)
switch(r->type) {
case R_CALL:
case R_CALLARM:
case R_CALLPOWER:
// Direct call.
ch.limit = limit - pcsp.value - callsize();
ch.sym = r->sym;
@@ -1164,8 +1166,8 @@ stkcheck(Chain *up, int depth)
// to StackLimit beyond the frame size.
if(strncmp(r->sym->name, "runtime.morestack", 17) == 0) {
limit = StackLimit + s->locals;
if(thechar == '5')
limit += 4; // saved LR
if(HasLinkRegister)
limit += RegSize;
}
break;
@@ -1184,7 +1186,7 @@ stkcheck(Chain *up, int depth)
break;
}
}
}
}
return 0;
}
@@ -1213,7 +1215,7 @@ stkprint(Chain *ch, int limit)
else
print("\t%d\tguaranteed after split check in %s\n", ch->limit, name);
} else {
stkprint(ch->up, ch->limit + (!HasLinkRegister)*PtrSize);
stkprint(ch->up, ch->limit + (!HasLinkRegister)*RegSize);
if(!HasLinkRegister)
print("\t%d\ton entry to %s\n", ch->limit, name);
}
@@ -1533,7 +1535,7 @@ callgraph(void)
r = &s->r[i];
if(r->sym == nil)
continue;
if((r->type == R_CALL || r->type == R_CALLARM) && r->sym->type == STEXT)
if((r->type == R_CALL || r->type == R_CALLARM || r->type == R_CALLPOWER) && r->sym->type == STEXT)
Bprint(&bso, "%s calls %s\n", s->name, r->sym->name);
}
}

View File

@@ -44,6 +44,7 @@ machoinit(void)
switch(thechar) {
// 64-bit architectures
case '6':
case '9':
macho64 = 1;
break;

View File

@@ -78,6 +78,7 @@ putelfsyment(int off, vlong addr, vlong size, int info, int shndx, int other)
{
switch(thechar) {
case '6':
case '9':
LPUT(off);
cput(info);
cput(other);

View File

@@ -49,6 +49,10 @@ func runObjDump(t *testing.T, exe, startaddr, endaddr string) (path, lineno stri
case "android", "nacl":
t.Skipf("skipping on %s", runtime.GOOS)
}
switch runtime.GOARCH {
case "power64", "power64le":
t.Skipf("skipping on %s, issue 9039", runtime.GOARCH)
}
cmd := exec.Command(exe, os.Args[0], startaddr, endaddr)
out, err := cmd.CombinedOutput()
@@ -199,6 +203,10 @@ func testDisasm(t *testing.T, flags ...string) {
}
func TestDisasm(t *testing.T) {
switch runtime.GOARCH {
case "power64", "power64le":
t.Skipf("skipping on %s, issue 9039", runtime.GOARCH)
}
testDisasm(t)
}
@@ -207,5 +215,9 @@ func TestDisasmExtld(t *testing.T) {
case "plan9", "windows":
t.Skipf("skipping on %s", runtime.GOOS)
}
switch runtime.GOARCH {
case "power64", "power64le":
t.Skipf("skipping on %s, no support for external linking, issue 9038", runtime.GOARCH)
}
testDisasm(t, "-ldflags=-linkmode=external")
}

View File

@@ -1414,6 +1414,184 @@ var rppcStrings = []intName{
func (i R_PPC) String() string { return stringName(uint32(i), rppcStrings, false) }
func (i R_PPC) GoString() string { return stringName(uint32(i), rppcStrings, true) }
// Relocation types for PowerPC 64.
type R_PPC64 int
const (
R_PPC64_NONE R_PPC64 = 0
R_PPC64_ADDR32 R_PPC64 = 1
R_PPC64_ADDR24 R_PPC64 = 2
R_PPC64_ADDR16 R_PPC64 = 3
R_PPC64_ADDR16_LO R_PPC64 = 4
R_PPC64_ADDR16_HI R_PPC64 = 5
R_PPC64_ADDR16_HA R_PPC64 = 6
R_PPC64_ADDR14 R_PPC64 = 7
R_PPC64_ADDR14_BRTAKEN R_PPC64 = 8
R_PPC64_ADDR14_BRNTAKEN R_PPC64 = 9
R_PPC64_REL24 R_PPC64 = 10
R_PPC64_REL14 R_PPC64 = 11
R_PPC64_REL14_BRTAKEN R_PPC64 = 12
R_PPC64_REL14_BRNTAKEN R_PPC64 = 13
R_PPC64_GOT16 R_PPC64 = 14
R_PPC64_GOT16_LO R_PPC64 = 15
R_PPC64_GOT16_HI R_PPC64 = 16
R_PPC64_GOT16_HA R_PPC64 = 17
R_PPC64_JMP_SLOT R_PPC64 = 21
R_PPC64_REL32 R_PPC64 = 26
R_PPC64_ADDR64 R_PPC64 = 38
R_PPC64_ADDR16_HIGHER R_PPC64 = 39
R_PPC64_ADDR16_HIGHERA R_PPC64 = 40
R_PPC64_ADDR16_HIGHEST R_PPC64 = 41
R_PPC64_ADDR16_HIGHESTA R_PPC64 = 42
R_PPC64_REL64 R_PPC64 = 44
R_PPC64_TOC16 R_PPC64 = 47
R_PPC64_TOC16_LO R_PPC64 = 48
R_PPC64_TOC16_HI R_PPC64 = 49
R_PPC64_TOC16_HA R_PPC64 = 50
R_PPC64_TOC R_PPC64 = 51
R_PPC64_ADDR16_DS R_PPC64 = 56
R_PPC64_ADDR16_LO_DS R_PPC64 = 57
R_PPC64_GOT16_DS R_PPC64 = 58
R_PPC64_GOT16_LO_DS R_PPC64 = 59
R_PPC64_TOC16_DS R_PPC64 = 63
R_PPC64_TOC16_LO_DS R_PPC64 = 64
R_PPC64_TLS R_PPC64 = 67
R_PPC64_DTPMOD64 R_PPC64 = 68
R_PPC64_TPREL16 R_PPC64 = 69
R_PPC64_TPREL16_LO R_PPC64 = 70
R_PPC64_TPREL16_HI R_PPC64 = 71
R_PPC64_TPREL16_HA R_PPC64 = 72
R_PPC64_TPREL64 R_PPC64 = 73
R_PPC64_DTPREL16 R_PPC64 = 74
R_PPC64_DTPREL16_LO R_PPC64 = 75
R_PPC64_DTPREL16_HI R_PPC64 = 76
R_PPC64_DTPREL16_HA R_PPC64 = 77
R_PPC64_DTPREL64 R_PPC64 = 78
R_PPC64_GOT_TLSGD16 R_PPC64 = 79
R_PPC64_GOT_TLSGD16_LO R_PPC64 = 80
R_PPC64_GOT_TLSGD16_HI R_PPC64 = 81
R_PPC64_GOT_TLSGD16_HA R_PPC64 = 82
R_PPC64_GOT_TLSLD16 R_PPC64 = 83
R_PPC64_GOT_TLSLD16_LO R_PPC64 = 84
R_PPC64_GOT_TLSLD16_HI R_PPC64 = 85
R_PPC64_GOT_TLSLD16_HA R_PPC64 = 86
R_PPC64_GOT_TPREL16_DS R_PPC64 = 87
R_PPC64_GOT_TPREL16_LO_DS R_PPC64 = 88
R_PPC64_GOT_TPREL16_HI R_PPC64 = 89
R_PPC64_GOT_TPREL16_HA R_PPC64 = 90
R_PPC64_GOT_DTPREL16_DS R_PPC64 = 91
R_PPC64_GOT_DTPREL16_LO_DS R_PPC64 = 92
R_PPC64_GOT_DTPREL16_HI R_PPC64 = 93
R_PPC64_GOT_DTPREL16_HA R_PPC64 = 94
R_PPC64_TPREL16_DS R_PPC64 = 95
R_PPC64_TPREL16_LO_DS R_PPC64 = 96
R_PPC64_TPREL16_HIGHER R_PPC64 = 97
R_PPC64_TPREL16_HIGHERA R_PPC64 = 98
R_PPC64_TPREL16_HIGHEST R_PPC64 = 99
R_PPC64_TPREL16_HIGHESTA R_PPC64 = 100
R_PPC64_DTPREL16_DS R_PPC64 = 101
R_PPC64_DTPREL16_LO_DS R_PPC64 = 102
R_PPC64_DTPREL16_HIGHER R_PPC64 = 103
R_PPC64_DTPREL16_HIGHERA R_PPC64 = 104
R_PPC64_DTPREL16_HIGHEST R_PPC64 = 105
R_PPC64_DTPREL16_HIGHESTA R_PPC64 = 106
R_PPC64_TLSGD R_PPC64 = 107
R_PPC64_TLSLD R_PPC64 = 108
R_PPC64_REL16 R_PPC64 = 249
R_PPC64_REL16_LO R_PPC64 = 250
R_PPC64_REL16_HI R_PPC64 = 251
R_PPC64_REL16_HA R_PPC64 = 252
)
var rppc64Strings = []intName{
{0, "R_PPC64_NONE"},
{1, "R_PPC64_ADDR32"},
{2, "R_PPC64_ADDR24"},
{3, "R_PPC64_ADDR16"},
{4, "R_PPC64_ADDR16_LO"},
{5, "R_PPC64_ADDR16_HI"},
{6, "R_PPC64_ADDR16_HA"},
{7, "R_PPC64_ADDR14"},
{8, "R_PPC64_ADDR14_BRTAKEN"},
{9, "R_PPC64_ADDR14_BRNTAKEN"},
{10, "R_PPC64_REL24"},
{11, "R_PPC64_REL14"},
{12, "R_PPC64_REL14_BRTAKEN"},
{13, "R_PPC64_REL14_BRNTAKEN"},
{14, "R_PPC64_GOT16"},
{15, "R_PPC64_GOT16_LO"},
{16, "R_PPC64_GOT16_HI"},
{17, "R_PPC64_GOT16_HA"},
{21, "R_PPC64_JMP_SLOT"},
{26, "R_PPC64_REL32"},
{38, "R_PPC64_ADDR64"},
{39, "R_PPC64_ADDR16_HIGHER"},
{40, "R_PPC64_ADDR16_HIGHERA"},
{41, "R_PPC64_ADDR16_HIGHEST"},
{42, "R_PPC64_ADDR16_HIGHESTA"},
{44, "R_PPC64_REL64"},
{47, "R_PPC64_TOC16"},
{48, "R_PPC64_TOC16_LO"},
{49, "R_PPC64_TOC16_HI"},
{50, "R_PPC64_TOC16_HA"},
{51, "R_PPC64_TOC"},
{56, "R_PPC64_ADDR16_DS"},
{57, "R_PPC64_ADDR16_LO_DS"},
{58, "R_PPC64_GOT16_DS"},
{59, "R_PPC64_GOT16_LO_DS"},
{63, "R_PPC64_TOC16_DS"},
{64, "R_PPC64_TOC16_LO_DS"},
{67, "R_PPC64_TLS"},
{68, "R_PPC64_DTPMOD64"},
{69, "R_PPC64_TPREL16"},
{70, "R_PPC64_TPREL16_LO"},
{71, "R_PPC64_TPREL16_HI"},
{72, "R_PPC64_TPREL16_HA"},
{73, "R_PPC64_TPREL64"},
{74, "R_PPC64_DTPREL16"},
{75, "R_PPC64_DTPREL16_LO"},
{76, "R_PPC64_DTPREL16_HI"},
{77, "R_PPC64_DTPREL16_HA"},
{78, "R_PPC64_DTPREL64"},
{79, "R_PPC64_GOT_TLSGD16"},
{80, "R_PPC64_GOT_TLSGD16_LO"},
{81, "R_PPC64_GOT_TLSGD16_HI"},
{82, "R_PPC64_GOT_TLSGD16_HA"},
{83, "R_PPC64_GOT_TLSLD16"},
{84, "R_PPC64_GOT_TLSLD16_LO"},
{85, "R_PPC64_GOT_TLSLD16_HI"},
{86, "R_PPC64_GOT_TLSLD16_HA"},
{87, "R_PPC64_GOT_TPREL16_DS"},
{88, "R_PPC64_GOT_TPREL16_LO_DS"},
{89, "R_PPC64_GOT_TPREL16_HI"},
{90, "R_PPC64_GOT_TPREL16_HA"},
{91, "R_PPC64_GOT_DTPREL16_DS"},
{92, "R_PPC64_GOT_DTPREL16_LO_DS"},
{93, "R_PPC64_GOT_DTPREL16_HI"},
{94, "R_PPC64_GOT_DTPREL16_HA"},
{95, "R_PPC64_TPREL16_DS"},
{96, "R_PPC64_TPREL16_LO_DS"},
{97, "R_PPC64_TPREL16_HIGHER"},
{98, "R_PPC64_TPREL16_HIGHERA"},
{99, "R_PPC64_TPREL16_HIGHEST"},
{100, "R_PPC64_TPREL16_HIGHESTA"},
{101, "R_PPC64_DTPREL16_DS"},
{102, "R_PPC64_DTPREL16_LO_DS"},
{103, "R_PPC64_DTPREL16_HIGHER"},
{104, "R_PPC64_DTPREL16_HIGHERA"},
{105, "R_PPC64_DTPREL16_HIGHEST"},
{106, "R_PPC64_DTPREL16_HIGHESTA"},
{107, "R_PPC64_TLSGD"},
{108, "R_PPC64_TLSLD"},
{249, "R_PPC64_REL16"},
{250, "R_PPC64_REL16_LO"},
{251, "R_PPC64_REL16_HI"},
{252, "R_PPC64_REL16_HA"},
}
func (i R_PPC64) String() string { return stringName(uint32(i), rppc64Strings, false) }
func (i R_PPC64) GoString() string { return stringName(uint32(i), rppc64Strings, true) }
// Relocation types for SPARC.
type R_SPARC int

View File

@@ -532,6 +532,9 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error {
if f.Class == ELFCLASS64 && f.Machine == EM_AARCH64 {
return f.applyRelocationsARM64(dst, rels)
}
if f.Class == ELFCLASS64 && f.Machine == EM_PPC64 {
return f.applyRelocationsPPC64(dst, rels)
}
return errors.New("not implemented")
}
@@ -671,6 +674,51 @@ func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error {
return nil
}
func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error {
// 24 is the size of Rela64.
if len(rels)%24 != 0 {
return errors.New("length of relocation section is not a multiple of 24")
}
symbols, _, err := f.getSymbols(SHT_SYMTAB)
if err != nil {
return err
}
b := bytes.NewReader(rels)
var rela Rela64
for b.Len() > 0 {
binary.Read(b, f.ByteOrder, &rela)
symNo := rela.Info >> 32
t := R_PPC64(rela.Info & 0xffff)
if symNo == 0 || symNo > uint64(len(symbols)) {
continue
}
sym := &symbols[symNo-1]
if SymType(sym.Info&0xf) != STT_SECTION {
// We don't handle non-section relocations for now.
continue
}
switch t {
case R_PPC64_ADDR64:
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
continue
}
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
case R_PPC64_ADDR32:
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
continue
}
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
}
}
return nil
}
func (f *File) DWARF() (*dwarf.Data, error) {
// There are many other DWARF sections, but these
// are the required ones, and the debug/dwarf package
@@ -693,7 +741,7 @@ func (f *File) DWARF() (*dwarf.Data, error) {
// If there's a relocation table for .debug_info, we have to process it
// now otherwise the data in .debug_info is invalid for x86-64 objects.
rela := f.Section(".rela.debug_info")
if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_AARCH64) {
if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_AARCH64 || f.Machine == EM_PPC64) {
data, err := rela.Data()
if err != nil {
return nil, err

View File

@@ -266,6 +266,12 @@ var relocationTests = []relocationTest{
{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: int64(0x24)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
},
},
{
"testdata/go-relocation-test-gcc482-ppc64le.obj",
[]relocationTestEntry{
{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{dwarf.Field{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -mtune=power8 -mcpu=power7 -gdwarf-2 -fstack-protector"}, dwarf.Field{Attr: dwarf.AttrLanguage, Val: int64(1)}, dwarf.Field{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c"}, dwarf.Field{Attr: dwarf.AttrCompDir, Val: "/tmp"}, dwarf.Field{Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, dwarf.Field{Attr: dwarf.AttrHighpc, Val: uint64(0x24)}, dwarf.Field{Attr: dwarf.AttrStmtList, Val: int64(0)}}}},
},
},
{
"testdata/go-relocation-test-clang-x86.obj",
[]relocationTestEntry{

Binary file not shown.

View File

@@ -1384,6 +1384,8 @@ func ArchChar(goarch string) (string, error) {
return "6", nil
case "arm":
return "5", nil
case "power64", "power64le":
return "9", nil
}
return "", errors.New("unsupported GOARCH " + goarch)
}

View File

@@ -5,4 +5,4 @@
package build
const goosList = "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows "
const goarchList = "386 amd64 amd64p32 arm "
const goarchList = "386 amd64 amd64p32 arm power64 power64le "

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build 386 arm
// +build 386 arm power64 power64le
package crc32

2784
src/liblink/asm9.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -82,6 +82,19 @@ Pconv(Fmt *fp)
p = va_arg(fp->args, Prog*);
bigP = p;
if(fp->flags & FmtSharp) {
char *s = str;
s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, p->as);
if(p->from.type != D_NONE)
s += sprint(s, " from={%#D}", &p->from);
if(p->reg)
s += sprint(s, " reg=%d", p->reg);
if(p->to.type != D_NONE)
s += sprint(s, " to={%#D}", &p->to);
return fmtstrcpy(fp, str);
}
switch(p->as) {
case ADATA:
sprint(str, "%.5lld (%L) %A %D/%d,%D",
@@ -126,6 +139,31 @@ Dconv(Fmt *fp)
a = va_arg(fp->args, Addr*);
i = a->type;
if(fp->flags & FmtSharp) {
char *s = str;
s += sprint(s, "type=");
if(i == D_NONE) {
sprint(s, "NONE");
goto brk;
}
if(i >= D_INDIR) {
i -= D_INDIR;
s += sprint(s, "INDIR+");
}
if(i >= 0 && i < D_LAST && dnames6[i] != nil)
s += sprint(s, "%s ", dnames6[i]);
else
s += sprint(s, "%d ", i);
s += sprint(s, "offset=%ld etype=%E width=%d", a->offset, a->etype, a->width);
if(a->class != 0)
s += sprint(s, " class=%s", cnames9[(int)a->class]);
if(a->sym != nil)
s += sprint(s, " sym=%s", a->sym->name);
if(a->type == D_BRANCH && a->u.branch != nil)
s += sprint(s, " branch=%.5lld", a->u.branch->pc);
goto brk;
}
if(fp->flags & FmtLong) {
if(i == D_CONST)
sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32);

451
src/liblink/list9.c Normal file
View File

@@ -0,0 +1,451 @@
// cmd/9l/list.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <link.h>
#include "../cmd/9l/9.out.h"
enum
{
STRINGSZ = 1000,
};
static int Aconv(Fmt*);
static int Dconv(Fmt*);
static int Pconv(Fmt*);
static int Rconv(Fmt*);
static int DSconv(Fmt*);
static int Mconv(Fmt*);
static int DRconv(Fmt*);
//
// Format conversions
// %A int Opcodes (instruction mnemonics)
//
// %D Addr* Addresses (instruction operands)
// Flags: "%lD": seperate the high and low words of a constant by "-"
//
// %P Prog* Instructions
//
// %R int Registers
//
// %$ char* String constant addresses (for internal use only)
// %^ int C_* classes (for liblink internal use)
#pragma varargck type "$" char*
#pragma varargck type "M" Addr*
void
listinit9(void)
{
fmtinstall('A', Aconv);
fmtinstall('D', Dconv);
fmtinstall('P', Pconv);
fmtinstall('R', Rconv);
// for liblink internal use
fmtinstall('^', DRconv);
// for internal use
fmtinstall('$', DSconv);
fmtinstall('M', Mconv);
}
static Prog* bigP;
static int
Pconv(Fmt *fp)
{
char str[STRINGSZ], *s;
Prog *p;
int a;
p = va_arg(fp->args, Prog*);
bigP = p;
a = p->as;
if(fp->flags & FmtSharp) {
s = str;
s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, a);
if(p->from.type != D_NONE)
s += sprint(s, " from={%#D}", &p->from);
if(p->reg)
s += sprint(s, " reg=%d", p->reg);
if(p->from3.type != D_NONE)
s += sprint(s, " from3={%#D}", &p->from3);
if(p->to.type != D_NONE)
s += sprint(s, " to={%#D}", &p->to);
return fmtstrcpy(fp, str);
}
if(a == ADATA || a == AINIT || a == ADYNT)
sprint(str, "%.5lld (%L) %A %D/%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
else if(a == ATEXT) {
if(p->reg != 0)
sprint(str, "%.5lld (%L) %A %D,%d,%lD", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
else
sprint(str, "%.5lld (%L) %A %D,%lD", p->pc, p->lineno, a, &p->from, &p->to);
} else if(a == AGLOBL) {
if(p->reg != 0)
sprint(str, "%.5lld (%L) %A %D,%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
else
sprint(str, "%.5lld (%L) %A %D,%D", p->pc, p->lineno, a, &p->from, &p->to);
} else {
s = str;
if(p->mark & NOSCHED)
s += sprint(s, "*");
if(p->reg == NREG && p->from3.type == D_NONE)
sprint(s, "%.5lld (%L) %A %D,%D", p->pc, p->lineno, a, &p->from, &p->to);
else
if(a != ATEXT && p->from.type == D_OREG) {
sprint(s, "%.5lld (%L) %A %lld(R%d+R%d),%D", p->pc, p->lineno, a,
p->from.offset, p->from.reg, p->reg, &p->to);
} else
if(p->to.type == D_OREG) {
sprint(s, "%.5lld (%L) %A %D,%lld(R%d+R%d)", p->pc, p->lineno, a,
&p->from, p->to.offset, p->to.reg, p->reg);
} else {
s += sprint(s, "%.5lld (%L) %A %D", p->pc, p->lineno, a, &p->from);
if(p->reg != NREG)
s += sprint(s, ",%c%d", p->from.type==D_FREG?'F':'R', p->reg);
if(p->from3.type != D_NONE)
s += sprint(s, ",%D", &p->from3);
sprint(s, ",%D", &p->to);
}
if(p->spadj != 0)
return fmtprint(fp, "%s # spadj=%d", str, p->spadj);
}
return fmtstrcpy(fp, str);
}
static int
Aconv(Fmt *fp)
{
char *s;
int a;
a = va_arg(fp->args, int);
s = "???";
if(a >= AXXX && a < ALAST)
s = anames9[a];
return fmtstrcpy(fp, s);
}
static int
Dconv(Fmt *fp)
{
char str[STRINGSZ];
Addr *a;
int32 v;
a = va_arg(fp->args, Addr*);
if(fp->flags & FmtSharp) {
char *s = str;
if(a->type == D_NONE) {
sprint(s, "type=NONE");
goto ret;
}
if(a->type >= 0 && a->type < D_LAST && dnames9[a->type] != nil)
s += sprint(s, "type=%s ", dnames9[a->type]);
else
s += sprint(s, "type=%d ", a->type);
if(a->name >= 0 && a->name < D_LAST && dnames9[a->name] != nil)
s += sprint(s, "name=%s ", dnames9[a->name]);
else
s += sprint(s, "name=%d ", a->name);
s += sprint(s, "offset=%ld etype=%E width=%d", a->offset, a->etype, a->width);
if(a->class != 0)
s += sprint(s, " class=%s", cnames9[a->class]);
if(a->reg != NREG)
s += sprint(s, " reg=%d", a->reg);
if(a->sym != nil)
s += sprint(s, " sym=%s", a->sym->name);
if(a->type == D_BRANCH && a->u.branch != nil)
s += sprint(s, " branch=%.5lld", a->u.branch->pc);
goto ret;
}
if(fp->flags & FmtLong) {
if(a->type == D_CONST)
sprint(str, "$%d-%d", (int32)a->offset, (int32)(a->offset>>32));
else {
// ATEXT dst is not constant
sprint(str, "!!%D", a);
}
goto ret;
}
switch(a->type) {
default:
sprint(str, "GOK-type(%d)", a->type);
break;
case D_NONE:
str[0] = 0;
if(a->name != D_NONE || a->reg != NREG || a->sym != nil)
sprint(str, "%M(R%d)(NONE)", a, a->reg);
break;
case D_CONST:
case D_DCONST:
if(a->reg != NREG)
sprint(str, "$%M(R%d)", a, a->reg);
else
sprint(str, "$%M", a);
break;
case D_OREG:
if(a->reg != NREG)
sprint(str, "%M(R%d)", a, a->reg);
else
sprint(str, "%M", a);
break;
case D_REG:
sprint(str, "R%d", a->reg);
if(a->name != D_NONE || a->sym != nil)
sprint(str, "%M(R%d)(REG)", a, a->reg);
break;
case D_FREG:
sprint(str, "F%d", a->reg);
if(a->name != D_NONE || a->sym != nil)
sprint(str, "%M(F%d)(REG)", a, a->reg);
break;
case D_CREG:
if(a->reg == NREG)
strcpy(str, "CR");
else
sprint(str, "CR%d", a->reg);
if(a->name != D_NONE || a->sym != nil)
sprint(str, "%M(C%d)(REG)", a, a->reg);
break;
case D_SPR:
if(a->name == D_NONE && a->sym == nil) {
switch((ulong)a->offset) {
case D_XER: sprint(str, "XER"); break;
case D_LR: sprint(str, "LR"); break;
case D_CTR: sprint(str, "CTR"); break;
default: sprint(str, "SPR(%lld)", a->offset); break;
}
break;
}
sprint(str, "SPR-GOK(%d)", a->reg);
if(a->name != D_NONE || a->sym != nil)
sprint(str, "%M(SPR-GOK%d)(REG)", a, a->reg);
break;
case D_DCR:
if(a->name == D_NONE && a->sym == nil) {
sprint(str, "DCR(%lld)", a->offset);
break;
}
sprint(str, "DCR-GOK(%d)", a->reg);
if(a->name != D_NONE || a->sym != nil)
sprint(str, "%M(DCR-GOK%d)(REG)", a, a->reg);
break;
case D_OPT:
sprint(str, "OPT(%d)", a->reg);
break;
case D_FPSCR:
if(a->reg == NREG)
strcpy(str, "FPSCR");
else
sprint(str, "FPSCR(%d)", a->reg);
break;
case D_MSR:
sprint(str, "MSR");
break;
case D_BRANCH:
if(bigP->pcond != nil) {
v = bigP->pcond->pc;
//if(v >= INITTEXT)
// v -= INITTEXT-HEADR;
if(a->sym != nil)
sprint(str, "%s+%.5lux(BRANCH)", a->sym->name, v);
else
sprint(str, "%.5lux(BRANCH)", v);
} else if(a->u.branch != nil)
sprint(str, "%lld", a->u.branch->pc);
else if(a->sym != nil)
sprint(str, "%s+%lld(APC)", a->sym->name, a->offset);
else
sprint(str, "%lld(APC)", a->offset);
break;
case D_FCONST:
//sprint(str, "$%lux-%lux", a->ieee.h, a->ieee.l);
sprint(str, "$%.17g", a->u.dval);
break;
case D_SCONST:
sprint(str, "$\"%$\"", a->u.sval);
break;
}
ret:
return fmtstrcpy(fp, str);
}
static int
Mconv(Fmt *fp)
{
char str[STRINGSZ];
Addr *a;
LSym *s;
int32 l;
a = va_arg(fp->args, Addr*);
s = a->sym;
//if(s == nil) {
// l = a->offset;
// if((vlong)l != a->offset)
// sprint(str, "0x%llux", a->offset);
// else
// sprint(str, "%lld", a->offset);
// goto out;
//}
switch(a->name) {
default:
sprint(str, "GOK-name(%d)", a->name);
break;
case D_NONE:
l = a->offset;
if((vlong)l != a->offset)
sprint(str, "0x%llux", a->offset);
else
sprint(str, "%lld", a->offset);
break;
case D_EXTERN:
if(a->offset != 0)
sprint(str, "%s+%lld(SB)", s->name, a->offset);
else
sprint(str, "%s(SB)", s->name, a->offset);
break;
case D_STATIC:
sprint(str, "%s<>+%lld(SB)", s->name, a->offset);
break;
case D_AUTO:
if(s == nil)
sprint(str, "%lld(SP)", -a->offset);
else
sprint(str, "%s-%lld(SP)", s->name, -a->offset);
break;
case D_PARAM:
if(s == nil)
sprint(str, "%lld(FP)", a->offset);
else
sprint(str, "%s+%lld(FP)", s->name, a->offset);
break;
}
//out:
return fmtstrcpy(fp, str);
}
static int
Rconv(Fmt *fp)
{
char str[STRINGSZ];
int r;
r = va_arg(fp->args, int);
if(r < NREG)
sprint(str, "r%d", r);
else
sprint(str, "f%d", r-NREG);
return fmtstrcpy(fp, str);
}
static int
DRconv(Fmt *fp)
{
char *s;
int a;
a = va_arg(fp->args, int);
s = "C_??";
if(a >= C_NONE && a <= C_NCLASS)
s = cnames9[a];
return fmtstrcpy(fp, s);
}
static int
DSconv(Fmt *fp)
{
int i, c;
char str[STRINGSZ], *p, *a;
a = va_arg(fp->args, char*);
p = str;
for(i=0; i<sizeof(int32); i++) {
c = a[i] & 0xff;
if(c >= 'a' && c <= 'z' ||
c >= 'A' && c <= 'Z' ||
c >= '0' && c <= '9' ||
c == ' ' || c == '%') {
*p++ = c;
continue;
}
*p++ = '\\';
switch(c) {
case 0:
*p++ = 'z';
continue;
case '\\':
case '"':
*p++ = c;
continue;
case '\n':
*p++ = 'n';
continue;
case '\t':
*p++ = 't';
continue;
}
*p++ = (c>>6) + '0';
*p++ = ((c>>3) & 7) + '0';
*p++ = (c & 7) + '0';
}
*p = 0;
return fmtstrcpy(fp, str);
}

1086
src/liblink/obj9.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -142,6 +142,8 @@ writeobj(Link *ctxt, Biobuf *b)
edata = nil;
for(pl = ctxt->plist; pl != nil; pl = pl->link) {
for(p = pl->firstpc; p != nil; p = plink) {
if(ctxt->debugasm && ctxt->debugvlog)
print("obj: %p %P\n", p, p);
plink = p->link;
p->link = nil;
@@ -365,7 +367,10 @@ writesym(Link *ctxt, Biobuf *b, LSym *s)
name = "";
if(r->sym != nil)
name = r->sym->name;
Bprint(ctxt->bso, "\trel %d+%d t=%d %s+%lld\n", (int)r->off, r->siz, r->type, name, (vlong)r->add);
if(ctxt->arch->thechar == '5' || ctxt->arch->thechar == '9')
Bprint(ctxt->bso, "\trel %d+%d t=%d %s+%llux\n", (int)r->off, r->siz, r->type, name, (vlong)r->add);
else
Bprint(ctxt->bso, "\trel %d+%d t=%d %s+%lld\n", (int)r->off, r->siz, r->type, name, (vlong)r->add);
}
}
@@ -777,7 +782,7 @@ rdsym(Link *ctxt, Biobuf *f, char *pkg)
s->type = SRODATA;
adduint32(ctxt, s, i32);
s->reachable = 0;
} else if(strncmp(s->name, "$f64.", 5) == 0) {
} else if(strncmp(s->name, "$f64.", 5) == 0 || strncmp(s->name, "$i64.", 5) == 0) {
int64 i64;
i64 = strtoull(s->name+5, nil, 16);
s->type = SRODATA;

835
src/liblink/sched9.c Normal file
View File

@@ -0,0 +1,835 @@
// cmd/9l/sched.c from Vita Nuova.
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// +build ignore
#include "l.h"
enum
{
E_ICC = 1<<0,
E_FCC = 1<<1,
E_MEM = 1<<2,
E_MEMSP = 1<<3, /* uses offset and size */
E_MEMSB = 1<<4, /* uses offset and size */
E_LR = 1<<5,
E_CR = 1<<6,
E_CTR = 1<<7,
E_XER = 1<<8,
E_CR0 = 0xF<<0,
E_CR1 = 0xF<<4,
ANYMEM = E_MEM|E_MEMSP|E_MEMSB,
ALL = ~0,
};
typedef struct Sch Sch;
typedef struct Dep Dep;
struct Dep
{
ulong ireg;
ulong freg;
ulong cc;
ulong cr;
};
struct Sch
{
Prog p;
Dep set;
Dep used;
long soffset;
char size;
char comp;
};
void regused(Sch*, Prog*);
int depend(Sch*, Sch*);
int conflict(Sch*, Sch*);
int offoverlap(Sch*, Sch*);
void dumpbits(Sch*, Dep*);
void
sched(Prog *p0, Prog *pe)
{
Prog *p, *q;
Sch sch[NSCHED], *s, *t, *u, *se, stmp;
if(!debug['Q'])
return;
/*
* build side structure
*/
s = sch;
for(p=p0;; p=p->link) {
memset(s, 0, sizeof(*s));
s->p = *p;
regused(s, p);
if(debug['X']) {
Bprint(&bso, "%P\tset", &s->p);
dumpbits(s, &s->set);
Bprint(&bso, "; used");
dumpbits(s, &s->used);
if(s->comp)
Bprint(&bso, "; compound");
if(s->p.mark & LOAD)
Bprint(&bso, "; load");
if(s->p.mark & BRANCH)
Bprint(&bso, "; branch");
if(s->p.mark & FCMP)
Bprint(&bso, "; fcmp");
Bprint(&bso, "\n");
}
s++;
if(p == pe)
break;
}
se = s;
for(s=se-1; s>=sch; s--) {
/*
* load delay. interlocked.
*/
if(s->p.mark & LOAD) {
if(s >= se-1)
continue;
if(!conflict(s, (s+1)))
continue;
/*
* s is load, s+1 is immediate use of result
* t is the trial instruction to insert between s and s+1
*/
for(t=s-1; t>=sch; t--) {
if(t->p.mark & BRANCH)
goto no2;
if(t->p.mark & FCMP)
if((s+1)->p.mark & BRANCH)
goto no2;
if(t->p.mark & LOAD)
if(conflict(t, (s+1)))
goto no2;
for(u=t+1; u<=s; u++)
if(depend(u, t))
goto no2;
goto out2;
no2:;
}
if(debug['X'])
Bprint(&bso, "?l%P\n", &s->p);
continue;
out2:
if(debug['X']) {
Bprint(&bso, "!l%P\n", &t->p);
Bprint(&bso, "%P\n", &s->p);
}
stmp = *t;
memmove(t, t+1, (uchar*)s - (uchar*)t);
*s = stmp;
s--;
continue;
}
/*
* fop2 delay.
*/
if(s->p.mark & FCMP) {
if(s >= se-1)
continue;
if(!((s+1)->p.mark & BRANCH))
continue;
/* t is the trial instruction to use */
for(t=s-1; t>=sch; t--) {
for(u=t+1; u<=s; u++)
if(depend(u, t))
goto no3;
goto out3;
no3:;
}
if(debug['X'])
Bprint(&bso, "?f%P\n", &s->p);
continue;
out3:
if(debug['X']) {
Bprint(&bso, "!f%P\n", &t->p);
Bprint(&bso, "%P\n", &s->p);
}
stmp = *t;
memmove(t, t+1, (uchar*)s - (uchar*)t);
*s = stmp;
s--;
continue;
}
}
/*
* put it all back
*/
for(s=sch, p=p0; s<se; s++, p=q) {
q = p->link;
if(q != s->p.link) {
*p = s->p;
p->link = q;
}
}
if(debug['X'])
Bprint(&bso, "\n");
}
void
regused(Sch *s, Prog *realp)
{
int c, ar, ad, ld, sz, nr, upd;
ulong m;
Prog *p;
p = &s->p;
s->comp = compound(p);
if(s->comp) {
s->set.ireg |= 1<<REGTMP;
s->used.ireg |= 1<<REGTMP;
}
ar = 0; /* dest is really reference */
ad = 0; /* source/dest is really address */
ld = 0; /* opcode is load instruction */
sz = 32*4; /* size of load/store for overlap computation */
nr = 0; /* source/dest is not really reg */
upd = 0; /* move with update; changes reg */
/*
* flags based on opcode
*/
switch(p->as) {
case ATEXT:
curtext = realp;
autosize = p->to.offset + 8;
ad = 1;
break;
case ABL:
s->set.cc |= E_LR;
ar = 1;
ad = 1;
break;
case ABR:
ar = 1;
ad = 1;
break;
case ACMP:
case ACMPU:
case ACMPW:
case ACMPWU:
s->set.cc |= E_ICC;
if(p->reg == 0)
s->set.cr |= E_CR0;
else
s->set.cr |= (0xF<<((p->reg&7)*4));
ar = 1;
break;
case AFCMPO:
case AFCMPU:
s->set.cc |= E_FCC;
if(p->reg == 0)
s->set.cr |= E_CR0;
else
s->set.cr |= (0xF<<((p->reg&7)*4));
ar = 1;
break;
case ACRAND:
case ACRANDN:
case ACREQV:
case ACRNAND:
case ACRNOR:
case ACROR:
case ACRORN:
case ACRXOR:
s->used.cr |= 1<<p->from.reg;
s->set.cr |= 1<<p->to.reg;
nr = 1;
break;
case ABCL: /* tricky */
s->used.cc |= E_FCC|E_ICC;
s->used.cr = ALL;
s->set.cc |= E_LR;
ar = 1;
break;
case ABC: /* tricky */
s->used.cc |= E_FCC|E_ICC;
s->used.cr = ALL;
ar = 1;
break;
case ABEQ:
case ABGE:
case ABGT:
case ABLE:
case ABLT:
case ABNE:
case ABVC:
case ABVS:
s->used.cc |= E_ICC;
s->used.cr |= E_CR0;
ar = 1;
break;
case ALSW:
case AMOVMW:
/* could do better */
sz = 32*4;
ld = 1;
break;
case AMOVBU:
case AMOVBZU:
upd = 1;
sz = 1;
ld = 1;
break;
case AMOVB:
case AMOVBZ:
sz = 1;
ld = 1;
break;
case AMOVHU:
case AMOVHZU:
upd = 1;
sz = 2;
ld = 1;
break;
case AMOVH:
case AMOVHBR:
case AMOVHZ:
sz = 2;
ld = 1;
break;
case AFMOVSU:
case AMOVWU:
case AMOVWZU:
upd = 1;
sz = 4;
ld = 1;
break;
case AFMOVS:
case AMOVW:
case AMOVWZ:
case AMOVWBR:
case ALWAR:
sz = 4;
ld = 1;
break;
case AFMOVDU:
upd = 1;
sz = 8;
ld = 1;
break;
case AFMOVD:
sz = 8;
ld = 1;
break;
case AFMOVDCC:
sz = 8;
ld = 1;
s->set.cc |= E_FCC;
s->set.cr |= E_CR1;
break;
case AMOVFL:
case AMOVCRFS:
case AMTFSB0:
case AMTFSB0CC:
case AMTFSB1:
case AMTFSB1CC:
s->set.ireg = ALL;
s->set.freg = ALL;
s->set.cc = ALL;
s->set.cr = ALL;
break;
case AADDCC:
case AADDVCC:
case AADDCCC:
case AADDCVCC:
case AADDMECC:
case AADDMEVCC:
case AADDECC:
case AADDEVCC:
case AADDZECC:
case AADDZEVCC:
case AANDCC:
case AANDNCC:
case ACNTLZWCC:
case ADIVWCC:
case ADIVWVCC:
case ADIVWUCC:
case ADIVWUVCC:
case AEQVCC:
case AEXTSBCC:
case AEXTSHCC:
case AMULHWCC:
case AMULHWUCC:
case AMULLWCC:
case AMULLWVCC:
case ANANDCC:
case ANEGCC:
case ANEGVCC:
case ANORCC:
case AORCC:
case AORNCC:
case AREMCC:
case AREMVCC:
case AREMUCC:
case AREMUVCC:
case ARLWMICC:
case ARLWNMCC:
case ASLWCC:
case ASRAWCC:
case ASRWCC:
case ASTWCCC:
case ASUBCC:
case ASUBVCC:
case ASUBCCC:
case ASUBCVCC:
case ASUBMECC:
case ASUBMEVCC:
case ASUBECC:
case ASUBEVCC:
case ASUBZECC:
case ASUBZEVCC:
case AXORCC:
s->set.cc |= E_ICC;
s->set.cr |= E_CR0;
break;
case AFABSCC:
case AFADDCC:
case AFADDSCC:
case AFCTIWCC:
case AFCTIWZCC:
case AFDIVCC:
case AFDIVSCC:
case AFMADDCC:
case AFMADDSCC:
case AFMSUBCC:
case AFMSUBSCC:
case AFMULCC:
case AFMULSCC:
case AFNABSCC:
case AFNEGCC:
case AFNMADDCC:
case AFNMADDSCC:
case AFNMSUBCC:
case AFNMSUBSCC:
case AFRSPCC:
case AFSUBCC:
case AFSUBSCC:
s->set.cc |= E_FCC;
s->set.cr |= E_CR1;
break;
}
/*
* flags based on 'to' field
*/
c = p->to.class;
if(c == 0) {
c = aclass(&p->to) + 1;
p->to.class = c;
}
c--;
switch(c) {
default:
print("unknown class %d %D\n", c, &p->to);
case C_NONE:
case C_ZCON:
case C_SCON:
case C_UCON:
case C_LCON:
case C_ADDCON:
case C_ANDCON:
case C_SBRA:
case C_LBRA:
break;
case C_CREG:
c = p->to.reg;
if(c == NREG)
s->set.cr = ALL;
else
s->set.cr |= (0xF << ((p->from.reg&7)*4));
s->set.cc = ALL;
break;
case C_SPR:
case C_FPSCR:
case C_MSR:
case C_XER:
s->set.ireg = ALL;
s->set.freg = ALL;
s->set.cc = ALL;
s->set.cr = ALL;
break;
case C_LR:
s->set.cc |= E_LR;
break;
case C_CTR:
s->set.cc |= E_CTR;
break;
case C_ZOREG:
case C_SOREG:
case C_LOREG:
c = p->to.reg;
s->used.ireg |= 1<<c;
if(upd)
s->set.ireg |= 1<<c;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->to);
m = ANYMEM;
if(c == REGSB)
m = E_MEMSB;
if(c == REGSP)
m = E_MEMSP;
if(ar)
s->used.cc |= m;
else
s->set.cc |= m;
break;
case C_SACON:
case C_LACON:
s->used.ireg |= 1<<REGSP;
if(upd)
s->set.ireg |= 1<<c;
break;
case C_SECON:
case C_LECON:
s->used.ireg |= 1<<REGSB;
if(upd)
s->set.ireg |= 1<<c;
break;
case C_REG:
if(nr)
break;
if(ar)
s->used.ireg |= 1<<p->to.reg;
else
s->set.ireg |= 1<<p->to.reg;
break;
case C_FREG:
if(ar)
s->used.freg |= 1<<p->to.reg;
else
s->set.freg |= 1<<p->to.reg;
break;
case C_SAUTO:
case C_LAUTO:
s->used.ireg |= 1<<REGSP;
if(upd)
s->set.ireg |= 1<<c;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->to);
if(ar)
s->used.cc |= E_MEMSP;
else
s->set.cc |= E_MEMSP;
break;
case C_SEXT:
case C_LEXT:
s->used.ireg |= 1<<REGSB;
if(upd)
s->set.ireg |= 1<<c;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->to);
if(ar)
s->used.cc |= E_MEMSB;
else
s->set.cc |= E_MEMSB;
break;
}
/*
* flags based on 'from' field
*/
c = p->from.class;
if(c == 0) {
c = aclass(&p->from) + 1;
p->from.class = c;
}
c--;
switch(c) {
default:
print("unknown class %d %D\n", c, &p->from);
case C_NONE:
case C_ZCON:
case C_SCON:
case C_UCON:
case C_LCON:
case C_ADDCON:
case C_ANDCON:
case C_SBRA:
case C_LBRA:
c = p->from.reg;
if(c != NREG)
s->used.ireg |= 1<<c;
break;
case C_CREG:
c = p->from.reg;
if(c == NREG)
s->used.cr = ALL;
else
s->used.cr |= (0xF << ((p->from.reg&7)*4));
s->used.cc = ALL;
break;
case C_SPR:
case C_FPSCR:
case C_MSR:
case C_XER:
s->set.ireg = ALL;
s->set.freg = ALL;
s->set.cc = ALL;
s->set.cr = ALL;
break;
case C_LR:
s->used.cc |= E_LR;
break;
case C_CTR:
s->used.cc |= E_CTR;
break;
case C_ZOREG:
case C_SOREG:
case C_LOREG:
c = p->from.reg;
s->used.ireg |= 1<<c;
if(ld)
p->mark |= LOAD;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->from);
m = ANYMEM;
if(c == REGSB)
m = E_MEMSB;
if(c == REGSP)
m = E_MEMSP;
s->used.cc |= m;
break;
case C_SACON:
case C_LACON:
s->used.ireg |= 1<<REGSP;
break;
case C_SECON:
case C_LECON:
s->used.ireg |= 1<<REGSB;
break;
case C_REG:
if(nr)
break;
s->used.ireg |= 1<<p->from.reg;
break;
case C_FREG:
s->used.freg |= 1<<p->from.reg;
break;
case C_SAUTO:
case C_LAUTO:
s->used.ireg |= 1<<REGSP;
if(ld)
p->mark |= LOAD;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->from);
s->used.cc |= E_MEMSP;
break;
case C_SEXT:
case C_LEXT:
s->used.ireg |= 1<<REGSB;
if(ld)
p->mark |= LOAD;
if(ad)
break;
s->size = sz;
s->soffset = regoff(&p->from);
s->used.cc |= E_MEMSB;
break;
}
c = p->reg;
if(c != NREG) {
if(p->from.type == D_FREG || p->to.type == D_FREG)
s->used.freg |= 1<<c;
else
s->used.ireg |= 1<<c;
}
}
/*
* test to see if 2 instrictions can be
* interchanged without changing semantics
*/
int
depend(Sch *sa, Sch *sb)
{
ulong x;
if(sa->set.ireg & (sb->set.ireg|sb->used.ireg))
return 1;
if(sb->set.ireg & sa->used.ireg)
return 1;
if(sa->set.freg & (sb->set.freg|sb->used.freg))
return 1;
if(sb->set.freg & sa->used.freg)
return 1;
if(sa->set.cr & (sb->set.cr|sb->used.cr))
return 1;
if(sb->set.cr & sa->used.cr)
return 1;
x = (sa->set.cc & (sb->set.cc|sb->used.cc)) |
(sb->set.cc & sa->used.cc);
if(x) {
/*
* allow SB and SP to pass each other.
* allow SB to pass SB iff doffsets are ok
* anything else conflicts
*/
if(x != E_MEMSP && x != E_MEMSB)
return 1;
x = sa->set.cc | sb->set.cc |
sa->used.cc | sb->used.cc;
if(x & E_MEM)
return 1;
if(offoverlap(sa, sb))
return 1;
}
return 0;
}
int
offoverlap(Sch *sa, Sch *sb)
{
if(sa->soffset < sb->soffset) {
if(sa->soffset+sa->size > sb->soffset)
return 1;
return 0;
}
if(sb->soffset+sb->size > sa->soffset)
return 1;
return 0;
}
/*
* test 2 adjacent instructions
* and find out if inserted instructions
* are desired to prevent stalls.
* first instruction is a load instruction.
*/
int
conflict(Sch *sa, Sch *sb)
{
if(sa->set.ireg & sb->used.ireg)
return 1;
if(sa->set.freg & sb->used.freg)
return 1;
if(sa->set.cr & sb->used.cr)
return 1;
return 0;
}
int
compound(Prog *p)
{
Optab *o;
o = oplook(p);
if(o->size != 4)
return 1;
if(p->to.type == D_REG && p->to.reg == REGSB)
return 1;
return 0;
}
void
dumpbits(Sch *s, Dep *d)
{
int i;
for(i=0; i<32; i++)
if(d->ireg & (1<<i))
Bprint(&bso, " R%d", i);
for(i=0; i<32; i++)
if(d->freg & (1<<i))
Bprint(&bso, " F%d", i);
for(i=0; i<32; i++)
if(d->cr & (1<<i))
Bprint(&bso, " C%d", i);
for(i=0; i<32; i++)
switch(d->cc & (1<<i)) {
default:
break;
case E_ICC:
Bprint(&bso, " ICC");
break;
case E_FCC:
Bprint(&bso, " FCC");
break;
case E_LR:
Bprint(&bso, " LR");
break;
case E_CR:
Bprint(&bso, " CR");
break;
case E_CTR:
Bprint(&bso, " CTR");
break;
case E_XER:
Bprint(&bso, " XER");
break;
case E_MEM:
Bprint(&bso, " MEM%d", s->size);
break;
case E_MEMSB:
Bprint(&bso, " SB%d", s->size);
break;
case E_MEMSP:
Bprint(&bso, " SP%d", s->size);
break;
}
}

14
src/math/abs_power64x.s Normal file
View File

@@ -0,0 +1,14 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build power64 power64le
#include "textflag.h"
TEXT ·Abs(SB),NOSPLIT,$0-16
MOVD x+0(FP), R3
MOVD $((1<<63)-1), R4
AND R4, R3
MOVD R3, ret+8(FP)
RETURN

View File

@@ -0,0 +1,46 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build power64 power64le
#include "textflag.h"
// This file provides fast assembly versions for the elementary
// arithmetic operations on vectors implemented in arith.go.
TEXT ·mulWW(SB),NOSPLIT,$0
BR ·mulWW_g(SB)
TEXT ·divWW(SB),NOSPLIT,$0
BR ·divWW_g(SB)
TEXT ·addVV(SB),NOSPLIT,$0
BR ·addVV_g(SB)
TEXT ·subVV(SB),NOSPLIT,$0
BR ·subVV_g(SB)
TEXT ·addVW(SB),NOSPLIT,$0
BR ·addVW_g(SB)
TEXT ·subVW(SB),NOSPLIT,$0
BR ·subVW_g(SB)
TEXT ·shlVU(SB),NOSPLIT,$0
BR ·shlVU_g(SB)
TEXT ·shrVU(SB),NOSPLIT,$0
BR ·shrVU_g(SB)
TEXT ·mulAddVWW(SB),NOSPLIT,$0
BR ·mulAddVWW_g(SB)
TEXT ·addMulVVW(SB),NOSPLIT,$0
BR ·addMulVVW_g(SB)
TEXT ·divWVW(SB),NOSPLIT,$0
BR ·divWVW_g(SB)
TEXT ·bitLen(SB),NOSPLIT,$0
BR ·bitLen_g(SB)

Some files were not shown because too many files have changed in this diff Show More