orc: preserve non volatile sse registers
authorMatej Knopp <matej.knopp@gmail.com>
Mon, 19 Jun 2017 02:00:31 +0000 (04:00 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Tue, 20 Jun 2017 06:17:20 +0000 (09:17 +0300)
required for MSVC
https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx

orc already marks these register in compiler->save_regs,
but the actual saving and restoring was not done

https://bugzilla.gnome.org/show_bug.cgi?id=783931

orc/orcprogram-sse.c

index 0f27b9a..97a1ec9 100644 (file)
@@ -764,6 +764,49 @@ orc_program_has_float (OrcCompiler *compiler)
 #define LABEL_STEP_DOWN(x) (8+(x))
 #define LABEL_STEP_UP(x) (13+(x))
 
+static void
+orc_compiler_sse_save_registers (OrcCompiler *compiler)
+{
+  int i;
+  int saved = 0;
+  for (i = 0; i < 16; ++i) {
+    if (compiler->save_regs[X86_XMM0 + i] == 1) {
+      ++saved;
+    }
+  }
+  if (saved > 0) {
+    orc_x86_emit_mov_imm_reg (compiler, 4, 16 * saved, compiler->gp_tmpreg);
+    orc_x86_emit_sub_reg_reg (compiler, compiler->is_64bit ? 8 : 4,
+        compiler->gp_tmpreg, X86_ESP);
+    saved = 0;
+    for (i = 0; i < 16; ++i) {
+      if (compiler->save_regs[X86_XMM0 + i] == 1) {
+        orc_x86_emit_mov_sse_memoffset (compiler, 16, X86_XMM0 + i,
+            saved * 16, X86_ESP, FALSE, FALSE);
+        ++saved;
+      }
+    }
+  }
+}
+
+static void
+orc_compiler_sse_restore_registers (OrcCompiler *compiler)
+{
+  int i;
+  int saved = 0;
+  for (i = 0; i < 16; ++i) {
+    if (compiler->save_regs[X86_XMM0 + i] == 1) {
+      orc_x86_emit_mov_memoffset_sse (compiler, 16, saved * 16, X86_ESP,
+          X86_XMM0 + i, FALSE);
+      ++saved;
+    }
+  }
+  if (saved > 0) {
+    orc_x86_emit_mov_imm_reg (compiler, 4, 16 * saved, compiler->gp_tmpreg);
+    orc_x86_emit_add_reg_reg (compiler, compiler->is_64bit ? 8 : 4,
+        compiler->gp_tmpreg, X86_ESP);
+  }
+}
 
 void
 orc_compiler_sse_assemble (OrcCompiler *compiler)
@@ -804,6 +847,8 @@ orc_compiler_sse_assemble (OrcCompiler *compiler)
 
   orc_x86_emit_prologue (compiler);
 
+  orc_compiler_sse_save_registers (compiler);
+
 #ifndef MMX
   if (orc_program_has_float (compiler)) {
     set_mxcsr = TRUE;
@@ -990,6 +1035,9 @@ orc_compiler_sse_assemble (OrcCompiler *compiler)
 #else
   orc_x86_emit_emms (compiler);
 #endif
+
+  orc_compiler_sse_restore_registers (compiler);
+
   orc_x86_emit_epilogue (compiler);
 
   orc_x86_calculate_offsets (compiler);