Hello Thiemo,

here is a (partially crude) patch which mixes your code with
my own MIPS host extension and code parts from a MIPS host
made by Johannes E. Schindelin 2 years ago.

Using this new code I was able to start a Linux kernel
using qemu-system-mipsel running in an emulated MALTA machine.

I could also start a simple i386 application (/bin/echo)
with qemu-i386 (until it failed with the usual libc / tls problems).

When I started to write MIPS host, I found it difficult to
get all locations which needed new code. To make it easier for
new ports, I changed sequences of #if ... #endif, #if ... #endif
into #if ... #elif ... #elif ... #else #error #endif.

Other changes include some smaller spelling corrections.

Most important was Johannes code for testandset and PARAMn.

The patch still includes your relocation code, but it is disabled
and uses my own code. I had no time to check or try the differences.

Fabrice, could you please update the status web page and add
"experimental MIPS host support" (otherwise still more people might
start to re-invent the code) :-).

Stefan

Thiemo Seufer schrieb:
> CVSROOT: /sources/qemu
> Module name: qemu
> Changes by: Thiemo Seufer <ths> 07/05/05 19:23:11
>
> Modified files:
> . : Makefile.target cpu-all.h cpu-exec.c
> dyngen-exec.h dyngen.c dyngen.h exec-all.h
>
> Log message:
> Some bits of Linux/MIPS host support, still segfaulty.

diff --rec -u -x .svn -x CVS head/cpu-all.h mipshost/cpu-all.h
--- head/cpu-all.h	2007-05-06 11:19:42.000000000 +0200
+++ mipshost/cpu-all.h	2007-05-07 21:24:08.000000000 +0200
@@ -1045,8 +1045,9 @@
 
 #else
 /* The host CPU doesn't have an easily accessible cycle counter.
-   Just return a monotonically increasing vlue.  This will be totally wrong,
+   Just return a monotonically increasing value.  This will be totally wrong,
    but hopefully better than nothing.  */
+#warning host without cycle counter
 static inline int64_t cpu_get_real_ticks (void)
 {
     static int64_t ticks = 0;
diff --rec -u -x .svn -x CVS head/dyngen.c mipshost/dyngen.c
--- head/dyngen.c	2007-05-06 11:19:44.000000000 +0200
+++ mipshost/dyngen.c	2007-05-07 20:37:11.000000000 +0200
@@ -1653,18 +1653,22 @@
 #define INSN_RETURN     0x03e00008
 #define INSN_NOP        0x00000000
 
-        uint8_t *p = p_end;
-
-        if (p < (p_start + 0x8)) {
+        uint8_t *p = (void *)(p_end - 8);
+        if (p == p_start) {
             error("empty code for %s", name);
-        } else {
-            uint32_t end_insn1, end_insn2;
-
-            p -= 0x8;
-            end_insn1 = get32((uint32_t *)(p + 0x0));
-            end_insn2 = get32((uint32_t *)(p + 0x4));
-            if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP)
-                error("jr ra not found at end of %s", name);
+        } else if (get32((uint32_t *)(p)) != INSN_RETURN) {
+            error("jr ra expected near the end of %s", name);
+        } else if (get32((uint32_t *)(p + 4)) != INSN_NOP) {
+            error("nop expected at the end of %s", name);
+        } else if ((get32((uint32_t *)(p_start)) >> 16) == 0x3c1c &&
+                  (get32((uint32_t *)(p_start + 4)) >> 16) == 0x279c &&
+                  get32((uint32_t *)(p_start + 8)) == 0x0399e021) {
+            /* Skip prologue
+               lui      gp,nn
+               addiu    gp,gp,nn
+               addu     gp,gp,t9 */
+            p_start += 12;
+            start_offset += 12;
         }
         copy_size = p - p_start;
     }
@@ -1727,9 +1731,7 @@
             if (offset >= start_offset &&
                 offset < start_offset + (p_end - p_start)) {
                 sym_name = get_rel_sym_name(rel);
-                if(!sym_name)
-                    continue;
-                if (*sym_name && 
+                if (sym_name && *sym_name && 
                     !strstart(sym_name, "__op_param", NULL) &&
                     !strstart(sym_name, "__op_jmp", NULL) &&
                     !strstart(sym_name, "__op_gen_label", NULL)) {
@@ -1740,9 +1742,8 @@
 				sym_name+1, sym_name);
 			continue;
 		    }
-#endif
-#if defined(__APPLE__)
-/* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */
+#elif defined(__APPLE__)
+/* set __attribute((unused)) on darwin because we want to avoid warning when we don't use the symbol */
                     fprintf(outfile, "extern char %s __attribute__((unused));\n", sym_name);
 #elif defined(HOST_IA64)
 			if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
@@ -1754,7 +1755,7 @@
 				fprintf(outfile, "    extern char %s;\n",
 					sym_name);
 #else
-                    fprintf(outfile, "extern char %s;\n", sym_name);
+                    fprintf(outfile, "    extern char %s;\n", sym_name);
 #endif
                 }
             }
