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.
 | |
| 
 |