1.0.20.8: ATOMIC-INCF implementation
[sbcl.git] / src / compiler / x86 / cell.lisp
index 241d434..753838a 100644 (file)
 ;;;; raw instance slot accessors
 
 (defun make-ea-for-raw-slot (object index instance-length n-words)
-  (sc-case index
-    (any-reg (make-ea :dword
-                      :base object
-                      :index instance-length
-                      :disp (- (* (- instance-slots-offset n-words)
-                                  n-word-bytes)
-                               instance-pointer-lowtag)))
-    (immediate (make-ea :dword :base object
+  (if (integerp instance-length)
+      ;; For RAW-INSTANCE-INIT/* VOPs, which know the exact instance length
+      ;; at compile time.
+      (make-ea :dword
+               :base object
+               :disp (- (* (- instance-length instance-slots-offset index (1- n-words))
+                           n-word-bytes)
+                        instance-pointer-lowtag))
+      (flet ((make-ea-using-value (value)
+               (make-ea :dword :base object
                         :index instance-length
                         :scale 4
                         :disp (- (* (- instance-slots-offset n-words)
                                     n-word-bytes)
                                  instance-pointer-lowtag
-                                 (fixnumize (tn-value index)))))))
+                                 (* value n-word-bytes)))))
+        (if (typep index 'tn)
+            (sc-case index
+              (any-reg (make-ea :dword
+                                :base object
+                                :index instance-length
+                                :disp (- (* (- instance-slots-offset n-words)
+                                            n-word-bytes)
+                                         instance-pointer-lowtag)))
+              (immediate (make-ea-using-value (tn-value index))))
+            (make-ea-using-value index)))))
 
 (define-vop (raw-instance-ref/word)
   (:translate %raw-instance-ref/word)
     (inst mov (make-ea-for-raw-slot object index tmp 1) value)
     (move result value)))
 
+(define-vop (raw-instance-init/word)
+  (:args (object :scs (descriptor-reg))
+         (value :scs (unsigned-reg)))
+  (:arg-types * unsigned-num)
+  (:info instance-length index)
+  (:generator 5
+    (inst mov (make-ea-for-raw-slot object index instance-length 1) value)))
+
+(define-vop (raw-instance-atomic-incf/word)
+  (:translate %raw-instance-atomic-incf/word)
+  (:policy :fast-safe)
+  (:args (object :scs (descriptor-reg))
+         (index :scs (any-reg immediate))
+         (diff :scs (signed-reg) :target result))
+  (:arg-types * tagged-num signed-num)
+  (:temporary (:sc unsigned-reg) tmp)
+  (:results (result :scs (unsigned-reg)))
+  (:result-types unsigned-num)
+  (:generator 5
+    (loadw tmp object 0 instance-pointer-lowtag)
+    (inst shr tmp n-widetag-bits)
+    (when (sc-is index any-reg)
+      (inst shl tmp 2)
+      (inst sub tmp index))
+    #!+sb-thread
+    (inst lock)
+    (inst xadd (make-ea-for-raw-slot object index tmp 1) diff)
+    (move result diff)))
+
 (define-vop (raw-instance-ref/single)
   (:translate %raw-instance-ref/single)
   (:policy :fast-safe)
           (inst fst result))
         (inst fxch value)))))
 
+(define-vop (raw-instance-init/single)
+  (:args (object :scs (descriptor-reg))
+         (value :scs (single-reg)))
+  (:arg-types * single-float)
+  (:info instance-length index)
+  (:generator 5
+    (with-tn@fp-top (value)
+      (inst fst (make-ea-for-raw-slot object index instance-length 1)))))
+
 (define-vop (raw-instance-ref/double)
   (:translate %raw-instance-ref/double)
   (:policy :fast-safe)
           (inst fstd result))
         (inst fxch value)))))
 
+(define-vop (raw-instance-init/double)
+  (:args (object :scs (descriptor-reg))
+         (value :scs (double-reg)))
+  (:arg-types * double-float)
+  (:info instance-length index)
+  (:generator 5
+    (with-tn@fp-top (value)
+      (inst fstd (make-ea-for-raw-slot object index instance-length 2)))))
+
 (define-vop (raw-instance-ref/complex-single)
   (:translate %raw-instance-ref/complex-single)
   (:policy :fast-safe)
         (inst fst result-imag))
       (inst fxch value-imag))))
 
+(define-vop (raw-instance-init/complex-single)
+  (:args (object :scs (descriptor-reg))
+         (value :scs (complex-single-reg)))
+  (:arg-types * complex-single-float)
+  (:info instance-length index)
+  (:generator 5
+    (let ((value-real (complex-single-reg-real-tn value)))
+      (with-tn@fp-top (value-real)
+        (inst fst (make-ea-for-raw-slot object index instance-length 2))))
+    (let ((value-imag (complex-single-reg-imag-tn value)))
+      (with-tn@fp-top (value-imag)
+        (inst fst (make-ea-for-raw-slot object index instance-length 1))))))
+
 (define-vop (raw-instance-ref/complex-double)
   (:translate %raw-instance-ref/complex-double)
   (:policy :fast-safe)
       (unless (location= value-imag result-imag)
         (inst fstd result-imag))
       (inst fxch value-imag))))
+
+(define-vop (raw-instance-init/complex-double)
+  (:args (object :scs (descriptor-reg))
+         (value :scs (complex-double-reg)))
+  (:arg-types * complex-double-float)
+  (:info instance-length index)
+  (:generator 20
+    (let ((value-real (complex-double-reg-real-tn value)))
+      (with-tn@fp-top (value-real)
+        (inst fstd (make-ea-for-raw-slot object index instance-length 4))))
+    (let ((value-imag (complex-double-reg-imag-tn value)))
+      (with-tn@fp-top (value-imag)
+        (inst fstd (make-ea-for-raw-slot object index instance-length 2))))))