@@ -1828,7 +1829,7 @@
             }
         }
 
-        /* load parameres in variables */
+        /* load parameters in variables */
         for(i = 0; i < nb_args; i++) {
             fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
         }
@@ -2512,6 +2513,78 @@
             }
 #elif defined(HOST_MIPS)
             {
+#ifdef CONFIG_FORMAT_ELF
+                char xname[256];
+                for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
+                    host_ulong r_offset = rel->r_offset;
+                    if (r_offset >= start_offset &&
+                        r_offset < start_offset + copy_size) {
+                        int reloc_offset = r_offset - start_offset;
+#if defined(WORDS_BIGENDIAN)
+                        int reloc_offset_lsb = reloc_offset + 2;
+#else
+                        int reloc_offset_lsb = reloc_offset;
+#endif
+                        int addend = get32((uint32_t *)(text + r_offset));
+                        int type = ELF32_R_TYPE(rel->r_info);
+                        sym_name = get_rel_sym_name(rel);
+                        get_reloc_expr(xname, sizeof(xname), sym_name);
+                        switch(type) {
+                        case R_MIPS_HI16:
+                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (uint16_t)((uint32_t)(%s) >> 16); // r_offset = %d // R_MIPS_HI16\n", 
+                                    reloc_offset_lsb, xname, r_offset);
+                            break;
+                        case R_MIPS_LO16:
+                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (uint16_t)(%s); // r_offset = %d // R_MIPS_LO16\n", 
+                                    reloc_offset_lsb, xname, r_offset);
+                            break;
+                        case R_MIPS_GOT16:
+                            /* No need to relocate. */
+                            fprintf(outfile, "    (void)%s; // reloc_offset = %d, r_offset = %d // R_MIPS_GOT16\n", 
+                                    xname, reloc_offset, r_offset);
+                            break;
+                        case R_MIPS_PC16:
+                            fprintf(outfile, "    /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
+                                    rel->r_offset, sym_name);
+                            fprintf(outfile,
+                                    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
+                                    "(0x%x & ~0xffff) "
+                                    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
+                                    "   & 0xffff);\n",
+                                    reloc_offset, addend, addend, name, reloc_offset);
+                            break;
+                        case R_MIPS_CALL16:
+                            /* No need to relocate. */
+                            fprintf(outfile, "    (void)%s; // reloc_offset = %d, r_offset = %d // R_MIPS_CALL16\n", 
+                                    xname, reloc_offset, r_offset);
+                            break;
+                        case R_MIPS_GOTHI16:
+                            fprintf(outfile, "#error unsupported mips relocation R_MIPS_GOTHI16\n");
+                            break;
+                        case R_MIPS_GOTLO16:
+                            fprintf(outfile, "#error unsupported mips relocation R_MIPS_GOTLO16\n");
+                            break;
+                        case R_MIPS_CALLHI16:
+                            fprintf(outfile, "#warning untested mips relocation R_MIPS_CALLHI16\n");
+                            fprintf(outfile, "    (void)%s; // reloc_offset = %d, r_offset = %d // R_MIPS_CALLHI16\n", 
+                                    xname, reloc_offset, r_offset);
+                            break;
+                        case R_MIPS_CALLLO16:
+                            fprintf(outfile, "#warning untested mips relocation R_MIPS_CALLLO16\n");
+                            fprintf(outfile, "    (void)%s; // reloc_offset = %d, r_offset = %d // R_MIPS_CALLLO16\n", 
+                                    xname, reloc_offset, r_offset);
+                            break;
+                        default:
+                            error("unsupported mips relocation (%d) for %s in %s\n", type, sym_name, name);
+                        }
+                    }
+                }
+#else
+#error unsupport object format
+#endif
+            }
+#elif defined(HOST_MIPS)
+            {
                 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
 		    if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
                         char name[256];
@@ -2548,16 +2621,6 @@
 				    " | (%s & 0xffff);\n",
                                     reloc_offset, reloc_offset, name);
 			    break;
