From 5805b07218aef3c1049b5db9d89841d383ee917d Mon Sep 17 00:00:00 2001
From: grischka <grischka>
Date: Mon, 3 Oct 2016 12:27:50 +0200
Subject: [PATCH] Alternative fix for "Incorrect function call code on ARMv6"

"make test" crashes without that "save_regs()".

This partially reverts
commit 49d3118621a68f6583228f123efd16f0f803d908.

Found another solution:  In a 2nd pass Just look if
any of the argument registers has been saved again,
and restore if so.
---
 arm-gen.c | 11 +++++++++++
 tccgen.c  |  5 +++++
 2 files changed, 16 insertions(+)

diff --git a/arm-gen.c b/arm-gen.c
index 218ace1f..cca9da5d 100644
--- a/arm-gen.c
+++ b/arm-gen.c
@@ -1047,6 +1047,7 @@ static int copy_params(int nb_args, struct plan *plan, int todo)
 {
   int size, align, r, i, nb_extra_sval = 0;
   struct param_plan *pplan;
+  int pass = 0;
 
    /* Several constraints require parameters to be copied in a specific order:
       - structures are copied to the stack before being loaded in a reg;
@@ -1063,8 +1064,14 @@ static int copy_params(int nb_args, struct plan *plan, int todo)
       - parameters assigned to VFP regs be copied before structures assigned to
         VFP regs as the copy might use an even numbered VFP reg that already
         holds part of a structure. */
+again:
   for(i = 0; i < NB_CLASSES; i++) {
     for(pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) {
+
+      if (pass
+          && (i != CORE_CLASS || pplan->sval->r < VT_CONST))
+        continue;
+
       vpushv(pplan->sval);
       pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */
       switch(i) {
@@ -1170,6 +1177,10 @@ static int copy_params(int nb_args, struct plan *plan, int todo)
     }
   }
 
+  /* second pass to restore registers that were saved on stack by accident */
+  if (++pass < 2)
+    goto again;
+
   /* Manually free remaining registers since next parameters are loaded
    * manually, without the help of gv(int). */
   save_regs(nb_args);
diff --git a/tccgen.c b/tccgen.c
index d55ee391..56be31bf 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -861,6 +861,11 @@ ST_FUNC int gv(int rc)
 #endif
                 if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
                            (vtop->r & VT_LVAL)) {
+                    /* We do not want to modifier the long long
+                       pointer here, so the safest (and less
+                       efficient) is to save all the other registers
+                       in the stack. XXX: totally inefficient. */
+                    save_regs(1);
                     /* load from memory */
                     vtop->type.t = load_type;
                     load(r, vtop);