Use the new disassembler.
[movitz-core.git] / image.lisp
blobbe069e6e2f4b29f50e20b39e160481ba8da21498
1 ;;;;------------------------------------------------------------------
2 ;;;;
3 ;;;; Copyright (C) 2001,2000, 2002-2005,
4 ;;;; Department of Computer Science, University of Tromso, Norway.
5 ;;;;
6 ;;;; Filename: image.lisp
7 ;;;; Description: Construction of Movitz images.
8 ;;;; Author: Frode Vatvedt Fjeld <frodef@acm.org>
9 ;;;; Created at: Sun Oct 22 00:22:43 2000
10 ;;;; Distribution: See the accompanying file COPYING.
11 ;;;;
12 ;;;; $Id: image.lisp,v 1.115 2008/02/23 22:34:14 ffjeld Exp $
13 ;;;;
14 ;;;;------------------------------------------------------------------
16 (in-package movitz)
18 (define-binary-class movitz-run-time-context (movitz-heap-object)
19 ((run-time-context-start :binary-type :label) ; keep this at the top.
20 (type
21 :binary-type other-type-byte
22 :initform :run-time-context)
23 (padding
24 :binary-type 3)
25 (atomically-continuation
26 :binary-type lu32
27 :initform 0)
28 (raw-scratch0 ; A non-GC-root scratch register
29 :binary-type lu32
30 :initform 0)
31 (pointer-start :binary-type :label)
32 (ret-trampoline
33 :binary-type code-vector-word
34 :map-binary-write 'movitz-intern-code-vector
35 :map-binary-read-delayed 'movitz-word-code-vector
36 :binary-tag :primitive-function)
37 (cons-commit
38 :binary-type code-vector-word
39 :initform nil
40 :map-binary-write 'movitz-intern-code-vector
41 :map-binary-read-delayed 'movitz-word-code-vector
42 :binary-tag :primitive-function)
43 (cons-non-pointer
44 :binary-type code-vector-word
45 :map-binary-write 'movitz-intern-code-vector
46 :map-binary-read-delayed 'movitz-word-code-vector
47 :binary-tag :primitive-function)
48 (cons-commit-non-pointer
49 :binary-type code-vector-word
50 :map-binary-write 'movitz-intern-code-vector
51 :map-binary-read-delayed 'movitz-word-code-vector
52 :binary-tag :primitive-function)
53 (cons-non-header
54 :binary-type code-vector-word
55 :map-binary-write 'movitz-intern-code-vector
56 :map-binary-read-delayed 'movitz-word-code-vector
57 :binary-tag :primitive-function)
58 (cons-commit-non-header
59 :binary-type code-vector-word
60 :map-binary-write 'movitz-intern-code-vector
61 :map-binary-read-delayed 'movitz-word-code-vector
62 :binary-tag :primitive-function)
64 (cons-pointer
65 :binary-type code-vector-word
66 :initform nil
67 :map-binary-write 'movitz-intern-code-vector
68 :map-binary-read-delayed 'movitz-word-code-vector
69 :binary-tag :primitive-function)
70 ;; tag-specific class-of primitive-functions
71 (fast-class-of :binary-type :label)
72 (fast-class-of-even-fixnum ; 0000
73 :binary-type code-vector-word
74 :map-binary-write 'movitz-intern-code-vector
75 :map-binary-read-delayed 'movitz-word-code-vector
76 :binary-tag :primitive-function)
77 (fast-class-of-cons ; 1111
78 :binary-type code-vector-word
79 :map-binary-write 'movitz-intern-code-vector
80 :map-binary-read-delayed 'movitz-word-code-vector
81 :binary-tag :primitive-function)
82 (fast-class-of-character ; 2222
83 :binary-type code-vector-word
84 :map-binary-write 'movitz-intern-code-vector
85 :map-binary-read-delayed 'movitz-word-code-vector
86 :binary-tag :primitive-function)
87 (fast-class-of-tag3 ; 3333
88 :binary-type code-vector-word
89 :map-binary-write 'movitz-intern-code-vector
90 :map-binary-read-delayed 'movitz-word-code-vector
91 :binary-tag :primitive-function)
92 (fast-class-of-odd-fixnum ; 4444
93 :binary-type code-vector-word
94 :map-binary-write 'movitz-intern-code-vector
95 :map-binary-read-delayed 'movitz-word-code-vector
96 :binary-tag :primitive-function)
97 (fast-class-of-null ; 5555
98 :binary-type code-vector-word
99 :map-binary-write 'movitz-intern-code-vector
100 :map-binary-read-delayed 'movitz-word-code-vector
101 :binary-tag :primitive-function)
102 (fast-class-of-other ; 6666
103 :binary-type code-vector-word
104 :map-binary-write 'movitz-intern-code-vector
105 :map-binary-read-delayed 'movitz-word-code-vector
106 :binary-tag :primitive-function)
107 (fast-class-of-symbol ; 7777
108 :binary-type code-vector-word
109 :map-binary-write 'movitz-intern-code-vector
110 :map-binary-read-delayed 'movitz-word-code-vector
111 :binary-tag :primitive-function)
113 (keyword-search
114 :map-binary-write 'movitz-intern-code-vector
115 :map-binary-read-delayed 'movitz-word-code-vector
116 :binary-tag :primitive-function
117 :binary-type code-vector-word)
118 (decode-keyargs-default
119 :map-binary-write 'movitz-intern-code-vector
120 :map-binary-read-delayed 'movitz-word-code-vector
121 :binary-tag :primitive-function
122 :binary-type code-vector-word)
123 (decode-keyargs-foo
124 :map-binary-write 'movitz-intern-code-vector
125 :map-binary-read-delayed 'movitz-word-code-vector
126 :binary-tag :primitive-function
127 :binary-type code-vector-word)
129 (fast-car
130 :binary-type code-vector-word
131 :initform nil
132 :map-binary-write 'movitz-intern-code-vector
133 :map-binary-read-delayed 'movitz-word-code-vector
134 :binary-tag :primitive-function)
135 (fast-cdr
136 :binary-type code-vector-word
137 :initform nil
138 :map-binary-write 'movitz-intern-code-vector
139 :map-binary-read-delayed 'movitz-word-code-vector
140 :binary-tag :primitive-function)
141 (fast-cddr
142 :binary-type code-vector-word
143 :initform nil
144 :map-binary-write 'movitz-intern-code-vector
145 :map-binary-read-delayed 'movitz-word-code-vector
146 :binary-tag :primitive-function)
147 (fast-car-ebx
148 :binary-type code-vector-word
149 :initform nil
150 :map-binary-write 'movitz-intern-code-vector
151 :map-binary-read-delayed 'movitz-word-code-vector
152 :binary-tag :primitive-function)
153 (fast-cdr-ebx
154 :binary-type code-vector-word
155 :initform nil
156 :map-binary-write 'movitz-intern-code-vector
157 :map-binary-read-delayed 'movitz-word-code-vector
158 :binary-tag :primitive-function)
159 ;; primitive functions global constants
160 (pop-current-values
161 :binary-type code-vector-word
162 :initform nil
163 :map-binary-write 'movitz-intern-code-vector
164 :map-binary-read-delayed 'movitz-word-code-vector
165 :binary-tag :primitive-function)
166 (dynamic-variable-lookup
167 :map-binary-write 'movitz-intern-code-vector
168 :binary-tag :primitive-function
169 :map-binary-read-delayed 'movitz-word-code-vector
170 :binary-type code-vector-word)
171 (dynamic-variable-store
172 :map-binary-write 'movitz-intern-code-vector
173 :binary-tag :primitive-function
174 :map-binary-read-delayed 'movitz-word-code-vector
175 :binary-type code-vector-word)
176 (dynamic-unwind-next
177 :map-binary-write 'movitz-intern-code-vector
178 :binary-tag :primitive-function
179 :map-binary-read-delayed 'movitz-word-code-vector
180 :binary-type code-vector-word)
181 (dynamic-variable-install
182 :map-binary-write 'movitz-intern-code-vector
183 :binary-tag :primitive-function
184 :map-binary-read-delayed 'movitz-word-code-vector
185 :binary-type code-vector-word)
186 (dynamic-variable-uninstall
187 :map-binary-write 'movitz-intern-code-vector
188 :binary-tag :primitive-function
189 :map-binary-read-delayed 'movitz-word-code-vector
190 :binary-type code-vector-word)
191 (assert-1arg
192 :map-binary-write 'movitz-intern-code-vector
193 :binary-tag :primitive-function
194 :map-binary-read-delayed 'movitz-word-code-vector
195 :binary-type code-vector-word)
196 (assert-2args
197 :map-binary-write 'movitz-intern-code-vector
198 :binary-tag :primitive-function
199 :map-binary-read-delayed 'movitz-word-code-vector
200 :binary-type code-vector-word)
201 (assert-3args
202 :map-binary-write 'movitz-intern-code-vector
203 :binary-tag :primitive-function
204 :map-binary-read-delayed 'movitz-word-code-vector
205 :binary-type code-vector-word)
206 (decode-args-1or2
207 :map-binary-write 'movitz-intern-code-vector
208 :binary-tag :primitive-function
209 :map-binary-read-delayed 'movitz-word-code-vector
210 :binary-type code-vector-word)
211 (box-u32-ecx
212 :binary-type code-vector-word
213 :map-binary-write 'movitz-intern-code-vector
214 :map-binary-read-delayed 'movitz-word-code-vector
215 :binary-tag :primitive-function)
216 (unbox-u32
217 :binary-type code-vector-word
218 :map-binary-write 'movitz-intern-code-vector
219 :map-binary-read-delayed 'movitz-word-code-vector
220 :binary-tag :primitive-function)
221 (fast-cdr-car
222 :binary-type code-vector-word
223 :initform nil
224 :map-binary-write 'movitz-intern-code-vector
225 :map-binary-read-delayed 'movitz-word-code-vector
226 :binary-tag :primitive-function)
227 (fast-cons
228 :binary-type code-vector-word
229 :initform nil
230 :map-binary-write 'movitz-intern-code-vector
231 :map-binary-read-delayed 'movitz-word-code-vector
232 :binary-tag :primitive-function)
233 (ensure-heap-cons-variable
234 :binary-type code-vector-word
235 :initform nil
236 :map-binary-write 'movitz-intern-code-vector
237 :map-binary-read-delayed 'movitz-word-code-vector
238 :binary-tag :primitive-function)
239 (fast-compare-two-reals
240 :binary-type code-vector-word
241 :initform nil
242 :map-binary-write 'movitz-intern-code-vector
243 :map-binary-read-delayed 'movitz-word-code-vector
244 :binary-tag :primitive-function)
245 (fast-compare-fixnum-real
246 :binary-type code-vector-word
247 :initform nil
248 :map-binary-write 'movitz-intern-code-vector
249 :map-binary-read-delayed 'movitz-word-code-vector
250 :binary-tag :primitive-function)
251 (fast-compare-real-fixnum
252 :binary-type code-vector-word
253 :initform nil
254 :map-binary-write 'movitz-intern-code-vector
255 :map-binary-read-delayed 'movitz-word-code-vector
256 :binary-tag :primitive-function)
257 (trampoline-cl-dispatch-1or2
258 :binary-type code-vector-word
259 :initform nil
260 :map-binary-write 'movitz-intern-code-vector
261 :map-binary-read-delayed 'movitz-word-code-vector
262 :binary-tag :primitive-function)
263 (dynamic-jump-next
264 :binary-type code-vector-word
265 :map-binary-write 'movitz-intern-code-vector
266 :map-binary-read-delayed 'movitz-word-code-vector
267 :binary-tag :primitive-function)
268 (copy-funobj-code-vector-slots
269 :binary-type code-vector-word
270 :map-binary-write 'movitz-intern-code-vector
271 :map-binary-read-delayed 'movitz-word-code-vector
272 :binary-tag :primitive-function)
275 (boolean-one :binary-type :label)
276 (not-nil ; not-nil, t-symbol and not-not-nil must be consecutive.
277 :binary-type word
278 :initform nil
279 :map-binary-write 'movitz-read-and-intern
280 :map-binary-read-delayed 'movitz-word)
281 (boolean-zero :binary-type :label)
282 (t-symbol
283 :binary-type word
284 :initarg :t-symbol
285 :map-binary-write 'movitz-intern
286 :map-binary-read-delayed 'movitz-word)
287 (not-not-nil
288 :binary-type word
289 :initform nil
290 :map-binary-write 'movitz-read-and-intern
291 :map-binary-read-delayed 'movitz-word)
292 ;; (null-cons :binary-type :label)
293 (null-symbol
294 :binary-type movitz-symbol
295 :reader movitz-run-time-context-null-symbol
296 :initarg :null-symbol)
298 (complicated-eql
299 :initform 'muerte::complicated-eql
300 :binary-type word
301 :binary-tag :global-function
302 :map-binary-write 'movitz-intern
303 :map-binary-read-delayed 'movitz-word)
304 (complicated-compare
305 :binary-type word
306 :binary-tag :global-function
307 :map-binary-read-delayed 'movitz-word
308 :map-binary-write 'movitz-intern)
309 (dynamic-env
310 :binary-type word
311 :initform 0)
313 (scratch1
314 :binary-type word
315 :initform 0)
316 (scratch2
317 :binary-type word
318 :initform 0)
319 (class
320 :binary-type word
321 :map-binary-write 'movitz-intern
322 :map-binary-read-delayed 'movitz-word
323 :initarg :class
324 :accessor run-time-context-class)
325 (slots
326 :binary-type word
327 :map-binary-write 'movitz-read-and-intern
328 :map-binary-read-delayed 'movitz-word
329 :initarg :slots
330 :initform #(:init nil)
331 :accessor run-time-context-slots)
332 (unwind-protect-tag
333 :binary-type word
334 :map-binary-read-delayed 'movitz-word
335 :map-binary-write 'movitz-read-and-intern
336 :initform 'muerte::unwind-protect-tag)
337 (restart-tag
338 :binary-type word
339 :map-binary-read-delayed 'movitz-word
340 :map-binary-write 'movitz-read-and-intern
341 :initform 'muerte::restart-protect-tag)
342 (new-unbound-value
343 :binary-type word
344 :map-binary-read-delayed 'movitz-word
345 :map-binary-write 'movitz-read-and-intern
346 :initform 'unbound)
347 (stack-bottom ; REMEMBER BOCHS!
348 :binary-type word
349 :initform #x0ff000)
350 (stack-top ; stack-top must be right after stack-bottom
351 :binary-type word ; in order for the bound instruction to work.
352 :initform #x100000)
354 :initform 'muerte.cl:+
355 :binary-type word
356 :binary-tag :global-function
357 :map-binary-write 'movitz-intern
358 :map-binary-read-delayed 'movitz-word)
359 (the-class-t
360 :binary-type word
361 :initform t
362 :map-binary-write (lambda (x type)
363 (declare (ignore type))
364 (movitz-read-and-intern (funcall 'muerte::movitz-find-class x)
365 'word))
366 :map-binary-read-delayed 'movitz-word)
367 (copy-funobj
368 :binary-type word
369 ;; :accessor movitz-run-time-context-copy-funobj
370 :initform 'muerte::copy-funobj
371 :map-binary-write (lambda (name type)
372 (declare (ignore type))
373 (movitz-intern (movitz-env-named-function name))))
376 (classes ; A vector of class meta-objects.
377 :initform nil ; The first element is the map of corresponding names
378 :binary-type word
379 :map-binary-write (lambda (x type)
380 (declare (ignore x type))
381 (let ((map (image-classes-map *image*)))
382 (movitz-read-and-intern
383 (apply #'vector
385 (mapcar (lambda (x)
386 (funcall 'muerte::movitz-find-class x))
387 map))
388 'word)))
389 :map-binary-read-delayed 'movitz-word)
390 (physical-address-offset
391 :binary-type lu32
392 :initform (image-ds-segment-base *image*))
393 (nursery-space
394 :binary-type word
395 :initform nil
396 :map-binary-write 'movitz-read-and-intern
397 :map-binary-read-delayed (lambda (x type)
398 (declare (ignore x type))
399 (movitz-read nil)))
400 (allow-other-keys-symbol
401 :binary-type word
402 :initform :allow-other-keys
403 :map-binary-write 'movitz-read-and-intern
404 :map-binary-read-delayed (lambda (x type)
405 (declare (ignore x type))
406 (movitz-read nil)))
407 (self
408 :binary-type word
409 :initform 6
410 :map-binary-read-delayed 'movitz-word)
411 (complicated-class-of
412 :binary-type word
413 :binary-tag :global-function
414 :map-binary-read-delayed 'movitz-word
415 :map-binary-write 'movitz-intern)
416 (stack-vector
417 :binary-type word
418 :initform nil
419 :map-binary-write 'movitz-read-and-intern
420 :map-binary-read-delayed (lambda (x type)
421 (declare (ignore x type))
422 (movitz-read nil)))
423 (exception-handlers
424 :binary-type word
425 :map-binary-write 'movitz-intern
426 :map-binary-read-delayed 'movitz-word
427 :initarg :exception-handlers
428 :accessor movitz-run-time-context-exception-handlers)
429 (interrupt-descriptor-table
430 :binary-type word
431 :accessor movitz-run-time-context-interrupt-descriptor-table
432 :initform (make-array 256 :initial-element 'muerte::default-interrupt-trampoline)
433 :map-binary-read-delayed 'movitz-word
434 :map-binary-write 'map-interrupt-trampolines-to-idt)
435 (num-values
436 :binary-type word ; Fixnum
437 :initform 0)
438 (values
439 :binary-type #.(* 4 +movitz-multiple-values-limit+)))
440 (:slot-align null-symbol -5))
442 (defun atomically-continuation-simple-pf (pf-name)
443 (ldb (byte 32 0) (global-constant-offset pf-name))
444 #+ignore
445 (bt:enum-value 'movitz::atomically-status
446 (list* :restart-primitive-function
447 (cons :reset-status-p
448 (if reset-status-p 1 0))
449 (cons :data
450 (if (not pf-name)
452 (truncate (+ (tag :null)
453 (bt:slot-offset 'movitz-run-time-context
454 (intern (symbol-name pf-name)
455 :movitz)))
456 4)))
457 registers)))
459 (defun atomically-status-jumper-fn (reset-status-p &rest registers)
460 (assert (not reset-status-p))
461 (assert (null registers))
462 (lambda (jumper)
463 (assert (= 0 (mod jumper 4)))
464 (bt:enum-value 'movitz::atomically-status
465 (list* :restart-jumper
466 (cons :reset-status-p
467 (if reset-status-p 1 0))
468 (cons :data (truncate jumper 4))
469 registers))))
471 (defmethod movitz-object-offset ((obj movitz-run-time-context)) 0)
473 (defun global-constant-offset (slot-name)
474 (check-type slot-name symbol)
475 (let ((slot-name (find-symbol (symbol-name slot-name) :movitz)))
476 (assert slot-name)
477 (if (not (eq slot-name 'unbound-function))
478 (slot-offset 'movitz-run-time-context slot-name)
479 (+ (slot-offset 'movitz-run-time-context 'null-symbol)
480 (slot-offset 'movitz-symbol 'function-value)
481 (tag :symbol)))))
483 (defun make-movitz-run-time-context ()
484 (make-instance 'movitz-run-time-context
485 :t-symbol (movitz-read 't)
486 :null-symbol *movitz-nil*))
488 (defclass movitz-image ()
489 ((ds-segment-base
490 :initarg :ds-segment-base
491 :initform #x100000
492 :accessor image-ds-segment-base)
493 (cs-segment-base
494 :initarg :cs-segment-base
495 :initform #x100000
496 :accessor image-cs-segment-base)))
498 (defclass symbolic-image (movitz-image)
499 ((object-hash
500 :accessor image-object-hash) ; object => address
501 (address-hash
502 :accessor image-address-hash) ; address => object
503 (cons-pointer
504 :accessor image-cons-pointer)
505 (read-map-hash
506 :initform (make-hash-table :test #'eql) ; lisp object => movitz object
507 :reader image-read-map-hash)
508 (inverse-read-map-hash
509 :initform (make-hash-table :test #'eql) ; lisp object => movitz object
510 :reader image-inverse-read-map-hash)
511 (oblist
512 :reader image-oblist
513 :initform (make-hash-table :test #'eql))
514 (global-environment
515 :initform (make-global-movitz-environment)
516 :reader image-global-environment)
517 (struct-slot-descriptions
518 :initform (make-hash-table :test #'eq)
519 :accessor image-struct-slot-descriptions)
520 (start-address
521 :initarg :start-address
522 :accessor image-start-address)
523 (symbol-hash-key-counter
524 :initform 0
525 :type unsigned-byte
526 :accessor image-symbol-hash-key-counter)
527 (nil-word
528 :accessor image-nil-word)
529 (nil-object
530 :initarg :nil-object
531 :accessor image-nil-object)
532 (t-symbol
533 :accessor image-t-symbol)
534 (bootblock
535 :accessor image-bootblock)
536 (movitz-modules
537 :initarg :movitz-modules
538 :initform nil
539 :accessor image-movitz-modules)
540 (movitz-features
541 :initarg :movitz-features
542 :accessor image-movitz-features)
543 (called-functions
544 :initarg :called-functions
545 :initform nil
546 :accessor image-called-functions)
547 (toplevel-funobj
548 :accessor image-toplevel-funobj)
549 (run-time-context
550 :accessor image-run-time-context)
551 (load-time-funobjs
552 :initform ()
553 :accessor image-load-time-funobjs)
554 (compile-time-variables
555 :initform ()
556 :accessor image-compile-time-variables)
557 (string-constants
558 :initform (make-hash-table :test #'equal)
559 :reader image-string-constants)
560 (cons-constants
561 :initform (make-hash-table :test #'equal)
562 :reader image-cons-constants)
563 (multiboot-header
564 :accessor image-multiboot-header)
565 (dump-count
566 :initform 0
567 :accessor dump-count)
568 (function-code-sizes
569 :initform (make-hash-table :test #'equal)
570 :initarg :function-code-sizes
571 :reader function-code-sizes)))
573 (defmethod image-classes-map ((image symbolic-image))
574 '(muerte.cl:null muerte.cl:cons muerte.cl:fixnum muerte.cl:symbol
575 muerte.cl:character muerte.cl:function muerte.cl:condition
576 muerte.cl:integer muerte.cl:ratio muerte.cl:complex
577 muerte.cl:vector muerte.cl:string muerte.cl:bit-vector muerte.cl:array
578 muerte.cl:class muerte.cl:standard-class
579 muerte.cl:standard-generic-function
580 muerte:run-time-context
581 muerte.mop:standard-effective-slot-definition
582 muerte.mop:funcallable-standard-class
583 muerte::basic-restart
584 muerte::illegal-object))
586 (defun class-object-offset (name)
587 (let ((name (translate-program name :cl :muerte.cl)))
588 (+ (bt:slot-offset 'movitz-basic-vector 'data)
589 (* 4 (1+ (or (position name (image-classes-map *image*))
590 (error "No class named ~S in class-map." name)))))))
592 (defun unbound-value ()
593 (declare (special *image*))
594 (movitz-read (slot-value (image-run-time-context *image*)
595 'new-unbound-value)))
597 (defun edi-offset ()
598 (declare (special *image*))
599 (- (image-nil-word *image*)))
601 (defmethod image-intern-object ((image symbolic-image) object &optional (size (sizeof object)))
602 (assert ; sanity check on "other" storage-types.
603 (or (not (typep object 'movitz-heap-object-other))
604 (and (= (- (tag :other))
605 (slot-offset (type-of object)
606 (first (binary-record-slot-names (type-of object)))))
607 (= +other-type-offset+ (slot-offset (type-of object) 'type))))
609 "The MOVITZ-HEAP-OBJECT-OTHER type ~A is malformed!" (type-of object))
610 (etypecase object
611 (movitz-null
612 (image-nil-word image))
613 (movitz-heap-object
614 (+ (movitz-object-offset object)
615 (or (gethash object (image-object-hash image))
616 (let* ((alignment (movitz-storage-alignment object))
617 (new-ptr (if (= (movitz-storage-alignment-offset object)
618 (mod (image-cons-pointer image)
619 (movitz-storage-alignment object)))
620 (image-cons-pointer image)
621 (+ (image-cons-pointer image)
622 (mod (- (image-cons-pointer image))
623 alignment)
624 (movitz-storage-alignment-offset object)))))
625 (setf (gethash new-ptr (image-address-hash image)) object
626 (gethash object (image-object-hash image)) new-ptr
627 (image-cons-pointer image) (+ new-ptr size))
628 new-ptr))))))
630 (defmethod image-memref ((image symbolic-image) address &optional (errorp t))
631 (let ((obj (gethash address (image-address-hash image) :nothing)))
632 (cond
633 ((not (typep obj 'movitz-object))
634 (when errorp
635 (error "Found non-movitz-object at image-address #x~X: ~A" address obj))
636 nil)
637 (t obj))))
639 (defmethod search-image ((image symbolic-image) address)
640 (loop for a downfrom (logand address -8) by 8
641 until (gethash a (image-address-hash image))
642 finally (let ((object (gethash a (image-address-hash image))))
643 (when (<= address (+ a (sizeof object)))
644 ;; (warn "Found at ~X: ~S" a (gethash a (image-address-hash image)))
645 (return object)))))
647 (defun search-image-funobj (address &optional (*image* *image*))
648 (search-image-funobj-by-image *image* address))
650 (defmethod search-image-funobj-by-image ((image symbolic-image) address)
651 (let ((code-vector (search-image image (1- address))))
652 (unless (and (typep code-vector 'movitz-basic-vector)
653 (eq :code (movitz-vector-element-type code-vector)))
654 (error "Not a code-vector at #x~8,'0X: ~S" address code-vector))
655 (let ((offset (- address (movitz-intern-code-vector code-vector))))
656 (assert (not (minusp offset)))
657 (format t "~&;; Matched code-vector at #x~X with offset ~D.~%"
658 (image-intern-object image code-vector)
659 offset))
660 (with-hash-table-iterator (next-object (image-object-hash *image*))
661 (loop with more-objects and object
662 do (multiple-value-setq (more-objects object) (next-object))
663 while more-objects
664 when (typecase object
665 (movitz-funobj
666 (when (eq code-vector (movitz-funobj-code-vector object))
667 object))
668 (movitz-symbol
669 (when (eq code-vector (movitz-symbol-value object))
670 (movitz-print object))))
671 collect it))))
673 (defun search-primitive-function (address &optional (*image* *image*))
674 (let ((code-vector (search-image *image* address)))
675 (unless (and (typep code-vector 'movitz-basic-vector)
676 (eq :u8 (movitz-vector-element-type code-vector)))
677 (error "Not a code-vector at #x~8,'0X: ~S" address code-vector))
678 (format t "~&;; Code vector: #x~X" (movitz-intern code-vector))
679 (loop for pf-name in (binary-record-slot-names 'movitz-run-time-context
680 :match-tags :primitive-function)
681 when (= (movitz-intern-code-vector code-vector)
682 (binary-slot-value (image-run-time-context *image*) pf-name))
683 do (format t "~&;; #x~X matches global primitive-function ~W with offset ~D."
684 address pf-name
685 (- address (movitz-intern-code-vector code-vector)))
686 and collect pf-name)))
690 (defun movitz-word (word &optional (type 'word))
691 "Return the movitz-object corresponding to (the integer) WORD."
692 (assert (eq type 'word))
693 (movitz-word-by-image *image* word))
695 (defun movitz-word-and-print (word &optional (type 'word))
696 (movitz-print (movitz-word word type)))
698 (defmethod movitz-word-by-image ((image symbolic-image) word)
699 (case (extract-tag word)
700 (#.+fixnum-tags+
701 (make-movitz-fixnum
702 (make-instance 'movitz-fixnum :value (fixnum-integer word))))
703 (:character
704 (make-instance 'movitz-character :char (code-char (ldb (byte 8 8) word))))
705 (:null
706 (image-nil-word image))
707 (t (image-memref *image* (logand word #xfffffff8) t))))
709 (defun movitz-intern-code-vector (object &optional (type 'code-vector-word))
710 "Four ways to denote a code-vector: a vector is that vector,
711 a symbol is considered a primitive-function and the symbol-value is used,
712 a movitz-funobj is that funobj's code-vector,
713 a cons is an offset (the car) from some other code-vector (the cdr)."
714 (assert (member type '(code-vector-word code-pointer)))
715 (etypecase object
716 ((or vector movitz-basic-vector)
717 (+ 2 (movitz-intern object)))
718 ((or symbol movitz-symbol)
719 (let ((primitive-code-vector (movitz-symbol-value (movitz-read object))))
720 (check-type primitive-code-vector movitz-basic-vector)
721 (movitz-intern-code-vector primitive-code-vector type)))
722 (movitz-funobj
723 (movitz-intern-code-vector (movitz-funobj-code-vector object) type))
724 (cons
725 ;; a cons denotes an offset (car) from some funobj's (cdr) code-vector.
726 (check-type (car object) integer)
727 (check-type (cdr object) movitz-funobj)
728 (+ (car object) (movitz-intern-code-vector (cdr object) type)))))
730 (defun movitz-intern-global-function (object &optional (type 'word))
731 (assert (eq type 'word))
732 (check-type object symbol)
733 (let ((x (movitz-env-named-function object)))
734 (check-type x movitz-funobj)
735 (movitz-intern x 'word)))
737 (defun movitz-word-code-vector (word &optional (type 'code-vector-word))
738 (assert (eq type 'code-vector-word))
739 (movitz-word (- word +code-vector-word-offset+)))
741 (defun copy-hash-table (x)
742 (let ((y (make-hash-table :test (hash-table-test x))))
743 (maphash (lambda (k v)
744 (setf (gethash k y) v))
748 (defun make-initial-segment-descriptor-table ()
749 (let ((u32-list
750 (let ((bt:*endian* :little-endian))
751 (merge-bytes (with-binary-output-to-list (octet-list)
752 (mapcar (lambda (init-args)
753 (write-binary 'segment-descriptor octet-list
754 (apply #'make-segment-descriptor init-args)))
755 `(() ; 0
756 (:base 0 :limit #xfffff ; 1: physical code
757 :type 14 :dpl 0 :flags (s p d/b g))
758 (:base 0 :limit #xfffff ; 2: physical data
759 :type 2 :dpl 3 :flags (s p d/b g))
760 (:base ,(image-cs-segment-base *image*) ; 3: logical code
761 :limit #xfff00
762 :type 14 :dpl 0 :flags (s p d/b g))
763 (:base ,(image-ds-segment-base *image*) ; 4: logical data
764 :limit #xfff00
765 :type 2 :dpl 0 :flags (s p d/b g))
767 8 32))))
768 (movitz-read (make-movitz-vector (length u32-list)
769 :initial-contents u32-list
770 :element-type '(unsigned-byte 32)))))
773 (defun make-movitz-image (&rest init-args &key start-address &allow-other-keys)
774 (let ((*image* (apply #'make-instance 'symbolic-image
775 :nil-object (make-movitz-nil)
776 :start-address start-address
777 :movitz-features '(:movitz)
778 :function-code-sizes
779 (if *image*
780 (copy-hash-table (function-code-sizes *image*))
781 (make-hash-table :test #'equal))
782 init-args)))
783 (setf (image-nil-word *image*)
784 (+ 5 (- (slot-offset 'movitz-run-time-context 'null-symbol)
785 (slot-offset 'movitz-run-time-context 'run-time-context-start))
786 (- start-address
787 (image-ds-segment-base *image*))))
788 (format t "~&;; NIL value: #x~X.~%" (image-nil-word *image*))
789 (assert (eq :null (extract-tag (image-nil-word *image*))) ()
790 "NIL value #x~X has tag ~D, but it must be ~D."
791 (image-nil-word *image*)
792 (ldb (byte 3 0) (image-nil-word *image*))
793 (tag :null))
794 (setf (image-run-time-context *image*) (make-movitz-run-time-context))
795 (setf (image-t-symbol *image*) (movitz-read t))
796 ;; (warn "NIL value: #x~X" (image-nil-word *image*))
797 *image*))
799 (defun find-primitive-function (name)
800 "Given the NAME of a primitive function, look up
801 that function's code-vector."
802 (let ((code-vector
803 (movitz-symbol-value (movitz-read name))))
804 (unless (and code-vector (not (eq 'unbound code-vector)))
805 (cerror "Install an empty vector instead."
806 "Global constant primitive function ~S is not defined!" name)
807 (setf code-vector
808 (setf (movitz-symbol-value (movitz-read name))
809 (movitz-read #()))))
810 (check-type code-vector movitz-basic-vector)
811 code-vector))
813 (defun create-image (&rest init-args
814 &key (init-file *default-image-init-file*)
815 (gc t)
816 ;; (start-address #x100000)
817 &allow-other-keys)
818 (psetq *image* (let ((*image* (apply #'make-movitz-image
819 :start-address #x100000
820 init-args)))
821 (when init-file
822 (movitz-compile-file init-file))
823 *image*)
824 *i* *image*)
825 (when gc
826 #+allegro (setf (sys:gsgc-parameter :generation-spread) 8)
827 #+allegro (excl:gc :tenure)
828 #+allegro (excl:gc t)) ; We just thrashed a lot of tenured objects.
829 *image*)
831 (defun set-file-position (stream position &optional who)
832 (declare (ignore who))
833 (or (ignore-errors (file-position stream position))
834 (let* ((end (file-position stream :end))
835 (diff (- position end)))
836 (dotimes (i diff)
837 (write-byte 0 stream))
838 (assert (= position (file-position stream)))))
839 (values))
841 (defun dump-image (&key (path *default-image-file*) ((:image *image*) *image*)
842 (multiboot-p t) ignore-dump-count (qemu-align-p t))
843 "When <multiboot-p> is true, include a MultiBoot-compliant header in the image."
844 (when (and (not ignore-dump-count)
845 (= 0 (dump-count *image*)))
846 ;; This is a hack to deal with the fact that the first dump won't work
847 ;; because the packages aren't properly set up.
848 (format t "~&;; Doing initiating dump..")
849 (dump-image :path path :multiboot-p multiboot-p :ignore-dump-count t)
850 (assert (plusp (dump-count *image*))))
851 (setf (movitz-symbol-value (movitz-read 'muerte:*build-number*))
852 (1+ *bootblock-build*))
853 (when (eq 'unbound (movitz-symbol-value (movitz-read 'muerte::*initial-segment-descriptor-table*)))
854 (setf (movitz-symbol-value (movitz-read 'muerte::*initial-segment-descriptor-table*))
855 (make-initial-segment-descriptor-table)))
856 (let ((handler (movitz-env-symbol-function 'muerte::interrupt-default-handler)))
857 (setf (movitz-run-time-context-exception-handlers (image-run-time-context *image*))
858 (movitz-read (make-array 256 :initial-element handler))))
859 (setf (movitz-symbol-value (movitz-read 'muerte::*setf-namespace*))
860 (movitz-read (movitz-environment-setf-function-names *movitz-global-environment*) t))
861 (setf (run-time-context-class (image-run-time-context *image*))
862 (muerte::movitz-find-class 'muerte::run-time-context))
863 ;; (setf (run-time-context-slots (image-run-time-context *image*)) #(1 2 3))
864 (let ((load-address (image-start-address *image*)))
865 (setf (image-cons-pointer *image*) (- load-address
866 (image-ds-segment-base *image*))
867 (image-address-hash *image*) (make-hash-table :test #'eq)
868 (image-object-hash *image*) (make-hash-table :test #'eq)
869 (image-multiboot-header *image*) (make-instance 'multiboot-header
870 :header-address 0
871 :load-address 0
872 :load-end-address 0
873 :entry-address 0))
874 (assert (= load-address (+ (image-intern-object *image* (image-run-time-context *image*))
875 (image-ds-segment-base *image*))))
876 (when multiboot-p
877 (assert (< (+ (image-intern-object *image* (image-multiboot-header *image*))
878 (sizeof (image-multiboot-header *image*))
879 (- load-address))
880 8192)))
881 ;; make the toplevel-funobj
882 (unless (image-load-time-funobjs *image*)
883 (warn "No top-level funobjs!"))
884 (setf (image-load-time-funobjs *image*)
885 (stable-sort (copy-list (image-load-time-funobjs *image*)) #'> :key #'third))
886 (let* ((toplevel-funobj (make-toplevel-funobj *image*)))
887 (setf (image-toplevel-funobj *image*) toplevel-funobj
888 #+ignore ((movitz-run-time-context-toplevel-funobj (image-run-time-context *image*)) toplevel-funobj))
889 (format t "~&;; load-sequence:~%~<~A~>~%" (mapcar #'second (image-load-time-funobjs *image*)))
890 (movitz-intern toplevel-funobj)
891 (let ((init-code-address (+ (movitz-intern-code-vector (movitz-funobj-code-vector toplevel-funobj))
892 (image-cs-segment-base *image*))))
893 (dolist (cf (image-called-functions *image*))
894 (unless (typep (movitz-env-named-function (car cf) nil)
895 'movitz-funobj)
896 (warn "Function ~S is called (in ~S) but not defined." (car cf) (cdr cf))))
897 (maphash #'(lambda (symbol function-value)
898 (let ((movitz-symbol (movitz-read symbol)))
899 (if (typep function-value 'movitz-object)
900 ;; (warn "SETTING ~A's funval to ~A"
901 ;; movitz-symbol function-value)
902 (setf (movitz-symbol-function-value movitz-symbol)
903 function-value)
904 #+ignore (warn "fv: ~W" (movitz-macro-expander-function function-value)))))
905 (movitz-environment-function-cells (image-global-environment *image*)))
906 (let ((run-time-context (image-run-time-context *image*)))
907 ;; pull in functions in run-time-context
908 (dolist (gcf-name (binary-record-slot-names 'movitz-run-time-context :match-tags :global-function))
909 (let* ((gcf-movitz-name (movitz-read (intern (symbol-name gcf-name)
910 ':muerte)))
911 (gcf-funobj (movitz-symbol-function-value gcf-movitz-name)))
912 (setf (slot-value run-time-context gcf-name) 0)
913 (cond
914 ((or (not gcf-funobj)
915 (eq 'unbound gcf-funobj))
916 (warn "Global constant function ~S is not defined!" gcf-name))
917 (t (check-type gcf-funobj movitz-funobj)
918 (setf (slot-value run-time-context gcf-name)
919 gcf-funobj)))))
920 ;; pull in primitive functions in run-time-context
921 (dolist (pf-name (binary-record-slot-names 'movitz-run-time-context
922 :match-tags :primitive-function))
923 (setf (slot-value run-time-context pf-name)
924 (find-primitive-function (intern (symbol-name pf-name) :muerte))))
925 #+ignore
926 (loop for k being the hash-keys of (movitz-environment-setf-function-names *movitz-global-environment*)
927 using (hash-value v)
928 do (assert (eq (symbol-value v) 'muerte::setf-placeholder))
929 do (when (eq *movitz-nil* (movitz-symbol-function-value (movitz-read v)))
930 (warn "non-used setf: ~S" v)))
931 ;; symbol plists
932 (loop for (symbol plist) on (movitz-environment-plists *movitz-global-environment*) by #'cddr
933 ;; do (warn "sp: ~S ~S" symbol plist)
934 do (let ((x (movitz-read symbol)))
935 (typecase x
936 (movitz-null)
937 (movitz-symbol
938 (setf (movitz-plist x)
939 (movitz-read (translate-program (loop for (property value) on plist by #'cddr
940 unless (member property '(special constantp))
941 append (list property value))
942 :cl :muerte.cl))))
943 (t (warn "not a symbol for plist: ~S has ~S" symbol plist)))))
944 ;; pull in global properties
945 (loop for (var value) on (image-compile-time-variables *image*) by #'cddr
946 do (let ((mname (movitz-read var))
947 (mvalue (movitz-read value)))
948 (setf (movitz-symbol-value mname) mvalue)))
949 (setf (movitz-symbol-value (movitz-read 'muerte::*packages*))
950 (movitz-read (make-packages-hash))))
951 (with-binary-file (stream path
952 :check-stream t
953 :direction :output
954 :if-exists :supersede
955 :if-does-not-exist :create)
956 (set-file-position stream 512) ; leave room for bootblock.
957 (let* ((stack-vector (make-instance 'movitz-basic-vector
958 :num-elements #x3ffe
959 :fill-pointer 0
960 :symbolic-data nil
961 :element-type :u32))
962 (image-start (file-position stream)))
963 (dump-image-core *image* stream) ; dump the kernel proper.
964 ;; make a stack-vector for the root run-time-context
965 (let* ((stack-vector-word
966 (let ((*endian* :little-endian))
967 (write-binary-record stack-vector stream)
968 ;; Intern as _last_ object in image.
969 (movitz-intern stack-vector)))
970 (image-end (file-position stream))
971 (kernel-size (- image-end image-start)))
972 (format t "~&;; Kernel size: ~D octets.~%" kernel-size)
973 (cond
974 (qemu-align-p
975 ;; QEMU is rather stupid about "auto-detecting" floppy geometries.
976 (loop for qemu-geo in '(320 360 640 720 720 820 840 1440 1440 1600 1640 1660 1760 2080 2240 2400
977 2880 2952 2988 3200 3200 3360 3444 3486 3520 3680 3840 5760 6240 6400 7040 7680)
978 as qemu-size = (* qemu-geo 512)
979 do (when (>= qemu-size image-end)
980 (set-file-position stream (1- qemu-size) 'pad-image-tail)
981 (write-byte #x0 stream)
982 (return))
983 finally
984 (cerror "Never mind, dump the image."
985 "No matching QEMU floppy geometry for size ~,2F MB." (/ image-end (* 1024 1024)))))
986 (t (let ((align-image-size 512)) ; Ensure image is multiple of x octets
987 (unless (zerop (mod image-end align-image-size))
988 (set-file-position stream (+ image-end (- (1- align-image-size) (mod image-end 512)))
989 'pad-image-tail)
990 (write-byte #x0 stream)))))
991 (format t "~&;; Image file size: ~D octets.~%" image-end)
992 ;; Write simple stage1 bootblock into sector 0..
993 (format t "~&;; Dump count: ~D." (incf (dump-count *image*)))
994 (flet ((global-slot-position (slot-name)
995 (+ 512
996 (image-nil-word *image*)
997 (image-ds-segment-base *image*)
998 (global-constant-offset slot-name)
999 (- load-address))))
1000 (with-simple-restart (continue "Don't write a floppy bootloader.")
1001 (let ((bootblock (make-bootblock kernel-size
1002 load-address
1003 init-code-address)))
1004 (setf (image-bootblock *image*) bootblock)
1005 (set-file-position stream 0)
1006 (write-sequence bootblock stream)))
1007 (let* ((stack-vector-address (+ (image-nil-word *image*)
1008 (global-constant-offset 'stack-vector)
1009 (image-ds-segment-base *image*)))
1010 (stack-vector-position (- (+ stack-vector-address 512)
1011 load-address)))
1012 (declare (ignore stack-vector-position))
1013 #+ignore(warn "stack-v-pos: ~S => ~S"
1014 stack-vector-position
1015 stack-vector-word)
1016 (set-file-position stream (global-slot-position 'stack-vector) 'stack-vector)
1017 (write-binary 'word stream stack-vector-word)
1018 (set-file-position stream (global-slot-position 'stack-bottom) 'stack-bottom)
1019 (write-binary 'lu32 stream (+ 8 (* 4 4096) ; cushion
1020 (- stack-vector-word (tag :other))))
1021 (set-file-position stream (global-slot-position 'stack-top) 'stack-top)
1022 (write-binary 'lu32 stream (+ 8 (- stack-vector-word (tag :other))
1023 (* 4 (movitz-vector-num-elements stack-vector)))))
1024 (if (not multiboot-p)
1025 (format t "~&;; No multiboot header.")
1026 ;; Update multiboot header, symbolic and in the file..
1027 (let* ((mb (image-multiboot-header *image*))
1028 (mb-address (+ (movitz-intern mb)
1029 (slot-offset 'multiboot-header 'magic)
1030 (image-ds-segment-base *image*)))
1031 (mb-file-position (- (+ mb-address 512)
1032 load-address
1033 (slot-offset 'multiboot-header 'magic))))
1034 (when (< load-address #x100000)
1035 (warn "Multiboot load-address #x~x is below the 1MB mark."
1036 load-address))
1037 (when (> (+ mb-file-position (sizeof mb)) 8192)
1038 (warn "Multiboot header at position ~D is above the 8KB mark, ~
1039 this image will not be Multiboot compatible."
1040 (+ mb-file-position (sizeof mb))))
1041 (set-file-position stream mb-file-position 'multiboot-header)
1042 ;; (format t "~&;; Multiboot load-address: #x~X." load-address)
1043 (setf (header-address mb) mb-address
1044 (load-address mb) load-address
1045 (load-end-address mb) (+ load-address kernel-size)
1046 (bss-end-address mb) (+ load-address kernel-size)
1047 (entry-address mb) init-code-address)
1048 (write-binary-record mb stream))))))))))
1049 (values))
1051 (defun dump-image-core (image stream)
1052 (let ((*endian* :little-endian)
1053 (*record-all-funobjs* nil)
1054 (symbols-size 0)
1055 (conses-size 0)
1056 (funobjs-size 0)
1057 (code-vectors-size 0)
1058 (strings-size 0)
1059 (simple-vectors-size 0)
1060 (total-size 0)
1061 (symbols-numof 0)
1062 (gensyms-numof 0)
1063 (conses-numof 0)
1064 (funobjs-numof 0)
1065 (code-vectors-numof 0)
1066 (strings-numof 0)
1067 (simple-vectors-numof 0)
1068 (file-start-position (file-position stream))
1069 (pad-size 0))
1070 (declare (special *record-all-funobjs*))
1071 (loop with prev-obj
1072 for p upfrom (- (image-start-address image) (image-ds-segment-base image)) by 8
1073 until (>= p (image-cons-pointer image))
1074 summing
1075 (let ((obj (image-memref image p nil)))
1076 (cond
1077 ((not obj) 0) ; (+ 1mb (- 1mb)) vs. (+ 0 (- 1mb 1mb))
1078 (t (let ((new-pos (+ p file-start-position
1079 (- (image-ds-segment-base image)
1080 (image-start-address image)))))
1081 (let ((pad-delta (- new-pos (file-position stream))))
1082 (with-simple-restart (continue "Never mind.")
1083 (assert (<= 0 pad-delta 31) ()
1084 "pad-delta ~S for ~S (prev ~S), p: ~S, new-pos: ~S"
1085 pad-delta obj prev-obj p new-pos))
1086 (incf pad-size pad-delta))
1087 (set-file-position stream new-pos obj))
1088 ;; (warn "Dump at address #x~X, filepos #x~X: ~A" p (file-position stream) obj)
1089 (let ((old-pos (file-position stream))
1090 (write-size (write-binary-record obj stream)))
1091 (incf total-size write-size)
1092 (typecase obj
1093 (movitz-basic-vector
1094 (case (movitz-vector-element-type obj)
1095 (:character (incf strings-numof)
1096 (incf strings-size write-size))
1097 (:any-t (incf simple-vectors-numof)
1098 (incf simple-vectors-size write-size))
1099 (:code (incf code-vectors-numof)
1100 (incf code-vectors-size write-size))))
1101 (movitz-funobj (incf funobjs-numof)
1102 (incf funobjs-size write-size))
1103 (movitz-symbol (incf symbols-numof)
1104 (incf symbols-size write-size)
1105 (when (movitz-eql *movitz-nil* (movitz-symbol-package obj))
1106 (incf gensyms-numof)))
1107 (movitz-cons (incf conses-numof)
1108 (incf conses-size write-size)))
1109 (assert (= write-size (sizeof obj) (- (file-position stream) old-pos)) ()
1110 "Inconsistent write-size(~D)/sizeof(~D)/file-position delta(~D) ~
1111 for object ~S."
1112 write-size (sizeof obj) (- (file-position stream) old-pos) obj)
1113 (setf prev-obj obj)
1114 write-size))))
1115 finally
1116 (let ((total-size (file-position stream))
1117 (sum (+ symbols-size conses-size funobjs-size strings-size
1118 simple-vectors-size code-vectors-size pad-size)))
1119 (format t "~&;;~%;; ~D symbols (~D gensyms) (~,1F KB ~~ ~,1F%), ~D conses (~,1F KB ~~ ~,1F%),
1120 ~D funobjs (~,1F KB ~~ ~,1F%), ~D strings (~,1F KB ~~ ~,1F%),
1121 ~D simple-vectors (~,1F KB ~~ ~,1F%), ~D code-vectors (~,1F KB ~~ ~,1F%).
1122 ~,1F KB (~,1F%) of padding.
1123 In sum this accounts for ~,1F%, or ~D bytes.~%;;~%"
1124 symbols-numof gensyms-numof
1125 (/ symbols-size 1024) (/ (* symbols-size 100) total-size)
1126 conses-numof (/ conses-size 1024) (/ (* conses-size 100) total-size)
1127 funobjs-numof (/ funobjs-size 1024) (/ (* funobjs-size 100) total-size)
1128 strings-numof (/ strings-size 1024) (/ (* strings-size 100) total-size)
1129 simple-vectors-numof (/ simple-vectors-size 1024) (/ (* simple-vectors-size 100) total-size)
1130 code-vectors-numof (/ code-vectors-size 1024) (/ (* code-vectors-size 100) total-size)
1131 (/ pad-size 1024) (/ (* pad-size 100) total-size)
1132 (/ (* sum 100) total-size)
1133 sum)))))
1135 (defun intern-movitz-symbol (name)
1136 (assert (not (eq (symbol-package name) (find-package :common-lisp)))
1137 (name)
1138 "Trying to movitz-intern a symbol in the Common-Lisp package: ~S" name)
1139 (or (gethash name (image-oblist *image*))
1140 (let ((symbol (make-movitz-symbol name)))
1141 (when (get name :setf-placeholder)
1142 (setf (movitz-symbol-flags symbol) '(:setf-placeholder)
1143 (movitz-symbol-value symbol) (movitz-read (get name :setf-placeholder))))
1144 (setf (gethash name (image-oblist *image*)) symbol)
1145 (when (symbol-package name)
1146 (let ((p (gethash (symbol-package name) (image-read-map-hash *image*))))
1147 (when p
1148 (setf (movitz-symbol-package symbol) p))))
1149 (when (or (eq 'muerte.cl:t name)
1150 (keywordp (translate-program name :muerte.cl :cl)))
1151 (pushnew :constant-variable (movitz-symbol-flags symbol))
1152 (setf (movitz-symbol-value symbol)
1153 (movitz-read (translate-program (symbol-value (translate-program name :muerte.cl :cl))
1154 :cl :muerte.cl))))
1155 symbol)))
1157 (defun make-packages-hash (&optional (*image* *image*))
1158 (let ((lisp-to-movitz-package (make-hash-table :test #'eq))
1159 (packages-hash (make-hash-table :test #'equal :size 23)))
1160 (labels ((movitz-package-name (name &optional symbol)
1161 (declare (ignore symbol))
1162 (cond
1163 ((string= (string :keyword) name)
1164 name)
1165 ((and (< 7 (length name))
1166 (string= (string 'muerte.) name :end2 7))
1167 (subseq name 7))
1168 (t #+ignore (warn "Package ~S ~@[for symbol ~S ~]is not a Movitz package."
1169 name symbol)
1170 name)))
1171 (ensure-package (package-name lisp-package &optional context)
1172 (assert (not (member (package-name lisp-package)
1173 #+allegro '(excl common-lisp sys aclmop)
1174 #-allegro '(common-lisp)
1175 :test #'string=)) ()
1176 "I don't think you really want to dump the package ~A ~@[for symbol ~S~] with Movitz."
1177 lisp-package context)
1178 (setf (gethash lisp-package lisp-to-movitz-package)
1179 (or (gethash package-name packages-hash nil)
1180 (let* ((nicks (mapcar #'movitz-package-name (package-nicknames lisp-package)))
1181 (p (funcall 'muerte::make-package-object
1182 :name package-name
1183 :shadowing-symbols-list (package-shadowing-symbols lisp-package)
1184 :external-symbols (make-hash-table :test #'equal)
1185 :internal-symbols (make-hash-table :test #'equal)
1186 :nicknames nicks
1187 :use-list (mapcar #'(lambda (up)
1188 (ensure-package (movitz-package-name (package-name up))
1189 up context))
1190 (package-use-list lisp-package)))))
1191 (setf (gethash package-name packages-hash) p)
1192 (dolist (nick nicks)
1193 (setf (gethash nick packages-hash) p))
1194 p)))))
1195 (let ((movitz-cl-package (ensure-package (symbol-name :common-lisp)
1196 (find-package :muerte.common-lisp))))
1197 (setf (gethash "NIL" (funcall 'muerte:package-object-external-symbols movitz-cl-package))
1198 nil))
1199 (loop for symbol being the hash-key of (image-oblist *image*)
1200 as lisp-package = (symbol-package symbol)
1201 as package-name = (and lisp-package
1202 (movitz-package-name (package-name lisp-package) symbol))
1203 when package-name
1204 do (let* ((movitz-package (ensure-package package-name lisp-package symbol)))
1205 (multiple-value-bind (symbol status)
1206 (find-symbol (symbol-name symbol) (symbol-package symbol))
1207 (ecase status
1208 (:internal
1209 (setf (gethash (symbol-name symbol)
1210 (funcall 'muerte:package-object-internal-symbols movitz-package))
1211 symbol))
1212 (:external
1213 ;; (warn "putting external ~S in ~S" symbol package-name)
1214 (setf (gethash (symbol-name symbol)
1215 (funcall 'muerte:package-object-external-symbols movitz-package))
1216 symbol))
1217 (:inherited
1218 (warn "inherited symbol: ~S" symbol))))))
1219 ;;; (warn "PA: ~S" packages-hash)
1220 (let ((movitz-packages (movitz-read packages-hash)))
1221 (maphash (lambda (lisp-package movitz-package)
1222 (setf (gethash lisp-package (image-read-map-hash *image*))
1223 (movitz-read movitz-package)))
1224 lisp-to-movitz-package)
1225 (setf (slot-value (movitz-run-time-context-null-symbol (image-run-time-context *image*))
1226 'package)
1227 (movitz-read (ensure-package (string :common-lisp) :muerte.common-lisp)))
1228 (loop for symbol being the hash-key of (image-oblist *image*)
1229 as lisp-package = (symbol-package symbol)
1230 as package-name = (and lisp-package
1231 (movitz-package-name (package-name lisp-package) symbol))
1232 ;;; do (when (string= symbol :method)
1233 ;;; (warn "XXXX ~S ~S ~S" symbol lisp-package package-name))
1234 when package-name
1235 do (let* ((movitz-package (ensure-package package-name lisp-package symbol)))
1236 (setf (movitz-symbol-package (movitz-read symbol))
1237 (movitz-read movitz-package))))
1238 movitz-packages))))
1241 (defun run-time-context-find-slot (offset)
1242 "Return the name of the run-time-context slot located at offset."
1243 (dolist (slot-name (bt:binary-record-slot-names 'movitz-run-time-context))
1244 (when (= offset (bt:slot-offset 'movitz-run-time-context slot-name))
1245 (return slot-name))))
1247 #+ia-x86
1248 (defun comment-instruction (instruction funobj pc)
1249 "Return a list of strings that comments on INSTRUCTION."
1250 (loop for operand in (ia-x86::instruction-operands instruction)
1251 when (and (typep operand 'ia-x86::operand-indirect-register)
1252 (eq 'ia-x86::edi (ia-x86::operand-register operand))
1253 (not (ia-x86::operand-register2 operand))
1254 (= 1 (ia-x86::operand-scale operand))
1255 (run-time-context-find-slot (ia-x86::operand-offset operand))
1256 (not (typep instruction 'ia-x86-instr::lea)))
1257 collect (format nil "<Global slot ~A>"
1258 (run-time-context-find-slot (ia-x86::operand-offset operand)))
1259 when (and (typep operand 'ia-x86::operand-indirect-register)
1260 (eq 'ia-x86::edi (ia-x86::operand-register operand))
1261 (typep instruction 'ia-x86-instr::lea)
1262 (or (not (ia-x86::operand-register2 operand))
1263 (eq 'ia-x86::edi (ia-x86::operand-register2 operand))))
1264 collect (let ((x (+ (* (ia-x86::operand-scale operand)
1265 (image-nil-word *image*))
1266 (ia-x86::operand-offset operand)
1267 (ecase (ia-x86::operand-register2 operand)
1268 (ia-x86::edi (image-nil-word *image*))
1269 ((nil) 0)))))
1270 (case (ldb (byte 3 0) x)
1271 (#.(tag :character)
1272 (format nil "Immediate ~D (char ~S)"
1273 x (code-char (ldb (byte 8 8) x))))
1274 (#.(mapcar 'tag +fixnum-tags+)
1275 (format nil "Immediate ~D (fixnum ~D #x~X)"
1277 (truncate x +movitz-fixnum-factor+)
1278 (truncate x +movitz-fixnum-factor+)))
1279 (t (format nil "Immediate ~D" x))))
1280 when (and funobj
1281 (typep operand 'ia-x86::operand-indirect-register)
1282 (eq 'ia-x86::esi (ia-x86::operand-register operand))
1283 (member (ia-x86::operand-register2 operand) '(ia-x86::edi nil))
1284 (= 1 (ia-x86::operand-scale operand))
1285 #+ignore (= (mod (slot-offset 'movitz-funobj 'constant0) 4)
1286 (mod (ia-x86::operand-offset operand) 4))
1287 (<= 12 (ia-x86::operand-offset operand)))
1288 collect (format nil "~A"
1289 (nth (truncate (- (+ (ia-x86::operand-offset operand)
1290 (if (eq 'ia-x86::edi (ia-x86::operand-register2 operand))
1291 (image-nil-word *image*)
1293 (slot-offset 'movitz-funobj 'constant0))
1295 (movitz-funobj-const-list funobj)))
1296 when (and funobj
1297 (typep operand 'ia-x86::operand-indirect-register)
1298 (eq 'ia-x86::esi (ia-x86::operand-register2 operand))
1299 (eq 'ia-x86::edi (ia-x86::operand-register operand))
1300 (<= 12 (ia-x86::operand-offset operand)))
1301 collect (format nil "~A" (nth (truncate (- (+ (ia-x86::operand-offset operand)
1302 (* (ia-x86::operand-scale operand)
1303 (image-nil-word *image*)))
1304 (slot-offset 'movitz-funobj 'constant0))
1306 (movitz-funobj-const-list funobj)))
1307 when (typep operand 'ia-x86::operand-rel-pointer)
1308 collect (let* ((x (+ pc
1309 (imagpart (ia-x86::instruction-original-datum instruction))
1310 (length (ia-x86:instruction-prefixes instruction))
1311 (ia-x86::operand-offset operand)))
1312 (label (and funobj (car (find x (movitz-funobj-symtab funobj) :key #'cdr)))))
1313 (if label
1314 (format nil "branch to ~S at ~D" label x)
1315 (format nil "branch to ~D" x)))
1316 when (and (typep operand 'ia-x86::operand-immediate)
1317 (<= #x100 (ia-x86::operand-value operand) #x10000)
1318 (= (tag :character) (mod (ia-x86::operand-value operand) 256)))
1319 collect (format nil "#\\~C" (code-char (truncate (ia-x86::operand-value operand) 256)))
1320 when (and (typep operand 'ia-x86::operand-immediate)
1321 (zerop (mod (ia-x86::operand-value operand)
1322 +movitz-fixnum-factor+)))
1323 collect (format nil "#x~X" (truncate (ia-x86::operand-value operand)
1324 +movitz-fixnum-factor+))))
1326 (defun movitz-disassemble (name &rest args &key ((:image *image*) *image*) &allow-other-keys)
1327 (let* ((funobj (or (movitz-env-named-function name)
1328 (error "~S has no function definition." name))))
1329 (declare (special *image*))
1330 (apply #'movitz-disassemble-funobj funobj :name name args)))
1332 (defun movitz-assembly (name &optional (*image* *image*))
1333 (let* ((funobj (movitz-env-named-function name)))
1334 (declare (special *image*))
1335 (format t "~{~A~%~}" (movitz-funobj-symbolic-code funobj))))
1337 (defun movitz-disassemble-toplevel (module)
1338 (let ((funobj (car (find module (image-load-time-funobjs *image*) :key #'second))))
1339 (assert funobj (module)
1340 "No load funobj found for module ~S." module)
1341 (movitz-disassemble-funobj funobj :name module)))
1343 (defun movitz-disassemble-method (name lambda-list &optional qualifiers)
1344 (let* ((gf (or (movitz-env-named-function name)
1345 (error "No function named ~S." name)))
1346 (specializing-lambda-list
1347 (subseq lambda-list 0
1348 (position-if (lambda (x)
1349 (and (symbolp x)
1350 (char= #\& (char (string x) 0))))
1351 lambda-list)))
1352 (specializers (mapcar #'muerte::find-specializer
1353 (mapcar (lambda (x)
1354 (if (consp x)
1355 (second x)
1356 'muerte.cl::t))
1357 specializing-lambda-list)))
1358 (method (muerte::movitz-find-method gf qualifiers specializers))
1359 (funobj (muerte::movitz-slot-value method 'muerte::function))
1360 (*print-base* 16))
1361 (movitz-disassemble-funobj funobj)))
1363 (defparameter *recursive-disassemble-remember-funobjs* nil)
1365 (defun movitz-foo (funobj &key (name (movitz-funobj-name funobj)) ((:image *image*) *image*)
1366 (recursive t))
1367 (coerce (movitz-vector-symbolic-data (movitz-funobj-code-vector funobj))
1368 'list))
1370 #-ia-x86
1371 (defun movitz-disassemble-funobj (funobj &key (name (movitz-funobj-name funobj)) ((:image *image*) *image*)
1372 (recursive t))
1373 (let ((code (coerce (movitz-vector-symbolic-data (movitz-funobj-code-vector funobj))
1374 'list))
1375 (entry-points (loop for slot in '(code-vector%1op code-vector%2op code-vector%3op)
1376 for entry-arg-count upfrom 1
1377 for entry = (slot-value funobj slot)
1378 when (and (consp entry)
1379 (eq funobj (cdr entry)))
1380 collect (cons (car entry)
1381 entry-arg-count))))
1382 (let ((*print-case* :downcase))
1383 (format t "~&;; Movitz Disassembly of ~A:
1384 ;; ~D Constant~:P~@[: ~A~].
1385 ~:{~4D: ~16<~{ ~2,'0X~}~;~> ~A~@[ ;~{ ~A~}~]~%~}"
1386 (movitz-print (or (movitz-funobj-name funobj) name))
1387 (length (movitz-funobj-const-list funobj))
1388 (movitz-funobj-const-list funobj)
1389 (loop with pc = 0
1390 for (data . instruction) in (asm:disassemble-proglist code :symtab (movitz-funobj-symtab funobj)
1391 :collect-data t)
1392 when (assoc pc entry-points)
1393 collect (list pc nil
1394 (format nil " => Entry-point for ~D arguments <=" (cdr (assoc pc entry-points)))
1395 nil)
1396 when (let ((x (find pc (movitz-funobj-symtab funobj) :key #'cdr)))
1397 (when x (list pc (list (format nil " ~A" (car x))) "" nil)))
1398 collect it
1399 collect (list pc data instruction nil)
1400 do (incf pc (length data))))))
1401 (when recursive
1402 (let ((*recursive-disassemble-remember-funobjs*
1403 (cons funobj *recursive-disassemble-remember-funobjs*)))
1404 (loop for x in (movitz-funobj-const-list funobj)
1405 do (when (and (typep x '(and movitz-funobj (not movitz-funobj-standard-gf)))
1406 (not (member x *recursive-disassemble-remember-funobjs*)))
1407 (push x *recursive-disassemble-remember-funobjs*)
1408 (terpri)
1409 (movitz-disassemble-funobj x))))))
1413 #+ia-x86
1414 (defun movitz-disassemble-funobj (funobj &key (name (movitz-funobj-name funobj)) ((:image *image*) *image*)
1415 (recursive t))
1416 (let* ((code-vector (movitz-funobj-code-vector funobj))
1417 (code (map 'vector #'identity
1418 (movitz-vector-symbolic-data code-vector)))
1419 (code-position 0)
1420 (entry-points (map 'list #'identity (subseq code (movitz-vector-fill-pointer code-vector)))))
1421 (format t "~&;; Movitz Disassembly of ~A:~@[
1422 ;; ~D Constants: ~A~]
1423 ~:{~4D: ~16<~{ ~2,'0X~}~;~> ~A~@[ ;~{ ~A~}~]~%~}"
1424 (movitz-print (or (movitz-funobj-name funobj) name))
1425 (length (movitz-funobj-const-list funobj))
1426 (movitz-funobj-const-list funobj)
1427 (loop
1428 for pc = 0 then code-position
1429 for instruction = (ia-x86:decode-read-octet
1430 #'(lambda ()
1431 (when (< code-position
1432 (movitz-vector-fill-pointer code-vector))
1433 (prog1
1434 (aref code code-position)
1435 (incf code-position)))))
1436 for cbyte = (and instruction
1437 (ia-x86::instruction-original-datum instruction))
1438 until (null instruction)
1439 when (let ((x (find pc (movitz-funobj-symtab funobj) :key #'cdr)))
1440 (when x (list pc (list (format nil " ~S" (car x))) "" nil)))
1441 collect it
1442 when (some (lambda (x)
1443 (and (plusp pc) (= pc x)))
1444 entry-points)
1445 collect (list pc nil
1446 (format nil " => Entry-point for ~D arguments <="
1447 (1+ (position-if (lambda (x)
1448 (= pc x))
1449 entry-points)))
1450 nil)
1451 collect (list pc
1452 (ia-x86::cbyte-to-octet-list cbyte)
1453 instruction
1454 (comment-instruction instruction funobj pc)))))
1455 (when recursive
1456 (let ((*recursive-disassemble-remember-funobjs*
1457 (cons funobj *recursive-disassemble-remember-funobjs*)))
1458 (loop for x in (movitz-funobj-const-list funobj)
1459 do (when (and (typep x '(and movitz-funobj (not movitz-funobj-standard-gf)))
1460 (not (member x *recursive-disassemble-remember-funobjs*)))
1461 (push x *recursive-disassemble-remember-funobjs*)
1462 (terpri)
1463 (movitz-disassemble-funobj x)))))
1464 (values))
1466 #-ia-x86
1467 (defun movitz-disassemble-primitive (name &optional (*image* *image*))
1468 (let* ((code-vector (cond
1469 ((slot-exists-p (image-run-time-context *image*) name)
1470 (slot-value (image-run-time-context *image*) name))
1471 (t (movitz-symbol-value (movitz-read name)))))
1472 (code (coerce (movitz-vector-symbolic-data code-vector)
1473 'list)))
1474 (format t "~&;; Movitz disassembly of ~S:
1475 ~:{~4D: ~16<~{ ~2,'0X~}~;~> ~A~@[ ;~{ ~A~}~]~%~}"
1476 name
1477 (loop with pc = 0
1478 for (data . instruction) in (asm:disassemble-proglist code :collect-data t)
1479 collect (list pc
1480 data
1481 instruction
1482 nil #+ignore (comment-instruction instruction nil pc))
1483 do (incf pc (length data))))
1484 (values)))
1486 #+ia-x86
1487 (defun movitz-disassemble-primitive (name &optional (*image* *image*))
1488 (let* ((code-vector (cond
1489 ((slot-exists-p (image-run-time-context *image*) name)
1490 (slot-value (image-run-time-context *image*) name))
1491 (t (movitz-symbol-value (movitz-read name)))))
1492 (code (map 'vector #'identity
1493 (movitz-vector-symbolic-data code-vector)))
1494 (code-position 0))
1495 (format t "~&;; Movitz disassembly of ~S:
1496 ~:{~4D: ~16<~{ ~2,'0X~}~;~> ~A~@[ ;~{ ~A~}~]~%~}"
1497 name
1498 (loop
1499 for pc = 0 then code-position
1500 for instruction = (ia-x86:decode-read-octet
1501 #'(lambda ()
1502 (when (< code-position (length code))
1503 (prog1
1504 (aref code code-position)
1505 (incf code-position)))))
1506 until (null instruction)
1507 for cbyte = (ia-x86::instruction-original-datum instruction)
1508 collect (list pc
1509 (ia-x86::cbyte-to-octet-list cbyte)
1510 instruction
1511 (comment-instruction instruction nil pc))))
1512 (values)))
1514 (defmethod image-read-intern-constant ((*image* symbolic-image) expr)
1515 (typecase expr
1516 (string
1517 (or (gethash expr (image-string-constants *image*))
1518 (setf (gethash expr (image-string-constants *image*))
1519 (movitz-read expr))))
1520 (cons
1521 (or (gethash expr (image-cons-constants *image*))
1522 (setf (gethash expr (image-cons-constants *image*))
1523 (movitz-read expr))))
1524 (t (movitz-read expr))))
1526 ;;; "Reader"
1528 (defmethod image-lisp-to-movitz-object ((image symbolic-image) lisp-object)
1529 (gethash lisp-object (image-read-map-hash image)))
1531 (defmethod (setf image-lisp-to-movitz-object) (movitz-object (image symbolic-image) lisp-object)
1532 (setf (gethash movitz-object (image-inverse-read-map-hash image)) lisp-object
1533 (gethash lisp-object (image-read-map-hash image)) movitz-object))
1535 (defmethod image-movitz-to-lisp-object ((image symbolic-image) movitz-object)
1536 (gethash movitz-object (image-inverse-read-map-hash image)))
1538 (defmacro with-movitz-read-context (options &body body)
1539 (declare (ignore options))
1540 `(let ((*movitz-reader-clean-map*
1541 (if (boundp '*movitz-reader-clean-map*)
1542 (symbol-value '*movitz-reader-clean-map*)
1543 (make-hash-table :test #'eq))))
1544 (declare (special *movitz-reader-clean-map*))
1545 ,@body))
1547 (defun movitz-read (expr &optional re-read)
1548 "Map native lisp data to movitz-objects. Makes sure that when two EXPR are EQ, ~@
1549 the Movitz objects are also EQ, under the same image."
1550 (declare (optimize (debug 3) (speed 0)))
1551 (with-movitz-read-context ()
1552 (when (typep expr 'movitz-object)
1553 (return-from movitz-read expr))
1554 (or (and (not re-read)
1555 (let ((old-object (image-lisp-to-movitz-object *image* expr)))
1556 (when (and old-object (not (gethash old-object *movitz-reader-clean-map*)))
1557 (update-movitz-object old-object expr)
1558 (setf (gethash old-object *movitz-reader-clean-map*) t))
1559 old-object))
1560 (setf (image-lisp-to-movitz-object *image* expr)
1561 (etypecase expr
1562 (null *movitz-nil*)
1563 ((member t) (movitz-read 'muerte.cl:t))
1564 ((eql unbound) (make-instance 'movitz-unbound-value))
1565 (symbol (intern-movitz-symbol expr))
1566 (integer (make-movitz-integer expr))
1567 (character (make-movitz-character expr))
1568 (string (or (gethash expr (image-string-constants *image*))
1569 (setf (gethash expr (image-string-constants *image*))
1570 (make-movitz-string expr))))
1571 (vector (make-movitz-vector (length expr)
1572 :element-type (array-element-type expr)
1573 :initial-contents expr))
1574 (cons
1575 (or (let ((old-cons (gethash expr (image-cons-constants *image*))))
1576 (when old-cons
1577 (update-movitz-object old-cons expr)
1578 old-cons))
1579 (setf (gethash expr (image-cons-constants *image*))
1580 (if (eq '#0=#:error (ignore-errors (when (not (list-length expr)) '#0#)))
1581 (multiple-value-bind (unfolded-expr cdr-index)
1582 (unfold-circular-list expr)
1583 (let ((result (movitz-read unfolded-expr)))
1584 (setf (movitz-last-cdr result)
1585 (movitz-nthcdr cdr-index result))
1586 result))
1587 (make-movitz-cons (movitz-read (car expr))
1588 (movitz-read (cdr expr)))))))
1589 (hash-table
1590 (make-movitz-hash-table expr))
1591 (ratio
1592 (make-instance 'movitz-ratio
1593 :value expr))
1594 (structure-object
1595 (let ((slot-descriptions (gethash (type-of expr)
1596 (image-struct-slot-descriptions *image*)
1597 nil)))
1598 (unless slot-descriptions
1599 (error "Don't know how to movitz-read struct: ~S" expr))
1600 (let ((movitz-object (make-instance 'movitz-struct
1601 :class (muerte::movitz-find-class (type-of expr))
1602 :length (length slot-descriptions))))
1603 (setf (image-lisp-to-movitz-object *image* expr) movitz-object)
1604 (setf (slot-value movitz-object 'slot-values)
1605 (mapcar #'(lambda (slot)
1606 (movitz-read (slot-value expr (if (consp slot) (car slot) slot))))
1607 slot-descriptions))
1608 movitz-object)))
1609 (float ; XXX
1610 (movitz-read (rationalize expr))))))))
1614 (defun movitz-make-upload-form (object &optional (quotep t))
1615 "Not completed."
1616 (typecase object
1617 ((or movitz-null null) "()")
1618 (cons
1619 (format nil "(list~{ ~A~})"
1620 (mapcar #'movitz-make-upload-form object)))
1621 (movitz-cons
1622 (format nil "(list~{ ~A~})"
1623 (mapcar #'movitz-make-upload-form (movitz-print object))))
1624 (movitz-funobj
1625 (format nil "(internal:make-funobj :name ~A :constants ~A :code-vector ~A)"
1626 (movitz-make-upload-form (movitz-funobj-name object))
1627 (movitz-make-upload-form (movitz-funobj-const-list object))
1628 (movitz-print (movitz-funobj-code-vector object))))
1629 (movitz-symbol
1630 (let ((package (movitz-symbol-package object)))
1631 (cond
1632 ((eq *movitz-nil* package)
1633 (if (member :setf-placeholder (movitz-symbol-flags object))
1634 (format nil "(internal:setf-intern ~A)"
1635 (movitz-make-upload-form (movitz-symbol-value object)))
1636 (format nil "~:[~;'~]#:~A" quotep (movitz-print object))))
1637 (t (check-type package movitz-struct)
1638 (assert (eq (movitz-struct-class package)
1639 (muerte::movitz-find-class 'muerte::package-object)))
1640 (let ((package-name (intern (movitz-print (first (movitz-struct-slot-values package))))))
1641 (case package-name
1642 (keyword (format nil ":~A" (movitz-print object)))
1643 (common-lisp (format nil "~:[~;'~]~A" quotep (movitz-print object)))
1644 (t (format nil "~:[~;'~]~A:~A" quotep package-name (movitz-print object)))))))))
1645 (movitz-basic-vector
1646 (case (movitz-vector-element-type object)
1647 (:character (format nil "\"~A\"" (movitz-print object)))
1648 (t (movitz-print object))))
1649 (t (format nil "~A" (movitz-print object)))))
1652 (defun movitz-upload-function (name &optional (destination :bochs) (verbose nil))
1653 (unless (stringp destination)
1654 (setf destination
1655 (ecase destination
1656 (:kayak "fe80::240:f4ff:fe36:6f02%xl0")
1657 (:decpc "fe80::240:5ff:fe18:66d7%xl0")
1658 (:bochs "fe80::240:5ff:fe18:66d8%xl0"))))
1659 (let ((funobj (movitz-env-symbol-function name))
1660 (*print-readably* t)
1661 (*print-pretty* nil)
1662 (*print-base* 16)
1663 (*print-radix* nil))
1664 (let ((command (format nil "(internal:install-function ~A (list~{ ~A~}) ~W)"
1665 (movitz-make-upload-form (movitz-read name))
1666 (mapcar #'movitz-make-upload-form (movitz-funobj-const-list funobj))
1667 (movitz-print (movitz-funobj-code-vector funobj)))))
1668 (when verbose
1669 (pprint command) (terpri) (force-output))
1670 command
1671 #+allegro (if destination
1672 (excl::run-shell-command (format nil "./udp6-send.py ~A 1 ~S" destination command))
1673 command))))
1676 ;;; "Printer"
1678 (defun movitz-print (expr)
1679 "Find the host lisp object equivalent to the Movitz object expr."
1680 (etypecase expr
1681 (integer expr)
1682 (symbol expr)
1683 (array expr)
1684 (cons (mapcar #'movitz-print expr))
1685 ((or (satisfies movitz-null) movitz-run-time-context) nil)
1686 (movitz-unbound-value 'unbound)
1687 (movitz-fixnum
1688 (movitz-fixnum-value expr))
1689 (movitz-std-instance expr)
1690 (movitz-struct expr)
1691 (movitz-heap-object
1692 (or (image-movitz-to-lisp-object *image* expr)
1693 (error "Unknown Movitz object: ~S" expr)))))
1695 (defmethod make-toplevel-funobj ((*image* symbolic-image))
1696 (declare (special *image*))
1697 (let ((toplevel-code (loop for (funobj) in (image-load-time-funobjs *image*)
1698 collect `(muerte::simple-funcall ,funobj)))
1699 ;; We need toplevel-funobj's identity in the code below.
1700 (toplevel-funobj (make-instance 'movitz-funobj-pass1)))
1701 (make-compiled-funobj 'muerte::toplevel-function ()
1702 '((muerte::without-function-prelude))
1703 `(muerte.cl:progn
1704 (muerte::with-inline-assembly (:returns :nothing)
1705 (:cli)
1706 (:cld) ; clear direction flag => "normal" register GC roots.
1708 (:movw ,(1- (* 8 5)) (:esp -6))
1709 (:movl ,(+ (movitz-read-and-intern
1710 'muerte::*initial-segment-descriptor-table* 'word)
1711 (image-ds-segment-base *image*))
1712 :ecx)
1713 (:movl (:ecx ,(bt:slot-offset 'movitz-symbol 'value))
1714 :ecx)
1715 (:addl ,(+ (bt:slot-offset 'movitz-basic-vector 'data)
1716 (image-ds-segment-base *image*))
1717 :ecx)
1718 (:movl :ecx (:esp -4))
1719 (:lgdt (:esp -6))
1721 ;; Move to new CS
1722 (:pushl ,(ash (* 3 8) 0)) ; push segment selector
1723 (:call (:pc+ 0)) ; push EIP
1724 jmp-base
1725 (:subl '(:funcall ,(lambda (base dest)
1726 (+ (image-cs-segment-base *image*) (- dest) base))
1728 'jmp-base 'jmp-destination)
1729 (:esp))
1730 (:jmp-segment (:esp))
1731 jmp-destination
1733 (:movw ,(* 4 8) :cx)
1734 (:movw :cx :ds)
1735 (:movw :cx :es)
1736 (:movw :cx :fs)
1737 (:movw :cx :ss)
1738 (:movw ,(* 2 8) :cx)
1739 (:movw :cx :gs) ; physical context segment
1741 (:movl ,(image-nil-word *image*) :edi)
1742 (:globally (:movl (:edi (:edi-offset stack-top)) :esp))
1744 (:pushl #x37ab7378)
1745 (:pushl #x37ab7378)
1746 (:pushl 0)
1747 (:pushl 0)
1748 (:movl :esp :ebp)
1750 (:movl '(:funcall ,(lambda () (movitz-intern toplevel-funobj)))
1751 :esi)
1752 (:pushl :esi)
1753 (:pushl :edi)
1754 (:cmpl #x2badb002 :eax)
1755 (:jne 'no-multiboot)
1756 (:movl ,(movitz-read-and-intern 'muerte::*multiboot-data* 'word)
1757 :eax)
1758 ;; (:compile-form (:result-mode :eax) 'muerte::*multiboot-data*)
1759 ;; (:shll ,+movitz-fixnum-shift+ :ebx)
1760 (:movl :ebx (:eax ,(bt:slot-offset 'movitz-symbol 'value)))
1761 no-multiboot)
1762 ;; Check that the stack works..
1763 ;;; (:pushl #xabbabeef)
1764 ;;; (:popl :eax)
1765 ;;; (:cmpl #xabbabeef :eax)
1766 ;;; (:jne '(:sub-program (stack-doesnt-work)
1767 ;;; (:movl :ebp :eax)
1768 ;;; (:movl #xb8020 :ebx)
1769 ;;; ,@(mkasm-write-word-eax-ebx)
1770 ;;; (:movl (:edi -1) :eax)
1771 ;;; (:movl #xb8040 :ebx)
1772 ;;; ,@(mkasm-write-word-eax-ebx)
1773 ;;; (:jmp (:pc+ -2)))))
1775 ,@toplevel-code
1776 (muerte::halt-cpu))
1777 nil t :funobj toplevel-funobj)))
1779 (defun mkasm-write-word-eax-ebx ()
1780 (let ((loop-label (make-symbol "write-word-loop"))
1781 (l1 (make-symbol "write-word-l1"))
1782 (l2 (make-symbol "write-word-l2"))
1783 (l3 (make-symbol "write-word-l3"))
1784 (l4 (make-symbol "write-word-l4")))
1785 `(;; (:compile-two-forms (:eax :ebx) ,word ,dest)
1786 (:movl :eax :edx)
1788 ;; (:shrl #.los0::+movitz-fixnum-shift+ :ebx)
1789 (:movb 2 :cl)
1791 ((:gs-override) :movl #x07000700 (:ebx 0))
1792 ((:gs-override) :movl #x07000700 (:ebx 4))
1793 ((:gs-override) :movl #x07000700 (:ebx 8))
1794 ((:gs-override) :movl #x07000700 (:ebx 12))
1795 ,loop-label
1797 (:andl #x0f0f0f0f :eax)
1798 (:addl #x30303030 :eax)
1800 (:cmpb #x39 :al) (:jle ',l1) (:addb 7 :al)
1801 ,l1 ((:gs-override) :movb :al (14 :ebx)) ; 8
1802 (:cmpb #x39 :ah) (:jle ',l2) (:addb 7 :ah)
1803 ,l2 ((:gs-override) :movb :ah (10 :ebx)) ; 6
1805 (:shrl 16 :eax)
1807 (:cmpb #x39 :al) (:jle ',l3) (:addb 7 :al)
1808 ,l3 ((:gs-override) :movb :al (6 :ebx)) ; 4
1809 (:cmpb #x39 :ah) (:jle ',l4) (:addb 7 :ah)
1810 ,l4 ((:gs-override) :movb :ah (2 :ebx)) ; 2
1812 (:movl :edx :eax)
1813 (:shrl 4 :eax)
1814 (:subl 2 :ebx)
1815 (:decb :cl)
1816 (:jnz ',loop-label))))