-			case R_MIPS_PC16:
-                            fprintf(outfile, "    /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
-				    rel->r_offset, sym_name);
-                            fprintf(outfile,
-				    "    *(uint32_t *)(gen_code_ptr + 0x%x) = "
-				    "(0x%x & ~0xffff) "
-				    "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
-				    "   & 0xffff);\n",
-                                    reloc_offset, addend, addend, name, reloc_offset);
-			    break;
 			case R_MIPS_GOT16:
 			case R_MIPS_CALL16:
                             fprintf(outfile, "    /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
diff --rec -u -x .svn -x CVS head/dyngen-exec.h mipshost/dyngen-exec.h
--- head/dyngen-exec.h	2007-05-06 11:19:42.000000000 +0200
+++ mipshost/dyngen-exec.h	2007-05-07 20:02:40.000000000 +0200
@@ -89,21 +89,19 @@
 #undef NULL
 #define NULL 0
 
-#ifdef __i386__
+#if defined(__i386__)
 #define AREG0 "ebp"
 #define AREG1 "ebx"
 #define AREG2 "esi"
 #define AREG3 "edi"
-#endif
-#ifdef __x86_64__
+#elif defined(__x86_64__)
 #define AREG0 "r14"
 #define AREG1 "r15"
 #define AREG2 "r12"
 #define AREG3 "r13"
 //#define AREG4 "rbp"
 //#define AREG5 "rbx"
-#endif
-#ifdef __powerpc__
+#elif defined(__powerpc__)
 #define AREG0 "r27"
 #define AREG1 "r24"
 #define AREG2 "r25"
@@ -121,14 +119,12 @@
 #endif
 #define USE_INT_TO_FLOAT_HELPERS
 #define BUGGY_GCC_DIV64
-#endif
-#ifdef __arm__
+#elif defined(__arm__)
 #define AREG0 "r7"
 #define AREG1 "r4"
 #define AREG2 "r5"
 #define AREG3 "r6"
-#endif
-#ifdef __mips__
+#elif defined(__mips__)
 #define AREG0 "fp"
 #define AREG1 "s0"
 #define AREG2 "s1"
@@ -138,8 +134,7 @@
 #define AREG6 "s5"
 #define AREG7 "s6"
 #define AREG8 "s7"
-#endif
-#ifdef __sparc__
+#elif defined(__sparc__)
 #ifdef HOST_SOLARIS
 #define AREG0 "g2"
 #define AREG1 "g3"
@@ -168,14 +163,12 @@
 #endif
 #endif
 #define USE_FP_CONVERT
-#endif
-#ifdef __s390__
+#elif defined(__s390__)
 #define AREG0 "r10"
 #define AREG1 "r7"
 #define AREG2 "r8"
 #define AREG3 "r9"
-#endif
-#ifdef __alpha__
+#elif defined(__alpha__)
 /* Note $15 is the frame pointer, so anything in op-i386.c that would
    require a frame pointer, like alloca, would probably loose.  */
 #define AREG0 "$15"
@@ -185,19 +178,19 @@
 #define AREG4 "$12"
 #define AREG5 "$13"
 #define AREG6 "$14"
-#endif
-#ifdef __mc68000
+#elif defined(__mc68000)
 #define AREG0 "%a5"
 #define AREG1 "%a4"
 #define AREG2 "%d7"
 #define AREG3 "%d6"
 #define AREG4 "%d5"
-#endif
-#ifdef __ia64__
+#elif defined(__ia64__)
 #define AREG0 "r7"
 #define AREG1 "r4"
 #define AREG2 "r5"
 #define AREG3 "r6"
+#else
+#error unsupported CPU
 #endif
 
 /* force GCC to generate only one epilog at the end of the function */
@@ -231,6 +224,16 @@
 #define PARAM1 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param1)); _r; })
 #define PARAM2 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param2)); _r; })
 #define PARAM3 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param3)); _r; })
+#elif defined(__mips__)
+/* On MIPS, parameters to a c expression are passed via the global pointer.
+ * We don't want that. */
+#define PARAMN(index) ({ register int _r; \
+                asm("lui %0,%%hi(__op_param" #index ")\n\t" \
+                        "ori %0,%0,%%lo(__op_param" #index ")" \
+                        : "=r"(_r)); _r; })
+#define PARAM1 PARAMN(1)
+#define PARAM2 PARAMN(2)
+#define PARAM3 PARAMN(3)
 #else
 #if defined(__APPLE__)
 static int __op_param1, __op_param2, __op_param3;
@@ -250,44 +253,41 @@
 #define ASM_NAME(x) #x
 #endif
 
