2007-04-06 Andreas Faerber <andreas.faerber@web.de>
[mono.git] / mono / mini / tramp-alpha.c
index e30eeebdf9a1088fe4236178da80d754c32970c1..2f2882422b6bcaa19570054230013cc71bcf99c7 100644 (file)
@@ -508,14 +508,102 @@ mono_arch_nullify_class_init_trampoline (guint8 *code, gssize *regs)
 
   ALPHA_DEBUG("mono_arch_nullify_class_init_trampoline");
 
+  // pcode[-2] ldq     t12,n(gp)
+  // pcode[-1] jsr     ra,(t12),0x20003efcb40
+  if ((pcode[-2] & 0xFFFF0000) == 0xa77d0000 &&
+       pcode[-1] == 0x6b5b4000)
+  {
+      // Put "unop" into call inst
+      pcode--;
+      alpha_nop(pcode);
+      alpha_nop(pcode);
+      alpha_nop(pcode);
+
+      mono_arch_flush_icache ((code-4), 3*4);
+  }
+  else
+      g_assert_not_reached ();
 }
 
+/*
+** This method is called after delegate method is compiled.
+** We need to patch call site to call compiled method directly
+** (not via trampoline stub)
+** Determine address to patch using fp reg
+** 
+*/
 
 void
 mono_arch_patch_delegate_trampoline (guint8 *code, guint8 *tramp,
                                     gssize *regs, guint8 *addr)
 {
+  unsigned int *pcode = (unsigned int *)code;
+  int reg;
+  short fp_disp, obj_disp;
+  unsigned long *pobj, obj;
+
   ALPHA_DEBUG("mono_arch_patch_delegate_trampoline");
+
+  // The call signature for now is
+  // -4 - ldq     v0,24(fp)
+  // -3 - ldq     v0,40(v0)
+  // -2 - mov     v0,t12
+  // -1 - jsr     ra,(t12),0x200041476e4
+  //  0 - ldah    gp,0(ra)
+  if (((pcode[-4] & 0xFC000000) == 0xA4000000) &&
+      ((pcode[-3] & 0xFC000000) == 0xA4000000) &&
+      ((pcode[-2] & 0xFC000FE0) == 0x44000400) &&
+      ((pcode[-1] & 0xFFFF0000) == 0x6B5B0000))
+    {
+      fp_disp = (pcode[-4] & 0xFFFF);
+      obj_disp = (pcode[-3] & 0xFFFF);
+
+      pobj = regs[15] + fp_disp;
+      obj = *pobj;
+      reg = 0;
+    }
+    // The non-optimized call signature for now is
+    // -5 - ldq     v0,24(fp)
+    // -4 - mov     v0,v0
+    // -3 - ldq     v0,40(v0)
+    // -2 - mov     v0,t12
+    // -1 - jsr     ra,(t12),0x200041476e4
+    //  0 - ldah    gp,0(ra)
+  else if (((pcode[-5] & 0xFC000000) == 0xA4000000) &&
+          ((pcode[-4] & 0xFC000FE0) == 0x44000400) &&
+          ((pcode[-3] & 0xFC000000) == 0xA4000000) &&
+          ((pcode[-2] & 0xFC000FE0) == 0x44000400) &&
+          ((pcode[-1] & 0xFFFF0000) == 0x6B5B0000))
+    {
+      fp_disp = (pcode[-5] & 0xFFFF);
+      obj_disp = (pcode[-3] & 0xFFFF);
+
+      pobj = regs[15] + fp_disp;
+      obj = *pobj;
+      reg = 0;
+    }
+      // Code with linears optimization
+      // -4 - mov     reg,v0
+      // -3 - ldq     v0,40(v0)
+      // -2 - mov     v0,t12
+      // -1 - jsr     ra,(t12)
+      //  0 - ldah    gp,0(ra)
+  else if (((pcode[-4] & 0xFC000FE0) == 0x44000400) &&
+          ((pcode[-3] & 0xFC000000) == 0xA4000000) &&
+          ((pcode[-2] & 0xFC000FE0) == 0x44000400) &&
+          ((pcode[-1] & 0xFFFF0000) == 0x6B5B0000))
+    {
+      fp_disp = (pcode[-4] >> AXP_REG2_SHIFT) & AXP_REG_MASK;
+      obj_disp = (pcode[-3] & 0xFFFF);
+
+      obj = regs[fp_disp];
+      //obj = *pobj;
+      reg = 0;
+    }
+  else
+    g_assert_not_reached ();
+
+  *((gpointer*)(obj + obj_disp)) = addr;
 }
 
 void
@@ -625,3 +713,25 @@ mono_arch_patch_plt_entry (guint8 *code, guint8 *addr)
         g_assert_not_reached ();
 }
 
+/*
+ * This method is only called when running in the Mono Debugger.
+ */
+gpointer
+mono_debugger_create_notification_function (void)
+{
+  guint8 *code;
+  unsigned int *buf;
+
+  code = mono_global_codeman_reserve (16);
+  buf = (unsigned int *)code;
+
+  *buf = 0;
+
+  alpha_call_pal(buf, 0x80);
+  alpha_ret(buf, alpha_ra, 1);
+  //x86_breakpoint (buf);
+  //x86_ret (buf);
+
+  return code;
+}
+