+(define-vop (%compare-and-swap-symbol-value)
+ (:translate %compare-and-swap-symbol-value)
+ (:args (symbol :scs (descriptor-reg) :to (:result 1))
+ (old :scs (descriptor-reg any-reg) :target eax)
+ (new :scs (descriptor-reg any-reg)))
+ (:temporary (:sc descriptor-reg :offset eax-offset) eax)
+ #!+sb-thread
+ (:temporary (:sc descriptor-reg) tls)
+ (:results (result :scs (descriptor-reg any-reg)))
+ (:policy :fast-safe)
+ (:vop-var vop)
+ (:generator 15
+ ;; This code has to pathological cases: NO-TLS-VALUE-MARKER
+ ;; or UNBOUND-MARKER as NEW: in either case we would end up
+ ;; doing possible damage with CMPXCHG -- so don't do that!
+ (let ((unbound (generate-error-code vop 'unbound-symbol-error symbol))
+ (check (gen-label)))
+ (move eax old)
+ #!+sb-thread
+ (progn
+ (loadw tls symbol symbol-tls-index-slot other-pointer-lowtag)
+ ;; Thread-local area, no LOCK needed.
+ (inst fs-segment-prefix)
+ (inst cmpxchg (make-ea :dword :base tls) new)
+ (inst cmp eax no-tls-value-marker-widetag)
+ (inst jmp :ne check)
+ (move eax old)
+ (inst lock))
+ (inst cmpxchg (make-ea :dword :base symbol
+ :disp (- (* symbol-value-slot n-word-bytes)
+ other-pointer-lowtag))
+ new)
+ (emit-label check)
+ (move result eax)
+ (inst cmp result unbound-marker-widetag)
+ (inst jmp :e unbound))))
+