| Commit | Line | Data |
|---|---|---|
| 4df954cb | 1 | ;;; -*- Package: SPARC -*- |
| 2 | ;;; | |
| 3 | ;;; ********************************************************************** | |
| bf9df67b | 4 | ;;; This code was written as part of the CMU Common Lisp project at |
| 5 | ;;; Carnegie Mellon University, and has been placed in the public domain. | |
| bf9df67b | 6 | ;;; |
| 7 | (ext:file-comment | |
| 99a5797f | 8 | "$Header: src/compiler/sparc/system.lisp $") |
| 4df954cb | 9 | ;;; |
| bf9df67b | 10 | ;;; ********************************************************************** |
| 4df954cb | 11 | ;;; |
| 12 | ;;; MIPS VM definitions of various system hacking operations. | |
| 13 | ;;; | |
| 14 | ;;; Written by Rob MacLachlan | |
| 15 | ;;; | |
| 16 | ;;; Mips conversion by William Lott and Christopher Hoover. | |
| 17 | ;;; | |
| 18 | (in-package "SPARC") | |
| d8544caa | 19 | (intl:textdomain "cmucl-sparc-vm") |
| 4df954cb | 20 | |
| 4df954cb | 21 | |
| 22 | \f | |
| 23 | ;;;; Type frobbing VOPs | |
| 24 | ||
| 25 | (define-vop (get-lowtag) | |
| 26 | (:translate get-lowtag) | |
| 27 | (:policy :fast-safe) | |
| 28 | (:args (object :scs (any-reg descriptor-reg))) | |
| 29 | (:results (result :scs (unsigned-reg))) | |
| 30 | (:result-types positive-fixnum) | |
| 31 | (:generator 1 | |
| 32 | (inst and result object vm:lowtag-mask))) | |
| 33 | ||
| 34 | (define-vop (get-type) | |
| 35 | (:translate get-type) | |
| 36 | (:policy :fast-safe) | |
| 4fbccb9d | 37 | (:args (object :scs (descriptor-reg) :to (:eval 1))) |
| 38 | (:results (result :scs (unsigned-reg) :from (:eval 0))) | |
| 4df954cb | 39 | (:result-types positive-fixnum) |
| 40 | (:generator 6 | |
| 4fbccb9d | 41 | ;; Grab the lowtag. |
| 42 | (inst andcc result object lowtag-mask) | |
| 43 | ;; Check for various pointer types. | |
| 44 | (inst cmp result list-pointer-type) | |
| 45 | (inst b :eq done) | |
| 46 | (inst cmp result other-pointer-type) | |
| 47 | (inst b :eq other-pointer) | |
| 48 | (inst cmp result function-pointer-type) | |
| 49 | (inst b :eq function-pointer) | |
| 50 | (inst cmp result instance-pointer-type) | |
| 51 | (inst b :eq done) | |
| 52 | ;; Okay, it is an immediate. If fixnum, we want zero. Otherwise, | |
| 53 | ;; we want the low 8 bits. | |
| 290891fc | 54 | (inst andcc zero-tn object vm:fixnum-tag-mask) |
| 4fbccb9d | 55 | (inst b :eq done) |
| 290891fc | 56 | (inst li result 0) ; Watch out! LI in branch delay slot! |
| 4fbccb9d | 57 | ;; It wasn't a fixnum, so get the low 8 bits. |
| 58 | (inst b done) | |
| 59 | (inst and result object type-mask) | |
| 60 | ||
| 61 | FUNCTION-POINTER | |
| 62 | (inst b done) | |
| 63 | (load-type result object (- function-pointer-type)) | |
| 4df954cb | 64 | |
| 4fbccb9d | 65 | OTHER-POINTER |
| 66 | (load-type result object (- other-pointer-type)) | |
| 4df954cb | 67 | |
| 4fbccb9d | 68 | DONE)) |
| 4df954cb | 69 | |
| 4df954cb | 70 | |
| 8494e39c | 71 | (define-vop (function-subtype) |
| 72 | (:translate function-subtype) | |
| 73 | (:policy :fast-safe) | |
| 74 | (:args (function :scs (descriptor-reg))) | |
| 75 | (:results (result :scs (unsigned-reg))) | |
| 76 | (:result-types positive-fixnum) | |
| 77 | (:generator 6 | |
| 78 | (load-type result function (- vm:function-pointer-type)))) | |
| 79 | ||
| 80 | (define-vop (set-function-subtype) | |
| 81 | (:translate (setf function-subtype)) | |
| 82 | (:policy :fast-safe) | |
| 83 | (:args (type :scs (unsigned-reg) :target result) | |
| 84 | (function :scs (descriptor-reg))) | |
| 85 | (:arg-types positive-fixnum *) | |
| 86 | (:results (result :scs (unsigned-reg))) | |
| 87 | (:result-types positive-fixnum) | |
| 88 | (:generator 6 | |
| 290891fc | 89 | ;; Sparc is big-endian, and the type bits are in the least |
| 90 | ;; significant byte of the word, which means the type bits are at | |
| 91 | ;; the highest byte. | |
| 92 | (inst stb type function (- (- vm:word-bytes 1) function-pointer-type)) | |
| 8494e39c | 93 | (move result type))) |
| 94 | ||
| 4df954cb | 95 | (define-vop (get-header-data) |
| 96 | (:translate get-header-data) | |
| 97 | (:policy :fast-safe) | |
| 98 | (:args (x :scs (descriptor-reg))) | |
| 99 | (:results (res :scs (unsigned-reg))) | |
| 100 | (:result-types positive-fixnum) | |
| 101 | (:generator 6 | |
| 102 | (loadw res x 0 vm:other-pointer-type) | |
| c736685e | 103 | (inst srln res res vm:type-bits))) |
| 4df954cb | 104 | |
| 105 | (define-vop (get-closure-length) | |
| 106 | (:translate get-closure-length) | |
| 107 | (:policy :fast-safe) | |
| 108 | (:args (x :scs (descriptor-reg))) | |
| 109 | (:results (res :scs (unsigned-reg))) | |
| 110 | (:result-types positive-fixnum) | |
| 111 | (:generator 6 | |
| 112 | (loadw res x 0 vm:function-pointer-type) | |
| c736685e | 113 | (inst srln res res vm:type-bits))) |
| 4df954cb | 114 | |
| 115 | (define-vop (set-header-data) | |
| 116 | (:translate set-header-data) | |
| 117 | (:policy :fast-safe) | |
| 118 | (:args (x :scs (descriptor-reg) :target res) | |
| 119 | (data :scs (any-reg immediate zero))) | |
| 120 | (:arg-types * positive-fixnum) | |
| 121 | (:results (res :scs (descriptor-reg))) | |
| 23272192 | 122 | (:temporary (:scs (non-descriptor-reg)) t1 t2) |
| 4df954cb | 123 | (:generator 6 |
| 124 | (loadw t1 x 0 vm:other-pointer-type) | |
| 125 | (inst and t1 vm:type-mask) | |
| 126 | (sc-case data | |
| 127 | (any-reg | |
| c736685e | 128 | (inst slln t2 data (- vm:type-bits vm:fixnum-tag-bits)) |
| 4df954cb | 129 | (inst or t1 t2)) |
| 130 | (immediate | |
| 131 | (inst or t1 (ash (tn-value data) vm:type-bits))) | |
| 132 | (zero)) | |
| 133 | (storew t1 x 0 vm:other-pointer-type) | |
| 134 | (move res x))) | |
| 135 | ||
| 136 | ||
| 4df954cb | 137 | (define-vop (make-fixnum) |
| 138 | (:args (ptr :scs (any-reg descriptor-reg))) | |
| 139 | (:results (res :scs (any-reg descriptor-reg))) | |
| 140 | (:generator 1 | |
| 141 | ;; | |
| 142 | ;; Some code (the hash table code) depends on this returning a | |
| 143 | ;; positive number so make sure it does. | |
| c736685e | 144 | (inst slln res ptr vm:lowtag-bits) |
| 145 | (inst srln res res 1))) | |
| 4df954cb | 146 | |
| 147 | (define-vop (make-other-immediate-type) | |
| 148 | (:args (val :scs (any-reg descriptor-reg)) | |
| 149 | (type :scs (any-reg descriptor-reg immediate) | |
| 150 | :target temp)) | |
| 151 | (:results (res :scs (any-reg descriptor-reg))) | |
| 23272192 | 152 | (:temporary (:scs (non-descriptor-reg)) temp) |
| 4df954cb | 153 | (:generator 2 |
| 154 | (sc-case type | |
| 155 | (immediate | |
| c736685e | 156 | (inst slln temp val vm:type-bits) |
| 4df954cb | 157 | (inst or res temp (tn-value type))) |
| 158 | (t | |
| c736685e | 159 | (inst sran temp type vm:fixnum-tag-bits) |
| 160 | (inst slln res val (- vm:type-bits vm:fixnum-tag-bits)) | |
| 4df954cb | 161 | (inst or res res temp))))) |
| 162 | ||
| 163 | \f | |
| 164 | ;;;; Allocation | |
| 165 | ||
| 166 | (define-vop (dynamic-space-free-pointer) | |
| 167 | (:results (int :scs (sap-reg))) | |
| 168 | (:result-types system-area-pointer) | |
| 169 | (:translate dynamic-space-free-pointer) | |
| 170 | (:policy :fast-safe) | |
| 171 | (:generator 1 | |
| 172 | (move int alloc-tn))) | |
| 173 | ||
| 174 | (define-vop (binding-stack-pointer-sap) | |
| 175 | (:results (int :scs (sap-reg))) | |
| 176 | (:result-types system-area-pointer) | |
| 177 | (:translate binding-stack-pointer-sap) | |
| 178 | (:policy :fast-safe) | |
| 179 | (:generator 1 | |
| 180 | (move int bsp-tn))) | |
| 181 | ||
| 182 | (define-vop (control-stack-pointer-sap) | |
| 183 | (:results (int :scs (sap-reg))) | |
| 184 | (:result-types system-area-pointer) | |
| 185 | (:translate control-stack-pointer-sap) | |
| 186 | (:policy :fast-safe) | |
| 187 | (:generator 1 | |
| 188 | (move int csp-tn))) | |
| 189 | ||
| 190 | \f | |
| 191 | ;;;; Code object frobbing. | |
| 192 | ||
| 193 | (define-vop (code-instructions) | |
| 1ef7b3a2 | 194 | (:translate code-instructions) |
| ff834484 | 195 | (:policy :fast-safe) |
| 4df954cb | 196 | (:args (code :scs (descriptor-reg))) |
| 197 | (:temporary (:scs (non-descriptor-reg)) ndescr) | |
| 198 | (:results (sap :scs (sap-reg))) | |
| 199 | (:result-types system-area-pointer) | |
| 200 | (:generator 10 | |
| 201 | (loadw ndescr code 0 vm:other-pointer-type) | |
| c736685e | 202 | (inst srln ndescr vm:type-bits) |
| 203 | (inst slln ndescr vm:word-shift) | |
| 4df954cb | 204 | (inst sub ndescr vm:other-pointer-type) |
| 205 | (inst add sap code ndescr))) | |
| 206 | ||
| 207 | (define-vop (compute-function) | |
| 208 | (:args (code :scs (descriptor-reg)) | |
| 209 | (offset :scs (signed-reg unsigned-reg))) | |
| 210 | (:arg-types * positive-fixnum) | |
| 211 | (:results (func :scs (descriptor-reg))) | |
| 212 | (:temporary (:scs (non-descriptor-reg)) ndescr) | |
| 213 | (:generator 10 | |
| 214 | (loadw ndescr code 0 vm:other-pointer-type) | |
| c736685e | 215 | (inst srln ndescr vm:type-bits) |
| 216 | (inst slln ndescr vm:word-shift) | |
| 4df954cb | 217 | (inst add ndescr offset) |
| 218 | (inst add ndescr (- vm:function-pointer-type vm:other-pointer-type)) | |
| 219 | (inst add func code ndescr))) | |
| 220 | ||
| 1ef7b3a2 | 221 | |
| 4df954cb | 222 | \f |
| 223 | ;;;; Other random VOPs. | |
| 224 | ||
| 225 | ||
| bf9df67b | 226 | (defknown unix::do-pending-interrupt () (values)) |
| 227 | (define-vop (unix::do-pending-interrupt) | |
| 4df954cb | 228 | (:policy :fast-safe) |
| bf9df67b | 229 | (:translate unix::do-pending-interrupt) |
| 4df954cb | 230 | (:generator 1 |
| 231 | (inst unimp pending-interrupt-trap))) | |
| 232 | ||
| 233 | ||
| 234 | (define-vop (halt) | |
| 235 | (:generator 1 | |
| 236 | (inst unimp halt-trap))) | |
| 237 | ||
| 35d08ff3 | 238 | |
| 239 | \f | |
| 240 | ;;;; Dynamic vop count collection support | |
| 241 | ||
| 242 | (define-vop (count-me) | |
| 243 | (:args (count-vector :scs (descriptor-reg))) | |
| 244 | (:info index) | |
| 245 | (:temporary (:scs (non-descriptor-reg)) count) | |
| 246 | (:generator 1 | |
| 247 | (let ((offset | |
| 248 | (- (* (+ index vector-data-offset) word-bytes) other-pointer-type))) | |
| 249 | (assert (typep offset '(signed-byte 13))) | |
| 4ccddc49 | 250 | (inst ldn count count-vector offset) |
| 35d08ff3 | 251 | (inst add count 1) |
| 4ccddc49 | 252 | (inst stn count count-vector offset)))) |
| fe40afd6 | 253 | |
| 254 | ;; The RDTICK instruction on Sparc V9s allows access to a 63-bit cycle | |
| 255 | ;; counter. | |
| 256 | ||
| 257 | (defknown read-cycle-counter () | |
| 258 | (values (unsigned-byte 32) (unsigned-byte 32))) | |
| 259 | ||
| 260 | ;; Note: This should probably really only be used sparc-v8plus because | |
| 261 | ;; the tick counter is returned in a 64-bit register. | |
| 262 | (define-vop (read-cycle-counter) | |
| 263 | (:translate read-cycle-counter) | |
| 264 | (:guard (backend-featurep :sparc-v9)) | |
| 265 | (:args) | |
| 266 | (:policy :fast-safe) | |
| 267 | (:results (lo :scs (unsigned-reg)) | |
| 268 | (hi :scs (unsigned-reg))) | |
| 269 | (:result-types unsigned-num unsigned-num) | |
| 270 | ;; The temporary can be any of the 64-bit non-descriptor regs. It | |
| 271 | ;; can't be any non-descriptor reg because they might not get saved | |
| 272 | ;; on a task switch, since we're still a 32-bit app. Arbitrarily | |
| 273 | ;; select nl5. | |
| 274 | (:temporary (:sc unsigned-reg :offset nl5-offset) tick) | |
| 275 | (:generator 3 | |
| 276 | (inst rdtick tick) | |
| 277 | ;; Get the hi and low parts of the counter into the results. | |
| 278 | (inst srlx hi tick 32) | |
| c736685e | 279 | (inst clruw lo tick))) |
| fe40afd6 | 280 | |
| 281 | #+sparc-v9 | |
| 282 | (defun read-cycle-counter () | |
| d8544caa | 283 | _N"Read the instruction cycle counter available on UltraSparcs. The |
| 367cb892 | 284 | 64-bit counter is returned as two 32-bit unsigned integers. The low 32-bit |
| 285 | result is the first value." | |
| fe40afd6 | 286 | (read-cycle-counter)) |
| 8d75583b RT |
287 | |
| 288 | (defmacro with-cycle-counter (&body body) | |
| 289 | "Returns the primary value of BODY as the primary value, and the | |
| 290 | number of CPU cycles elapsed as secondary value." | |
| 291 | (let ((hi0 (gensym)) | |
| 292 | (hi1 (gensym)) | |
| 293 | (lo0 (gensym)) | |
| 294 | (lo1 (gensym))) | |
| 295 | `(multiple-value-bind (,lo0 ,hi0) | |
| 296 | (read-cycle-counter) | |
| 297 | (values (locally ,@body) | |
| 298 | (multiple-value-bind (,lo1 ,hi1) | |
| 299 | (read-cycle-counter) | |
| 300 | ;; Can't do anything about the notes about generic | |
| 301 | ;; arithmetic, so silence the notes.. | |
| 302 | (declare (optimize (inhibit-warnings 3)) | |
| 303 | (+ (ash (- ,hi1 ,hi0) 32) | |
| 304 | (- ,lo1 ,lo0))))))) |