Description: <short summary of the patch>
 TODO: Put a short summary on the line above and replace this paragraph
 with a longer explanation of this change. Complete the meta-information
 with other relevant fields (see below for details). To make it easier, the
 information below has been extracted from the changelog. Adjust it or drop
 it.
 .
 pypy (7.0.0+dfsg-3.lnd.1) unstable; urgency=medium
 .
   * add loongarch64 support.
Author: Jianjun Han <hanjianjun@loongson.cn>

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: https://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: 2021-06-01

--- pypy-7.0.0+dfsg.orig/rpython/translator/c/src/stacklet/slp_platformselect.h
+++ pypy-7.0.0+dfsg/rpython/translator/c/src/stacklet/slp_platformselect.h
@@ -14,6 +14,8 @@
 #include "switch_ppc64_gcc.h" /* gcc on ppc64 */
 #elif defined(__GNUC__) && defined(__mips__) && defined(_ABI64)
 #include "switch_mips64_gcc.h" /* gcc on mips64 */
+#elif defined(__GNUC__) && defined(__loongarch__) && defined(_ABILP64)
+#include "switch_loongarch64_gcc.h" /* gcc on loongarch64 */
 #elif defined(__GNUC__) && defined(__s390x__)
 #include "switch_s390x_gcc.h"
 #else
--- /dev/null
+++ pypy-7.0.0+dfsg/rpython/translator/c/src/stacklet/switch_loongarch64_gcc.h
@@ -0,0 +1,63 @@
+static void *slp_switch(void *(*save_state)(void*, void*),
+                        void *(*restore_state)(void*, void*),
+                        void *extra)
+{
+  void *result;
+  __asm__ volatile (
+     "addi.d $sp, $sp, -0x50\n"
+     "st.d $s0, $sp, 0x0\n" /* push the registers specified as caller-save */
+     "st.d $s1, $sp, 0x8\n"
+     "st.d $s2, $sp, 0x10\n"
+     "st.d $s3, $sp, 0x18\n"
+     "st.d $s4, $sp, 0x20\n"
+     "st.d $s5, $sp, 0x28\n"
+     "st.d $s6, $sp, 0x30\n"
+     "st.d $s7, $sp, 0x38\n"
+     "st.d $fp, $sp, 0x40\n"
+     "st.d $ra, $sp, 0x48\n"
+
+     "move $s0, %[rstate]\n" /* save 'restore_state' for later */
+     "move $s1, %[extra]\n" /* save 'extra' for later */
+
+     "move $a1, %[extra]\n"/* arg 2: extra */
+     "move $a0, $sp\n" /* arg 1: current (old) stack pointer */
+                           
+     "move $t8, %[sstate]\n"
+     "jirl $ra, $t8, 0\n" /* call save_state() */
+
+     "beqz $v0, 0f\n" /* skip the rest if the return value is null */
+
+     "move $sp, $v0\n" /* change the stack pointer */
+
+     /* From now on, the stack pointer is modified, but the content of the
+        stack is not restored yet.  It contains only garbage here. */
+
+     "move $a1, $s1\n" /* arg 2: extra */
+     "move $a0, $v0\n" /* arg 1: current (new) stack pointer */
+     "move $t8, $s0\n"
+     "jirl $ra, $t8, 0\n" /* call restore_state() */
+
+     /* The stack's content is now restored. */
+
+     "0:\n"
+     "move %[result], $v0\n"
+     "ld.d $s0, $sp, 0x0\n"
+     "ld.d $s1, $sp, 0x8\n"
+     "ld.d $s2, $sp, 0x10\n"
+     "ld.d $s3, $sp, 0x18\n"
+     "ld.d $s4, $sp, 0x20\n"
+     "ld.d $s5, $sp, 0x28\n"
+     "ld.d $s6, $sp, 0x30\n"
+     "ld.d $s7, $sp, 0x38\n"
+     "ld.d $fp, $sp, 0x40\n"
+     "ld.d $ra, $sp, 0x48\n"
+     "addi.d $sp, $sp, 0x50\n"
+
+     : [result]"=&r"(result)
+     : [sstate]"r"(save_state),
+       [rstate]"r"(restore_state),
+       [extra]"r"(extra)
+     : "memory", "v0", "a0", "a1", "t8"
+     );
+  return result;
+}
