16)
(define-integrable maximum-block-offset
- ;; PC always aligned on 32-bit boundary. Use the extra bit.
- (- (expt 2 (1+ block-offset-width)) 4))
+ ;; Starting PC always aligned on 64-bit boundary.
+ ;; - One bit is reserved for the continuation bit.
+ ;; - Three bits are always zero.
+ (- (expt 2 (+ (- 3 1) block-offset-width)) 8))
(define (block-offset->bit-string offset start?)
- (assert (zero? (remainder offset 4)))
+ (assert (zero? (remainder offset 8)))
(unsigned-integer->bit-string block-offset-width
- (+ (shift-left (quotient offset 4) 1)
+ (+ (shift-left (quotient offset 8) 1)
(if start? 0 1))))
;;; Machine dependent instruction order
(temp (allocate-temporary-register! 'GENERAL))
(manifest-type type-code:manifest-closure)
(manifest-size (closure-manifest-size size))
- (Free regnum:free-pointer))
+ (Free regnum:free-pointer)
+ ;; 1 for manifest, 1 for padding & format word, 1 for PC offset.
+ (offset 3))
(LAP ,@(load-tagged-immediate manifest-type manifest-size temp)
(STR X ,temp (POST+ ,Free (& 8)))
- ,@(generate-closure-entry label 1 min max 1 temp)
+ ,@(generate-closure-entry label 1 min max offset temp)
;; Free now points at the entry. Save it in target.
,@(register->register-transfer Free target)
;; Bump Free to point at the last component, one word before
(temp (allocate-temporary-register! 'GENERAL))
(manifest-type type-code:manifest-closure)
(manifest-size (multiclosure-manifest-size nentries size))
- ;; 8 for manifest, 8 for padding & format word, 8 for PC offset.
- (offset0 #x18)
+ ;; 1 for manifest, 1 for padding & format word, 1 for PC offset.
+ (offset0 3)
(Free regnum:free-pointer))
(define (generate-primary-entry entry)
(let ((label (car entry)) (min (cadr entry)) (max (caddr entry)))
\f
(define (generate-closure-entry label padding min max offset temp)
(let* ((label* (rtl-procedure/external-label (label->object label)))
- (code-word (make-procedure-code-word min max))
+ (format (make-closure-padded-format padding min max offset))
(Free regnum:free-pointer))
- ;; Could avoid zeroing the padding if we don't need it, but there's
- ;; no advantage.
- (define (padded-word)
- ;; padding(32) || code-word(16) || offset(16)
- (case endianness
- ((BIG)
- (bitwise-ior (shift-left padding 32)
- (bitwise-ior (shift-left code-word 16)
- offset)))
- ((LITTLE)
- (bitwise-ior padding
- (bitwise-ior (shift-left code-word 32)
- (shift-left offset 48))))
- (else
- (error "Unknown endianness:" endianness))))
(assert (not (= temp regnum:scratch-0)))
- (LAP ,@(load-unsigned-immediate temp (padded-word))
+ (LAP ,@(load-unsigned-immediate temp format)
(STR X ,temp (POST+ ,Free (& 8)))
;; Set temp := label - 8.
(ADR X ,temp (@PCR (- ,label* 8) ,regnum:scratch-0))
;; Store the PC offset.
(STR X ,temp (POST+ ,Free (& 8))))))
+(define (make-closure-padded-format padding min max offset)
+ ;; Entries are 64-bit-aligned, so offset is units of Scheme objects,
+ ;; limited to 15 bits. Low bit of the block offset is 0 because it
+ ;; always refers to the start of the block, not to a continuation
+ ;; offset.
+ (assert (< offset (expt 2 15)) "Your closure has too many entries.")
+ (let ((word
+ (bitwise-ior (shift-left offset (+ 16 1))
+ (make-procedure-code-word min max))))
+ ;; Padding (or entry count) comes first in memory.
+ (case endianness
+ ((BIG) (bitwise-ior padding (shift-left word 32)))
+ ((LITTLE) (bitwise-ior (shift-left word 32) padding))
+ (else (error "Unknown endianness:" endianness)))))
+
(define (closure-manifest-size size)
(multiclosure-manifest-size 1 size))
bool
read_cc_entry_offset (cc_entry_offset_t * ceo, insn_t * address)
{
+ const size_t units = ((sizeof (SCHEME_OBJECT)) / (sizeof (insn_t)));
+ assert (units == 2);
uint32_t word = (address[-3]);
uint16_t n = ((word & BLOCK_OFFSET_MASK) >> BLOCK_OFFSET_SHIFT);
- (ceo->offset) = (n >> 1);
+ /* Block offsets are stored in units of Scheme objects. */
+ (ceo->offset) = (units * (n >> 1));
(ceo->continued_p) = ((n & 1) != 0);
return (false);
}
bool
write_cc_entry_offset (cc_entry_offset_t * ceo, insn_t * address)
{
+ const size_t units = ((sizeof (SCHEME_OBJECT)) / (sizeof (insn_t)));
+ assert (units == 2);
+ assert (((ceo->offset) % units) == 0);
if (! ((ceo->offset) < 0x4000))
return (true);
(address[-3]) &=~ BLOCK_OFFSET_MASK;
(address[-3]) |=
- ((((ceo->offset) << 1) | ((ceo->continued_p) ? 1 : 0))
+ (((((ceo->offset) / units) << 1) | ((ceo->continued_p) ? 1 : 0))
<< BLOCK_OFFSET_SHIFT);
return (false);
}