Monday, May 01, 2006

Assembler templates

I've finished updating the PowerPC and x86 backends for the new compiler design, and new boot images are up. AMD64 will have to wait a few days.

If you study the compiler source, you will find many calls to the words with-template and define-intrinsic; the former is called during code generation time to load inputs from the stack to registers, and store registers back to the stack. The latter associates a word with a compiler intrinsic quotation which passes the specified arguments to with-template.

Here is a typical definition:
: generate-fixnum-mod
#! PowerPC doesn't have a MOD instruction; so we compute
#! x-(x/y)*y. Puts the result in "s" operand.
"s" operand "r" operand "y" operand MULLW
"s" operand "s" operand "x" operand SUBF ;

\ fixnum-mod [
! divide x by y, store result in x
"r" operand "x" operand "y" operand DIVW
generate-fixnum-mod
] H{
{ +input { { f "x" } { f "y" } } }
{ +scratch { { f "r" } { f "s" } } }
{ +output { "s" } }
} define-intrinsic

This looks like a macro assembler; the operands "x", "y", "r" and "s" are assigned at compile time, and used to generate an assembly segment involving various instructions, such as MULLW and SUBF.

The complete list of specifiers which can be passed as keys in the hashtable there is as follows:
  • +input - an array of pairs, where each pair is of the form { vreg string }; the string is an operand name, and the vreg is either an integer or f (meaning any free register can be assigned). The with-template form compiles code to load objects from the stack into the input registers
  • +scratch - this specifier is of the same format as +input, except here the registers are untouched. The body of the template can use them for any purpose, including outputs.
  • +output - a list of previously-assigned operand names holding values which should be moved to the stack. Registers allocated by +input and +scratch can be listed here.
  • +scratch - a list of previously-assigned operand names whose contents should not be assumed to have remained constant after the template finishes executing. Usually a template does not modify its inputs; however if it does, they must be listed here to avoid miscompiling code.

I'm going to implement a few assorted cleanups and optimizations now, and then move on to floating point intrinsics, which should provide a nice performance boost.

No comments: