Transputer backend overview
---------------------------
Transputer backend is not part of GCC distribution yet; instead, it is
available as a patch against the "official" GCC 2.7.2 distribution
(gcc-2.7.2.tar.gz).
It allows one to build a cross compiler that runs on a host capable of
running GCC in general and produces transputer assembly language output.
Features and peculiarities
~~~~~~~~~~~~~~~~~~~~~~~~~~
* SUPPORTED: code generation for most (all?) 32-bit transputers
(t800, t805, t425, t9000, t450)
* SUPPORTED: asm_operands.
* SUPPORTED: floating point instructions. However, no attempt is
made to optimize ALU and FPU operation overlapping.
* UNSUPPORTED: debugging info output. Just not ripe enough for now.
* UNSUPPORTED: nested functions (GNU extension to C). You can work
around this limitation by using a preprocessor macro instead.
* if you want code quality to be any decent, compile with -O. That's
because reload pass cannot do well for transputer without register
life info.
Run-time models supported
~~~~~~~~~~~~~~~~~~~~~~~~~
There are currently two of them. The first (generic) one is a
home-made model, hardly corresponding to any other model in existence.
In this model, no static chain is passed in function call; instead,
global data are addressed relative to program counter (Iptr). First
three words of function arguments are passed on integer register
stack. The benefits of this model are compact function prologues and
cheap function calls; on the other hand, it leaves no way to implement
a stack expansion scheme.
The binary tools (assembler, linker, etc.) for use with this model are
now available. Check , or
. Some libraries are available
too -- thanks to Roman Pozlevich
The second model (Expert) is compatible with the one used by ACE
Expert compilers in the Parix OS. The description of the model can be
found in the Parix documentation.
The two models are very different, and hopefully solve most problems
that might arise when porting GCC to other transputer-based platforms.
Transputer-specific compiler options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-mt800, -mt805, -mt425, -mt9000, -mt450
Run-time selection of target CPU type. Default is the processor
type you give to configure when building the compiler.
-mfpu, -mno-fpu
-mfpentry, -mno-fpentry
-mfpge, -mno-fpge
-mpop, -mno-pop
-mgtu, -mno-gtu
-msixteen, -mno-sixteen
-mxtend, -mno-xtend
-mslmul, -mno-slmul
Switches that enable/disable use of certain CPU capabilities. Each
of the -mtNNN target CPU selection options actually works by setting
certain combination of these. Hope you don't want to fiddle with
them; but if you do, search config/t800.h for their meaning.
-mshort16, -mshort32
Size for the "short int" type in bits. Default is 16 on transputers
that have support for 16-bit memory access (ls/ss), 32 on transputers
that don't have it. Specifying -mshort16 in the latter case results in
implementation of halfword stores using shift and byte store instructions.
Random examples of inline assembly usage
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
get_timer ()
{
int tmp;
asm volatile
("ldtimer"
: "=a" (tmp)
: /* no inputs */ );
return tmp;
}
This asm takes no inputs, and pushes one word of result onto the
integer reg-stack, according to the `a' constraint.
Constraint letters meaning:
a,b,c Areg,Breg,Creg respectively
t,v,u FAreg, FBreg, FCreg respectively
P popped input constraint modifier.
Example 2.
void
outword (unsigned word, unsigned chan)
{
asm volatile
("outword"
: /* no outputs */
: "bP" (chan), "aP" (word)
: "Areg", "Breg", "Creg", "FAreg", "FBreg", "FCreg", "Wreg[0]");
}
This asm consumes two inputs which come in Areg and Breg. The
modifier constraint `P' indicates that the input is popped off the
stack by the asm. The clobber section indicates that the asm clobbers
all stack registers.
"Wreg[0]" in the clobber section indicates that this asm destroys the
value of the word at the top of workspace. Note that "Wreg[0]" is
just an identifier; you cannot write, say, "Wreg[1]" here.
Note that popping constraint is not a substitute for a clobber; thus,
following asm would not reflect the fact that all registers are
clobbered by this asm (and so is incorrect):
void
outword (unsigned word, unsigned chan)
{
asm volatile
("outword"
: /* no outputs */
: "bP" (chan), "aP" (word)
: "Creg", "FAreg", "FBreg", "FCreg", "Wreg[0]");
}
Example 3.
float
square_root (float x)
{
register float tmp;
asm ("fpusqrtfirst\n\t"
"fpusqrtstep\n\t"
"fpusqrtstep\n\t"
"fpusqrtlast"
: "=t" (tmp)
: "tP" (x)
: "FBreg", "FCreg");
return tmp;
}
This asm pops its input off floating reg-stack, and pushes the result
back onto the floating reg-stack.
Example 4, from real life
static inline int
lit_load_in_byte (void)
{
int tmp = 0;
extern int boot_link_in;
asm volatile
("in"
: /* no outputs */
: "cP" (&tmp),
"bP" (boot_link_in),
"aP" (1)
: "Areg", "Breg", "Creg", "FAreg", "FBreg", "FCreg", "memory");
return tmp;
}
Here the asm inputs a byte from a link whose address is stored in
`boot_link_in'. Note that this asm has no explicit outputs, but puts
its result into memory (the `tmp' variable) as a side-effect. You
have to explicitly tell the compiler that the asm modifies memory;
that's what the "memory" in the clobber section of the asm is for.
Without it, the optimiser would rightfully optimize this function to
always return 0.
Note that the order of input operands in asms matters: supplying the
operands in reverse order (Creg, Breg, Areg), as in the above asm,
tends to give better code.
One more example, making use of local temporary variable
(from Roman Pozlevich, ):
int *alt (int* first, ...) {
int *res, **ptr;
__asm__ __volatile__ (
" alt \n\t"
" ldlp %w2; stl %w1 \n\t"
"0: \n\t"
" ldl %w1; ldnl 0; cj 1f \n\t"
" ldl %w1; ldnl 0; ldc 1; enbc \n\t"
" ldl %w1; ldnlp 1; stl %w1 \n\t"
" ldc 0; cj 0b \n\t"
"1: \n\t"
" altwt \n\t"
" ldlp %w2; stl %w1 \n\t"
"0: \n\t"
" ldl %w1; ldnl 0; cj 1f \n\t"
" ldl %w1; ldnl 0; dup; ldc 1; rev; disc \n\t"
" eqc 0; cj 1f \n\t"
" ldl %w1; ldnlp 1; stl %w1 \n\t"
" ldc 0; cj 0b \n\t"
"1: \n\t"
" ldl 0 \n\t"
: "=a" (res)
: "m" (ptr), "m" (first)
: "Breg", "Creg", "FAreg", "FBreg", "FCreg", "Wreg[0]"
);
return res;
}
You most likely don't want to understand what this code is doing, but
note the use of "m" constraint for local variables, and the use of
"%wN" to obtain stack offset in words for Nth operand of the asm.
Where to get T800 patches
~~~~~~~~~~~~~~~~~~~~~~~~~
The most recent version is always at
ftp://ftp.botik.ru/pub/local/gcc-t800/gcc-2.7.2
The port as a diff against gcc-2.7.2 is in the file
gcc-2.7.2-t800.NNN.dif.gz, where NNN is the alpha release number.
You most probably want to pick the largest numbered one.
patchNNN.gz contains patches from alpha release MMM to alpha release
NNN, where MMM=NNN-1. changesNNN contain a short overview of the
changes.
You can also find gcc-t800 at the mirror in UK:
ftp://unix.hensa.ac.uk/pub/parallel/transputer/software/compilers/gcc/pereslavl/
http://www.hensa.ac.uk/parallel/transputer/software/compilers/gcc/pereslavl/
Feedback
~~~~~~~~
Please e-mail bug reports to me at .
DO NOT send any bug reports for gcc-t800 to the GNU bug-gcc list
where GCC bugs normally go; gcc-t800 is not yet an official part of
GCC.
There is a (mostly inactive) mailing list for gcc-t800:
. If you want to subscribe to the list, send
e-mail with a line like this:
subscribe
to .
Installation
~~~~~~~~~~~~
(1) Apply T800 patches to the stock GCC distribution:
cd gcc-2.7.2
gzip -dc gcc-2.7.2-t800.12.dif.gz | patch -p1
(2) Configure the sources for the target of your choice.
Example 1: configure for `generic' model. This is what you need
if you are going to use gcc-t800 with TTOOLS.
./configure --target=t800
Note: this chooses t800 as the default CPU type. You can
however use the compiler thus built for other cpu types
by running `gcc -mt425', for example.
Example 2: configure for `expert' model
./configure --target=t800-parix
Example 3: configure for `expert' model, install in a private
directory rather than in /usr/local
./configure --target=t800-parix --prefix=$(HOME)/usr
(3) If you are impatient and want to try it out quickly, do
make LANGUAGES=c CC=gcc cc1
cc1 -O pself.c
more pself.s
(4) Follow the normal procedure for building and installing a cross
compiler, described in INSTALL. In short, the following might work:
make LANGUAGES=c CC=gcc
make install
While making, you will see warnings about `-g' and `-g1' options
being unsupported by the compiler -- indeed, debugging info
output is not yet supported. Ignore the warnings.
Acknowledgements
~~~~~~~~~~~~~~~~
FSF people provided the World with the GNU C Compiler.
Sergei Abramov enabled me to work on this port.
Kriton Kyrimis of High Performance Computing Laboratory, Athens,
inspired the port to Parix/GCel, and helped to work on it.
This work was in part supported by INTAS--International Association
for the promotion of cooperation with scientists from the independent
states of the former Soviet Union; grant # INTAS-93-0972
Dave Beckett easies life to the downloaders
of the package by mirroring gcc-t800 and TTOOLS at unix.hensa.ac.uk.
Thanks to all.
$Revision: 1.17 $