summaryrefslogtreecommitdiffstats
path: root/contrib/libstdc++/std/bastring.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libstdc++/std/bastring.h')
-rw-r--r--contrib/libstdc++/std/bastring.h34
1 files changed, 34 insertions, 0 deletions
diff --git a/contrib/libstdc++/std/bastring.h b/contrib/libstdc++/std/bastring.h
index f188628..7089126 100644
--- a/contrib/libstdc++/std/bastring.h
+++ b/contrib/libstdc++/std/bastring.h
@@ -73,7 +73,41 @@ private:
charT* data () { return reinterpret_cast<charT *>(this + 1); }
charT& operator[] (size_t s) { return data () [s]; }
charT* grab () { if (selfish) return clone (); ++ref; return data (); }
+#if defined __i486__ || defined __i586__ || defined __i686__
+ void release ()
+ {
+ size_t __val;
+ // This opcode exists as a .byte instead of as a mnemonic for the
+ // benefit of SCO OpenServer 5. The system assembler (which is
+ // essentially required on this target) can't assemble xaddl in
+ //COFF mode.
+ asm (".byte 0xf0, 0x0f, 0xc1, 0x02" // lock; xaddl %eax, (%edx)
+ : "=a" (__val)
+ : "0" (-1), "m" (ref), "d" (&ref)
+ : "memory");
+
+ if (__val == 1)
+ delete this;
+ }
+#elif defined __sparcv9__
+ void release ()
+ {
+ size_t __newval, __oldval = ref;
+ do
+ {
+ __newval = __oldval - 1;
+ __asm__ ("cas [%4], %2, %0"
+ : "=r" (__oldval), "=m" (ref)
+ : "r" (__oldval), "m" (ref), "r"(&(ref)), "0" (__newval));
+ }
+ while (__newval != __oldval);
+
+ if (__oldval == 0)
+ delete this;
+ }
+#else
void release () { if (--ref == 0) delete this; }
+#endif
inline static void * operator new (size_t, size_t);
inline static void operator delete (void *);
OpenPOWER on IntegriCloud