deep

a Cross Development Platform for Java

User Tools

Site Tools


dev:crosscompiler:backend_ppc:code_generator

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
dev:crosscompiler:backend_ppc:code_generator [2015/12/16 12:03] – [Stackframe] ursgrafdev:crosscompiler:backend_ppc:code_generator [2022/12/20 15:52] (current) – [Accessing the Hardware] ursgraf
Line 1: Line 1:
-====== Code Generator ======+====== Code Generator for PPC ======
 All results of all SSA instructions have an assigned register. Now, each SSA instruction can be translated into one or a sequence of machine instructions. In order to do this, we must define the stackframe, which is used when calling a method. All results of all SSA instructions have an assigned register. Now, each SSA instruction can be translated into one or a sequence of machine instructions. In order to do this, we must define the stackframe, which is used when calling a method.
  
 ===== Stackframe ===== ===== Stackframe =====
 We use a stack pointer (R1) but no frame pointer. We use a stack pointer (R1) but no frame pointer.
-[{{ .:stackframe.png?350&direct | // Stack frame for method calls //}}] +[{{ .:stackframeppc.png?350&direct | // Stack frame for method calls //}}] 
  
 Explanation: Explanation:
 LR is saved onto the stack first. Side note: This could be optimized, if method is a leaf method LR can stay unsaved. CTR, CR and XER need not to be saved. All of them might be used but they are never used across method calls. Considering the GPR's and FPR's, all nonvolatile register, which are used within this method, must be saved on the stack. Important: volatile FPR's must be saved as well if ''US.ENABLE_FLOATS()'' is called in this method (see [[.:exceptions|Exceptions]]).\\  LR is saved onto the stack first. Side note: This could be optimized, if method is a leaf method LR can stay unsaved. CTR, CR and XER need not to be saved. All of them might be used but they are never used across method calls. Considering the GPR's and FPR's, all nonvolatile register, which are used within this method, must be saved on the stack. Important: volatile FPR's must be saved as well if ''US.ENABLE_FLOATS()'' is called in this method (see [[.:exceptions|Exceptions]]).\\ 
-The field //local variables// is only used if the number of registers does not suffice. When dealing with FPR's some temprary space on the stack might be necessary (//temp. memory//). Some compiler specific subroutines dealing with //long// operations need the same space for saving and restoring some registers which are used therein.  \\  +The field //local variables// is only used if the number of registers does not suffice. When dealing with FPR's some temporary space on the stack might be necessary (//temp. memory//). Some compiler specific subroutines dealing with //long// operations need the same space for saving and restoring some registers which are used therein.  \\  
-Padding ensures that the stack frame is always a multiple of 16 bytes (quad-word aligned). \\ The field //parameter// serves to hold parameters for method calls, which can not be placed directly into registers. The size of the field //parameters// is determined by considering all the calls to other methods within this method and taking the maximum size of their parameters. //parameters// must be on top of the stack! This garantees that in all called methods these parameters can be accessed with the same offset. \\ +Padding ensures that the stack frame is always a multiple of 16 bytes (quad-word aligned). \\ The field //parameter// serves to hold parameters for method calls, which can not be placed directly into registers. The size of the field //parameters// is determined by considering all the calls to other methods within this method and taking the maximum size of their parameters. //parameters// must be at the top of the stack! This garantees that in all called methods these parameters can be accessed with the same offset. \\ 
 The stack pointer always points to the top of the actual frame. At the top the stack pointer of the caller has to be stored. When creating a new frame the relocation of the pointer and storing of its previous value must be atomic. This is achieved with the instruction //stwu//. When leaving the method in the epilogue a simple instruction //addi// suffices, since the compiler knows the size of the frame. The back chain pointer is used for the debugger, for exceptions and for the garbage collection. The stack pointer always points to the top of the actual frame. At the top the stack pointer of the caller has to be stored. When creating a new frame the relocation of the pointer and storing of its previous value must be atomic. This is achieved with the instruction //stwu//. When leaving the method in the epilogue a simple instruction //addi// suffices, since the compiler knows the size of the frame. The back chain pointer is used for the debugger, for exceptions and for the garbage collection.
 \\ \\
Line 33: Line 33:
   * Addresses of class variables   * Addresses of class variables
   * Addresses of constants (floats, strings, type descriptors)   * Addresses of constants (floats, strings, type descriptors)
-Such addresses must be loaded with the aid of an auxilliary (with //addi// and //addis//). After linking these addresses are known and must be corrected in the code. For this purpose a table called //fixups// is maintained. It contains all references to the objects, which were created by the class file reader and which final addresses must be inserted into the code. In order to know at what position in the machine code array a certain correction has to be made, the next position is stored in the instruction //addi// as an immediate operand beginning with the last position (//lastFixup//).+Such addresses must be loaded with the aid of an auxiliary (with //addi// and //addis//). After linking these addresses are known and must be corrected in the code. For this purpose a table called //fixups// is maintained. It contains all references to the objects, which were created by the class file reader and whose final addresses must be inserted into the code. In order to know at what position in the machine code array a certain correction has to be made, the next position is stored in the instruction //addi// as an immediate operand beginning with the last position (//lastFixup//).
  
 ===== Accessing the Hardware ===== ===== Accessing the Hardware =====
-Java does not allow direct access and manipulation of absolute memory locations. Nevertheless this is essential for embedded programming. We therefore include this possibility by the use a special Java class //US.java// (US stand for unsafe). Wenn methods of this class are used the code generator has to insert machine code directly. Already with the register allocation no registers have to be reserved for this instructions. //US.java// therefore serves as simple stubs. +Java does not allow direct access and manipulation of absolute memory locations. Nevertheless this is essential for embedded programming. We therefore include this possibility by using a special class //org.deepjava.unsafe.ppc.US.java// (US stand for unsafe). Wenn methods of this class are used the code generator has to insert machine code directly. The register allocator does not have to allocate registers for this instructions. //US.java// therefore serves as simple stubs. 
  
 ===== Low Level Classes ===== ===== Low Level Classes =====
Line 48: Line 48:
   * Delegation of interface methods: address of this method inserted into the type descriptor by the linker   * Delegation of interface methods: address of this method inserted into the type descriptor by the linker
   * Exception handling: call to this methods inserted by the code generator   * Exception handling: call to this methods inserted by the code generator
 +
 +==== Practical Implementation of Searching the Correct Interface Method ====
 +//imDelegIiMm// needs 3 auxiliary registers. At compile time we cannot reserve such auxiliary registers as these registers must always be the same. Therefore, we use parameter registers. They are volatile and can be freely used though this means, that interface methods can pass less parameters, which is generally true. If not true, the compiler will report.\\
 +R10 holds the necessary information for the delegate method. The first two bytes are the ID of the sought-after interface, tho last to bytes contain the method offset. Loading of R10 should happen after parameter copying as R10 might be used there. 
 +
 +
dev/crosscompiler/backend_ppc/code_generator.1450263816.txt.gz · Last modified: 2016/02/25 13:33 (external edit)