-#ifdef __i386__
+#if defined(__i386__)
 #define EXIT_TB() asm volatile ("ret")
 #define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __x86_64__
+#elif defined(__x86_64__)
 #define EXIT_TB() asm volatile ("ret")
 #define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __powerpc__
+#elif defined(__powerpc__)
 #define EXIT_TB() asm volatile ("blr")
 #define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __s390__
+#elif defined(__s390__)
 #define EXIT_TB() asm volatile ("br %r14")
 #define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __alpha__
+#elif defined(__alpha__)
 #define EXIT_TB() asm volatile ("ret")
-#endif
-#ifdef __ia64__
+#elif defined(__ia64__)
 #define EXIT_TB() asm volatile ("br.ret.sptk.many b0;;")
 #define GOTO_LABEL_PARAM(n) asm volatile ("br.sptk.many " \
 					  ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __sparc__
+#elif defined(__sparc__)
 #define EXIT_TB() asm volatile ("jmpl %i0 + 8, %g0; nop")
 #define GOTO_LABEL_PARAM(n) asm volatile ("ba " ASM_NAME(__op_gen_label) #n ";nop")
-#endif
-#ifdef __arm__
+#elif defined(__arm__)
 #define EXIT_TB() asm volatile ("b exec_loop")
 #define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __mc68000
+#elif defined(__mc68000)
 #define EXIT_TB() asm volatile ("rts")
-#endif
-#ifdef __mips__
-#define EXIT_TB() asm volatile ("jr $ra")
-#define GOTO_LABEL_PARAM(n) asm volatile (".set noat; la $1, " ASM_NAME(__op_gen_label) #n "; jr $1; .set at")
+#elif defined(__mips__)
+#define EXIT_TB() asm volatile ("jr $31; nop")
+#define GOTO_LABEL_PARAM(n) asm volatile (\
+    "lui $2,%hi(" ASM_NAME(__op_gen_label) #n ")\n\t" \
+    "ori $2,$2,%lo(" ASM_NAME(__op_gen_label)#n ")\n\t" \
+    "jr $2\n\t" \
+    "nop")
+#else
+#error unsupported CPU
 #endif
 
 #endif /* !defined(__DYNGEN_EXEC_H__) */
diff --rec -u -x .svn -x CVS head/dyngen.h mipshost/dyngen.h
--- head/dyngen.h	2007-05-06 11:19:44.000000000 +0200
+++ mipshost/dyngen.h	2007-05-07 20:19:20.000000000 +0200
@@ -19,7 +19,7 @@
  */
 
 int __op_param1, __op_param2, __op_param3;
-#if defined(__sparc__) || defined(__arm__)
+#if defined(__sparc__) || defined(__arm__) || defined(__mips__)
   void __op_gen_label1(){}
   void __op_gen_label2(){}
   void __op_gen_label3(){}
@@ -28,25 +28,26 @@
 #endif
 int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
 
-#ifdef __i386__
+#if defined(__i386__)
+
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
 }
-#endif
 
-#ifdef __x86_64__
+#elif defined(__x86_64__)
+
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
 }
-#endif
 
-#ifdef __s390__
+#elif defined(__s390__)
+
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
 }
-#endif
 
-#ifdef __ia64__
+#elif defined(__ia64__)
+
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
     while (start < stop) {
@@ -55,9 +56,8 @@
     }
     asm volatile (";;sync.i;;srlz.i;;");
 }
-#endif
 
-#ifdef __powerpc__
+#elif defined(__powerpc__)
 
 #define MIN_CACHE_LINE_SIZE 8 /* conservative value */
 
@@ -78,16 +78,15 @@
     asm volatile ("sync" : : : "memory");
     asm volatile ("isync" : : : "memory");
 }
-#endif
 
-#ifdef __alpha__
+#elif defined(__alpha__)
+
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
     asm ("imb");
 }
-#endif
 
-#ifdef __sparc__
+#elif defined(__sparc__)
 
 static void inline flush_icache_range(unsigned long start, unsigned long stop)
 {
@@ -100,9 +99,8 @@
 		__asm__ __volatile__("flush\t%0" : : "r" (p));
 }
 
-#endif
+#elif defined(__arm__)
 
-#ifdef __arm__
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
     register unsigned long _beg __asm ("a1") = start;
@@ -110,17 +108,16 @@
     register unsigned long _flg __asm ("a3") = 0;
     __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
 }
-#endif
 
-#ifdef __mc68000
+#elif defined(__mc68000)
+
 #include <asm/cachectl.h>
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
     cacheflush(start,FLUSH_SCOPE_LINE,FLUSH_CACHE_BOTH,stop-start+16);
 }
