133 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
.\" $Header$
 | 
						|
.TL
 | 
						|
Addition of register variables to an existing table.
 | 
						|
.NH 1
 | 
						|
Introduction
 | 
						|
.PP
 | 
						|
This is a short description of the newest feature in the
 | 
						|
table driven code generator for the Amsterdam Compiler Kit.
 | 
						|
It describes how to add register variables to an existing table.
 | 
						|
This assumes you have the distribution of October 1983 or later.
 | 
						|
It is not clear whether you should read this when starting with
 | 
						|
a table for a new machine,
 | 
						|
or whether you should wait till the table is well debugged already.
 | 
						|
.NH 1
 | 
						|
Modifications to the table itself.
 | 
						|
.NH 2
 | 
						|
Register section
 | 
						|
.PP
 | 
						|
You can add just before the properties of the register one
 | 
						|
of the following:
 | 
						|
.IP - 2
 | 
						|
regvar
 | 
						|
.IP -
 | 
						|
regvar ( pointer )
 | 
						|
.IP -
 | 
						|
regvar ( loop )
 | 
						|
.IP -
 | 
						|
regvar ( float )
 | 
						|
.LP
 | 
						|
All register variables of one type must be of the same size,
 | 
						|
and they may have no subregisters.
 | 
						|
.NH 2
 | 
						|
Codesection
 | 
						|
.PP
 | 
						|
.IP - 2
 | 
						|
Two pseudo functions are added to the list allowed inside expressions:
 | 
						|
.RS
 | 
						|
.IP 1) 3
 | 
						|
inreg ( expr ) has as a parameter the offset of a local,
 | 
						|
and returns 0,1 or 2:
 | 
						|
.RS
 | 
						|
.IP 2: 3
 | 
						|
if the variable is in a register.
 | 
						|
.IP 1:
 | 
						|
if the variable could be in a register but isn't.
 | 
						|
.IP 0:
 | 
						|
if the variable cannot be in a register.
 | 
						|
.RE
 | 
						|
.IP 2)
 | 
						|
regvar ( expr ) returns the register associated with the variable.
 | 
						|
Undefined if it is not in a register.
 | 
						|
So regvar ( expr ) is defined if and only if inreg (expr ) == 2.
 | 
						|
.RE
 | 
						|
.IP -
 | 
						|
It is now possible to remove() a register expression,
 | 
						|
this is of course needed for a store into a register local.
 | 
						|
.IP -
 | 
						|
The return out of a procedure may now involve register restores,
 | 
						|
so the special word 'return' in the table will invoke a user defined
 | 
						|
function.
 | 
						|
.NH 1
 | 
						|
Modifications to mach.c
 | 
						|
.PP
 | 
						|
If register variables are used in a table, the program
 | 
						|
.I cgg
 | 
						|
will define the word REGVARS during compilation of the sources.
 | 
						|
So the following functions described here should be bracketed
 | 
						|
by #ifdef REGVARS and #endif.
 | 
						|
.IP - 2
 | 
						|
regscore(off,size,typ,freq,totyp) long off;
 | 
						|
.br
 | 
						|
This function should assign a score to a register variable,
 | 
						|
the score should preferably be the estimated number of bytes
 | 
						|
gained when it is put in a register.
 | 
						|
Off and size are the offset and size of the variable,
 | 
						|
typ is the type, that is reg_any, reg_pointer, reg_loop or reg_float.
 | 
						|
Freq is the number of times it occurs statically, and totyp
 | 
						|
is the type of the register it is planned to go into.
 | 
						|
.br
 | 
						|
Keep in mind that the gain should be net, that is the cost for
 | 
						|
register save/restore sequences and the cost of initialisation
 | 
						|
in the case of parameters should already be included.
 | 
						|
.IP -
 | 
						|
i_regsave()
 | 
						|
.br
 | 
						|
This function is called at the start of a procedure, just before
 | 
						|
register saves are done.
 | 
						|
It can be used to initialise some variables if needed.
 | 
						|
.IP -
 | 
						|
f_regsave()
 | 
						|
.br
 | 
						|
This function is called at end of the register save sequence.
 | 
						|
It can be used to do the real saving if multiple register move
 | 
						|
instructions are available.
 | 
						|
.IP -
 | 
						|
regsave(regstr,off,size) char *regstr; long off;
 | 
						|
.br
 | 
						|
Should either do the real saving or set up a table to have
 | 
						|
it done by f_regsave.
 | 
						|
Note that initialisation of parameters should also be done,
 | 
						|
or planned here.
 | 
						|
.IP -
 | 
						|
regreturn()
 | 
						|
.br
 | 
						|
Should restore saved registers and return.
 | 
						|
The function result is already in the function return area by now.
 | 
						|
.NH 1
 | 
						|
Examples
 | 
						|
.PP
 | 
						|
Here are some examples out of the PDP 11 table
 | 
						|
.DS
 | 
						|
lol inreg($1)==2| |		| regvar($1)			| |
 | 
						|
 | 
						|
lil inreg($1)==2| |		| {regdef2, regvar($1)}		| |
 | 
						|
 | 
						|
stl inreg($1)==2| xsource2 |
 | 
						|
			remove(regvar($1))
 | 
						|
			move(%[1],regvar($1))              |       | |
 | 
						|
 | 
						|
inl inreg($1)==2| |     remove(regvar($1))
 | 
						|
			"inc %(regvar($1)%)"
 | 
						|
			setcc(regvar($1))          |       | |
 | 
						|
.DE
 | 
						|
.NH 1
 | 
						|
Afterthoughts.
 | 
						|
.PP
 | 
						|
At the time of this writing the tables for the PDP 11 and the M68000 and
 | 
						|
the VAX are converted, in all cases the two byte wordsize versions.
 | 
						|
No big problems have occurred, but experience has shown that it is
 | 
						|
necessary to check your table carefully for all patterns with locals in them
 | 
						|
because if you forget one code will be generated by that one coderule
 | 
						|
to use the memoryslot the local is not in.
 | 
						|
 |