+/*
+ * Support for fast access to the thread-local lmf structure using the GS
+ * segment register on NPTL + kernel 2.6.x.
+ */
+
+static gboolean tls_offset_inited = FALSE;
+
+#ifdef HAVE_KW_THREAD
+static __thread gpointer mono_lmf_addr;
+#endif
+
+static gpointer
+mono_arch_get_lmf_addr (void)
+{
+#ifdef HAVE_KW_THREAD
+ return mono_lmf_addr;
+#else
+ g_assert_not_reached ();
+ return NULL;
+#endif
+}
+
+void
+mono_arch_setup_jit_tls_data (MonoJitTlsData *tls)
+{
+ if (!tls_offset_inited) {
+ guint8 *code;
+
+ tls_offset_inited = TRUE;
+
+ if (getenv ("MONO_NPTL")) {
+ /*
+ * Determine the offset of mono_lfm_addr inside the TLS structures
+ * by disassembling the function above.
+ */
+ code = (guint8*)&mono_arch_get_lmf_addr;
+
+ /* This is generated by gcc 3.3.2 */
+ if ((code [0] == 0x55) && (code [1] == 0x89) && (code [2] == 0xe5) &&
+ (code [3] == 0x65) && (code [4] == 0xa1) && (code [5] == 0x00) &&
+ (code [6] == 0x00) && (code [7] == 0x00) && (code [8] == 0x00) &&
+ (code [9] == 0x8b) && (code [10] == 0x80)) {
+ lmf_tls_offset = *(int*)&(code [11]);
+ }
+ }
+ }
+
+#ifdef HAVE_KW_THREAD
+ mono_lmf_addr = &tls->lmf;
+#endif
+}
+
+void
+mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, int this_reg, int this_type, int vt_reg)
+{
+
+ /* add the this argument */
+ if (this_reg != -1) {
+ MonoInst *this;
+ MONO_INST_NEW (cfg, this, OP_OUTARG);
+ this->type = this_type;
+ this->sreg1 = this_reg;
+ mono_bblock_add_inst (cfg->cbb, this);
+ }
+
+ if (vt_reg != -1) {
+ MonoInst *vtarg;
+ MONO_INST_NEW (cfg, vtarg, OP_OUTARG);
+ vtarg->type = STACK_MP;
+ vtarg->sreg1 = vt_reg;
+ mono_bblock_add_inst (cfg->cbb, vtarg);
+ }
+}
+
+
+gint
+mono_arch_get_opcode_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
+{
+ if (cmethod->klass == mono_defaults.math_class) {
+ if (strcmp (cmethod->name, "Sin") == 0)
+ return OP_SIN;
+ else if (strcmp (cmethod->name, "Cos") == 0)
+ return OP_COS;
+ else if (strcmp (cmethod->name, "Tan") == 0)
+ return OP_TAN;
+ else if (strcmp (cmethod->name, "Atan") == 0)
+ return OP_ATAN;
+ else if (strcmp (cmethod->name, "Sqrt") == 0)
+ return OP_SQRT;
+ else if (strcmp (cmethod->name, "Abs") == 0 && fsig->params [0]->type == MONO_TYPE_R8)
+ return OP_ABS;
+#if 0
+ /* OP_FREM is not IEEE compatible */
+ else if (strcmp (cmethod->name, "IEEERemainder") == 0)
+ return OP_FREM;
+#endif
+ else
+ return -1;
+ } else {
+ return -1;
+ }
+ return -1;
+}
+
+