deep

a Cross Development Platform for Java

User Tools

Site Tools


dev:crosscompiler:backend_arm:code_generator

Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
dev:crosscompiler:backend_arm:code_generator [2019/07/27 16:32]
ursgraf [Code Generator for ARM]
dev:crosscompiler:backend_arm:code_generator [2019/11/17 19:54] (current)
ursgraf [Exception Stackframe]
Line 1: Line 1:
 ====== Code Generator for ARM ====== ====== Code Generator for ARM ======
-Everything which is not fully implemented is listed below 
-^topic^remarks^ 
-|throw| do together with exceptions | 
-|new| tests for three dimensional arrays fail| 
-|exceptions| | 
-|US.HALT|what to do here?| 
- 
 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.
  
Line 14: Line 7:
  
 Explanation:​ Explanation:​
-LR is saved onto the stack together with the necessary nonvolatile GPRs. Even if method is a leaf method LR must be saved onto the stack because LR serves as a scratch register within a method. Considering the GPR's and EXTRs, all nonvolatile register, which are used within this method, must be saved on the stack. Nonvolatiles in EXTR registers occupy either 8 bytes (EXTRD) or bytes (EXTRS). \\+LR is saved onto the stack together with the necessary nonvolatile GPRs. Even if method is a leaf method LR must be saved onto the stack because LR serves as a scratch register within a method. Considering the GPR's and EXTRs, all nonvolatile register, which are used within this method, must be saved on the stack. Nonvolatiles in EXTR registers occupy either 8 bytes (EXTRD) or bytes (EXTRS). \\
 Important: volatile EXTR's must be saved as well if ''​US.ENABLE_FLOATS()''​ is called in this method (see [[.:​exceptions|Exceptions]]). Important: volatile EXTR'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 and locals must be assigned a slot on the stack. When calling interface methods some temporary space on the stack might be necessary (see below). ​  +The field //local variables// is only used if the number of registers does not suffice and locals must be assigned a slot on the stack. ​Variables of type //long// or //double// occupy two slots. \\ 
-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. \\ +When calling interface methods some temporary space on the stack might be necessary (see below). ​\\  
 +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. Each floating point parameter on the stack occupies 8 bytes (EXTRS or EXTRD).\\ 
 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. 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. The back chain pointer is used for the debugger, for exceptions and for the garbage collection.
 \\ \\
 ===== Exception Stackframe ===== ===== Exception Stackframe =====
-In case of an exception ​the registers ​LR, CTR, CR, XER, SRR0 and SRR1 must be additionally ​saved. ​Then follow all GPRs. In factit would be sufficient to store all the volatile GPR's and the nonvolatile ​GPR'​s ​which are used within ​this method. But //stmw// and //lmw// can be applied very efficiently but allow for storing a whole row only.\\  +In case of an exception ​all volatile GPRs together with LR must be saved. ​Further, the nonvolatile ​GPRs which are used in this method ​must be saved as well. \\  
-FPR's need no saving, as they are normally ​not allowed to be used in exceptions (FP bit in MSR = 0). Here again, if ''​US.ENABLE_FLOATS()'' ​is called in this method, the FPR's must be saved as well.+EXTR's need no saving, as they are not allowed to be used in exceptions. If an exception method calls a method where EXTR are used (e.g. in an interrupt handler or in a decrementer subclassyou have to use ''​US.ENABLE_FLOATS()'' ​to store the them. 
 + 
 +[{{ :​dev:​crosscompiler:​backend_arm:​exceptionstackframearm.png?​350&​direct | //Stack frame for exception ​method//}}] 
 + 
 +For efficiency, the exception stack frame does not contain space for locals. Hence, you are not allowed to use so many locals that this becomes necessary. This will be checked for when compiling exception methods. Storage for interface methods as well as the area for parameter passing are not necessary ​as well.
  
-[{{ .:​exceptionstackframe.png?​250&​direct | //Stack frame for exception method//}}] 
  
-Optimization:​ The PPC architecture has lots of FPR's. One could use half of them in normal methods and the other half in exception methods. For such a case all normal methods which could be called from within exception methods must be translated a second time with the second set. The compiler would have to find out how to handle each method.+Optimization:​ The ARM architecture has lots of EXTR's. One could use half of them in normal methods and the other half in exception methods. For such a case all normal methods which could be called from within exception methods must be translated a second time with the second set. The compiler would have to find out how to handle each method.
  
 ===== Method Call ===== ===== Method Call =====
  
 ==== Parameter Passing ==== ==== Parameter Passing ====
-All parameters must be copied in the appropriate registers, see [[.:​register_allocation|Register Allocation]]. During this it might be necessary that two or more registers must be swapped in a cycle. For this purpose two arrays //destGPR// and //destFPR// are determined. They show which source register goes into which destination register, if the register holds a parameter. If a cycle is found it will be solved through the aid of R0 or FR0, respectively.+All parameters must be copied in the appropriate registers, see [[.:​register_allocation|Register Allocation]]. During this it might be necessary that two or more registers must be swapped in a cycle. For this purpose two arrays //destGPR// and //destFPR// are determined. They show which source register goes into which destination register, if the register holds a parameter.
  
 ==== Return Value ==== ==== Return Value ====
Line 42: Line 39:
   * 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 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//​).+Such addresses must be loaded with the aid of an auxiliary ​registers. 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 //movw// as an immediate operand beginning with the last position (//​lastFixup//​).
  
 ===== Accessing the Hardware ===== ===== Accessing the Hardware =====
dev/crosscompiler/backend_arm/code_generator.1564237956.txt.gz · Last modified: 2019/07/27 16:32 by ursgraf