- if(!code) {
- /* Now we'll create in 'buf' the S/390 trampoline code. This
- is the trampoline code common to all methods */
-
- code = buf = g_malloc(512);
-
- /*-----------------------------------------------------------
- STEP 0: First create a non-standard function prologue with a
- stack size big enough to save our registers.
- -----------------------------------------------------------*/
-
- s390_stm (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
- s390_lr (buf, s390_r11, s390_r15);
- s390_ahi (buf, STK_BASE, -CREATE_STACK_SIZE);
- s390_st (buf, s390_r11, 0, STK_BASE, 0);
- s390_stm (buf, s390_r2, s390_r5, STK_BASE, CREATE_GR_OFFSET);
-
- /* Save the FP registers */
- offset = CREATE_FP_OFFSET;
- for (i = s390_f0; i <= s390_f15; ++i) {
- s390_std (buf, i, 0, STK_BASE, offset);
- offset += 8;
- }
-
- /*----------------------------------------------------------
- STEP 1: call 'mono_get_lmf_addr()' to get the address of our
- LMF. We'll need to restore it after the call to
- 's390_magic_trampoline' and before the call to the native
- method.
- ----------------------------------------------------------*/
-
- s390_basr (buf, s390_r13, 0);
- s390_j (buf, 4);
- s390_word (buf, mono_get_lmf_addr);
- s390_l (buf, s390_r1, 0, s390_r13, 4);
- s390_basr (buf, s390_r14, s390_r1);
-
- /* XXX Update LMF !!! */
-
- /*----------------------------------------------------------
- STEP 2: call 's390_magic_trampoline()', who will compile the
- code and fix the method vtable entry for us
- ----------------------------------------------------------*/
-
- /* Set arguments */
-
- /* Arg 1: MonoMethod *method. It was put in r11 by the
- method-specific trampoline code, and then saved before the call
- to mono_get_lmf_addr()'. Restore r13, by the way :-) */
- s390_l (buf, s390_r2, 0, s390_r11, METHOD_SAVE_OFFSET);
-
- /* Arg 2: code (next address to the instruction that called us) */
- if (tramp_type == MONO_TRAMPOLINE_JUMP) {
- s390_lhi (buf, s390_r3, 0);
- } else {
- s390_l (buf, s390_r3, 0, s390_r11, S390_RET_ADDR_OFFSET);
- }
-
- /* Arg 3: stack pointer */
- s390_lr (buf, s390_r4, STK_BASE);
-
- /* Calculate call address and call
- 's390_magic_trampoline'. Return value will be in r2 */
- s390_basr (buf, s390_r13, 0);
- s390_j (buf, 4);
- if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
- s390_word (buf, s390_class_init_trampoline);
- } else {
- s390_word (buf, s390_magic_trampoline);
- }
- s390_l (buf, s390_r1, 0, s390_r13, 4);
- s390_basr (buf, s390_r14, s390_r1);
-
- /* OK, code address is now on r2. Move it to r1, so that we
- can restore r2 and use it from r1 later */
- s390_lr (buf, s390_r1, s390_r2);
-
-
- /*----------------------------------------------------------
- STEP 3: Restore the LMF
- ----------------------------------------------------------*/
-
- /* XXX Do it !!! */
-
- /*----------------------------------------------------------
- STEP 4: call the compiled method
- ----------------------------------------------------------*/
-
- /* Restore registers */
-
- s390_lm (buf, s390_r2, s390_r5, STK_BASE, CREATE_GR_OFFSET);
-
- /* Restore the FP registers */
- offset = CREATE_FP_OFFSET;
- for (i = s390_f0; i <= s390_f15; ++i) {
- s390_ld (buf, i, 0, STK_BASE, offset);
- offset += 8;
- }
-
- /* Restore stack pointer and jump to the code -
- R14 contains the return address to our caller */
- s390_lr (buf, STK_BASE, s390_r11);
- s390_lm (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
- s390_br (buf, s390_r1);
-
- /* Flush instruction cache, since we've generated code */
- mono_arch_flush_icache (code, buf - code);
-
- /* Sanity check */
- g_assert ((buf - code) <= 512);
- }