-#endif
 
-#ifdef __alpha__
+#elif defined(__alpha__)
 
 register int gp asm("$29");
 
@@ -141,9 +138,7 @@
     *dest |= (offset >> 2) & ((1 << 21) - 1);
 }
 
-#endif /* __alpha__ */
-
-#ifdef __arm__
+#elif defined(__arm__)
 
 #define ARM_LDR_TABLE_SIZE 1024
 
@@ -244,10 +239,7 @@
     return gen_code_ptr;
 }
 
-#endif /* __arm__ */
-
-#ifdef __ia64
-
+#elif defined(__ia64)
 
 /* Patch instruction with "val" where "mask" has 1 bits. */
 static inline void ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val)
@@ -462,12 +454,16 @@
     *gen_code_pp = gen_code_ptr;
 }
 
-#endif
+#elif defined(__mips__)
 
-#ifdef __mips__
 #include <sys/cachectl.h>
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
     _flush_cache ((void *)start, stop - start, BCACHE);
 }
+
+#else
+
+#error unsupported CPU
+
 #endif
diff --rec -u -x .svn -x CVS head/exec-all.h mipshost/exec-all.h
--- head/exec-all.h	2007-05-06 11:19:44.000000000 +0200
+++ mipshost/exec-all.h	2007-05-07 20:39:41.000000000 +0200
@@ -357,7 +357,7 @@
 extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
 extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
 
-#ifdef __powerpc__
+#if defined(__powerpc__)
 static inline int testandset (int *p)
 {
     int ret;
@@ -373,9 +373,7 @@
                           : "cr0", "memory");
     return ret;
 }
-#endif
-
-#ifdef __i386__
+#elif defined(__i386__)
 static inline int testandset (int *p)
 {
     long int readval = 0;
@@ -386,9 +384,7 @@
                           : "cc");
     return readval;
 }
-#endif
-
-#ifdef __x86_64__
+#elif defined(__x86_64__)
 static inline int testandset (int *p)
 {
     long int readval = 0;
@@ -399,9 +395,7 @@
                           : "cc");
     return readval;
 }
-#endif
-
-#ifdef __s390__
+#elif defined(__s390__)
 static inline int testandset (int *p)
 {
     int ret;
@@ -413,9 +407,7 @@
 			  : "cc", "memory" );
     return ret;
 }
-#endif
-
-#ifdef __alpha__
+#elif defined(__alpha__)
 static inline int testandset (int *p)
 {
     int ret;
@@ -432,9 +424,7 @@
 			  : "m" (*p));
     return ret;
 }
-#endif
-
-#ifdef __sparc__
+#elif defined(__sparc__)
 static inline int testandset (int *p)
 {
 	int ret;
@@ -446,9 +436,7 @@
 
 	return (ret ? 1 : 0);
 }
-#endif
-
-#ifdef __arm__
+#elif defined(__arm__)
 static inline int testandset (int *spinlock)
 {
     register unsigned int ret;
@@ -458,9 +446,7 @@
     
     return ret;
 }
-#endif
-
-#ifdef __mc68000
+#elif defined(__mc68000)
 static inline int testandset (int *p)
 {
     char ret;
@@ -470,37 +456,32 @@
                          : "cc","memory");
     return ret;
 }
-#endif
-
-#ifdef __ia64
+#elif defined(__ia64)
 #include <ia64intrin.h>
 
 static inline int testandset (int *p)
 {
     return __sync_lock_test_and_set (p, 1);
 }
-#endif
-
-#ifdef __mips__
+#elif defined(__mips__)
 static inline int testandset (int *p)
 {
     int ret;
-
-    __asm__ __volatile__ (
-	"	.set push		\n"
-	"	.set noat		\n"
-	"	.set mips2		\n"
-	"1:	li	$1, 1		\n"
-	"	ll	%0, %1		\n"
-	"	sc	$1, %1		\n"
-	"	bnez	$1, 1b		\n"
-	"	.set pop		"
-	: "=r" (ret), "+R" (*p)
-	:
-	: "memory");
-
+    __asm__ __volatile__(
+        ".set mips2\n"
+        "ll %0,%1\n"
+        ".set noreorder\n"
+        "bnez %0,1f\n"
+        "li %0,0\n"
+        "li %0,1\n"
+        "sc %0,%1\n"
+        "1:\n"
+        : "=r" (ret), "=m" (*p)
+    );
     return ret;
 }
+#else
+#error unimplemented CPU
 #endif
 
 typedef int spinlock_t;

Reply via email to