Use a much simpler endian-independent execute cache mechanism.
authorTaylor R Campbell <campbell@mumble.net>
Fri, 11 Jan 2019 06:35:27 +0000 (06:35 +0000)
committerTaylor R Campbell <campbell@mumble.net>
Fri, 11 Jan 2019 07:15:37 +0000 (07:15 +0000)
Requires no changes to the SVM1 byte code, so existing unlinked .com
files will continue to work (except for those created in the past
couple hours with my big-endian bodge that entailed no changes to the
little-endian hack), although built bands will confuse the microcode
because what cmpint stores in execute caches in memory changed.

- Before linking, an execution cache is simply the two words, as
  before on little-endian systems:

    <frame size> (fixnum)
    <name> (symbol)

- After linking, the frame size remains untouched and the name is
  replaced by the untagged address of the target:

    <frame size> (fixnum)
    <target> (untagged)

- INVOCATION:UUO-LINK now generates an (indirect-jump (pc-relative
  <cache>)) instruction, which already does the right thing:
  dereferences PC + offset to find a instruction address, and then
  jumps to that address.

src/compiler/machines/svm/assembler-runtime.scm
src/compiler/machines/svm/disassembler.scm
src/compiler/machines/svm/machine.scm
src/compiler/machines/svm/rules.scm
src/microcode/cmpintmd/svm1.c
src/microcode/cmpintmd/svm1.h

index 747cc76528b5010ae9445c2467cd8c06249ea150..fd8c3935279ed11cec8eb3e695a5ad8c69ca1322 100644 (file)
@@ -163,6 +163,7 @@ USA.
   (add-instruction-assembler! 'LOAD (load-assembler))
   (add-instruction-assembler! 'LOAD-ADDRESS (load-address-assembler))
   (add-instruction-assembler! 'JUMP (jump-assembler))
+  (add-instruction-assembler! 'INDIRECT-JUMP (indirect-jump-assembler))
   (add-instruction-assembler! 'CONDITIONAL-JUMP (cjump1-assembler))
   (add-instruction-assembler! 'CONDITIONAL-JUMP (cjump2-assembler)))
 
@@ -268,6 +269,35 @@ USA.
       ;; Does not fit into a smaller number of bytes; no fixing necessary.
       offset))
 
+(define (pc-relative-stats-unsigned nbits make-sample)
+  (let ((high (-1+ (expt 2 nbits)))
+       (low 0))
+    (let* ((bit-width (fixed-instruction-width (make-sample high)))
+          (byte-width (/ bit-width 8)))
+      (list nbits byte-width bit-width
+           (+ low byte-width) (+ high byte-width)))))
+
+(define (pc-relative-selector-unsigned stats make-inst)
+  (let ((nbits (car stats))
+       (byte-width (cadr stats))
+       (bit-width (caddr stats)))
+    (cons
+     (named-lambda (pc-relative-selector-handler offset)
+       (let ((operand (fix-offset-unsigned (- offset byte-width) nbits)))
+        (assemble-fixed-instruction bit-width (make-inst operand))))
+     (cddr stats))))
+
+(define-integrable (fix-offset-unsigned offset nbits)
+  (if (or (and (= nbits 16)
+              (let ((low 0) (high #xFF))
+                (and (<= low offset) (<= offset high))))
+         (and (= nbits 32)
+              (let ((low 0) (high #xFFFF))
+                (and (<= low offset) (<= offset high)))))
+      (unsigned-integer->bit-string nbits offset)
+      ;; Does not fit into a smaller number of bytes; no fixing necessary.
+      offset))
+
 (define (store-assembler)
   (let ((make-sample (lambda (offset)
                       (inst:store 'WORD rref:word-0
@@ -338,6 +368,22 @@ USA.
            ,(pc-relative-selector 16bit-stats make-inst)
            ,(pc-relative-selector 32bit-stats make-inst))))))))
 
+(define (indirect-jump-assembler)
+  (let ((make-sample (lambda (offset)
+                      (inst:indirect-jump (ea:pc-relative offset)))))
+    (let (( 8bit-stats (pc-relative-stats-unsigned  8 make-sample))
+         (16bit-stats (pc-relative-stats-unsigned 16 make-sample))
+         (32bit-stats (pc-relative-stats-unsigned 32 make-sample)))
+      (rule-matcher
+       ((PC-RELATIVE (- (? label) *PC*)))
+       (let ((make-inst (lambda (offset)
+                         (inst:indirect-jump (ea:pc-relative offset)))))
+        `((VARIABLE-WIDTH-EXPRESSION
+           (- ,label *PC*)
+           ,(pc-relative-selector-unsigned  8bit-stats make-inst)
+           ,(pc-relative-selector-unsigned 16bit-stats make-inst)
+           ,(pc-relative-selector-unsigned 32bit-stats make-inst))))))))
+
 (define (cjump2-assembler)
   (let ((make-sample (lambda (offset)
                       (inst:conditional-jump 'EQ rref:word-0 rref:word-1
@@ -668,8 +714,10 @@ USA.
     (let ((limit (expt 2 n-bits)))
       (define-pvt (symbol 'UNSIGNED- n-bits) (symbol 'U n-bits) 'INTEGER
        (lambda (object)
-         (and (exact-nonnegative-integer? object)
-              (< object limit)))
+         (or (and (bit-string? object)
+                  (= n-bits (bit-string-length object)))
+             (and (exact-nonnegative-integer? object)
+                  (< object limit))))
        (symbol 'ENCODE-UNSIGNED-INTEGER- n-bits)
        (symbol 'DECODE-UNSIGNED-INTEGER- n-bits)))))
 
@@ -724,19 +772,30 @@ USA.
 ;;;; Primitive codecs
 
 (define (encode-unsigned-integer-8 n write-byte)
-  (write-byte n))
+  (if (bit-string? n)
+      (write-bytes n 1 write-byte)
+      (write-byte n)))
 
 (define (encode-unsigned-integer-16 n write-byte)
-  (write-byte (remainder n #x100))
-  (write-byte (quotient n #x100)))
+  (if (bit-string? n)
+      (write-bytes n 2 write-byte)
+      (begin
+       (write-byte (remainder n #x100))
+       (write-byte (quotient n #x100)))))
 
 (define (encode-unsigned-integer-32 n write-byte)
-  (encode-unsigned-integer-16 (remainder n #x10000) write-byte)
-  (encode-unsigned-integer-16 (quotient n #x10000) write-byte))
+  (if (bit-string? n)
+      (write-bytes n 4 write-byte)
+      (begin
+       (encode-unsigned-integer-16 (remainder n #x10000) write-byte)
+       (encode-unsigned-integer-16 (quotient n #x10000) write-byte))))
 
 (define (encode-unsigned-integer-64 n write-byte)
-  (encode-unsigned-integer-32 (remainder n #x100000000) write-byte)
-  (encode-unsigned-integer-32 (quotient n #x100000000) write-byte))
+  (if (bit-string? n)
+      (write-bytes n 8 write-byte)
+      (begin
+       (encode-unsigned-integer-32 (remainder n #x100000000) write-byte)
+       (encode-unsigned-integer-32 (quotient n #x100000000) write-byte))))
 
 (define (decode-unsigned-integer-8 read-byte)
   (read-byte))
index 98710395bc02b2eb3b98fb77ac02796f36aff15d..56ebaadd85843e5f37fa507435bbff35664f2b4a 100644 (file)
@@ -348,21 +348,17 @@ USA.
              (vector-ref result 0))))))
 
 (define (read-procedure-cache block index)
-  (let ((word (system-vector-ref block index)))
-    (if (object-type? (ucode-type fixnum) word)
+  (let ((frame-size (system-vector-ref block index)))
+    (assert (object-type? (ucode-type fixnum) frame-size))
+    (if (object-type? (ucode-type interned-symbol)
+                     (system-vector-ref block (1+ index)))
        ;; Unlinked.
-       (vector 'INTERPRETED (system-vector-ref block (1+ index)) word)
+       (let ((name (system-vector-ref block (1+ index))))
+         (vector 'INTERPRETED name frame-size))
        ;; Linked.
-       (let ((offset (compiled-code-block/index->offset index))
-             (bytes address-units-per-object))
-         (let ((arity (read-unsigned-integer block offset 16))
-               (opcode (read-unsigned-integer block (+ offset bytes -2) 8))
-               (operand (read-unsigned-integer block (+ offset bytes -1) 8)))
-           (if (and (= opcode svm1-inst:ijump-u8) (= operand 0))
-               (vector 'COMPILED (read-procedure block (+ offset bytes)) arity)
-               (error (string-append "disassembler/read-procedure-cache:"
-                                     " Unexpected instruction")
-                      opcode operand)))))))
+       (let* ((offset (compiled-code-block/index->offset (1+ index)))
+              (procedure (read-procedure block offset)))
+         (vector 'COMPILED procedure frame-size)))))
 
 (define (read-procedure block offset)
   (with-absolutely-no-interrupts
index 79731378990db04f40f4cc8cd98acf29be109964..f4bcb56fa1d2833f7b9d7dd63ade113bc9447381 100644 (file)
@@ -141,6 +141,7 @@ USA.
 (define-inst entry-point label)
 
 (define-inst jump address)
+(define-inst indirect-jump offset)
 
 (define (inst:trap n . args)
   (list (cons* 'TRAP n args)))
@@ -222,14 +223,6 @@ USA.
 (define (ea:address label)
   (ea:pc-relative `(- ,label *PC*)))
 
-(define ea:uuo-entry-address
-  (let ((offset
-        ;; LABEL is the uuo-link-label, but the PC to jump to is two
-        ;; opcode bytes before the following word (the link address).
-        (- address-units-per-object 2)))
-    (named-lambda (ea:uuo-entry-address label)
-      (ea:pc-relative `(- (+ ,label ,offset) *PC*)))))
-
 (define (ea:stack-pop)
   (ea:post-increment rref:stack-pointer 'WORD))
 
index 23d8924816afdaf851d51c26d94e63e9dc061393..40f2d2097fa6efef9eb822a44abb6bc5b61461eb 100644 (file)
@@ -651,16 +651,16 @@ USA.
   continuation
   (expect-no-exit-interrupt-checks)
   (LAP ,@(clear-map!)
-       ,@(inst:jump (ea:uuo-entry-address
-                    (free-uuo-link-label name frame-size)))))
+       ,@(inst:indirect-jump
+         (ea:address (free-uuo-link-label name frame-size)))))
 
 (define-rule statement
   (INVOCATION:GLOBAL-LINK (? frame-size) (? continuation) (? name))
   continuation
   (expect-no-exit-interrupt-checks)
   (LAP ,@(clear-map!)
-       ,@(inst:jump (ea:uuo-entry-address
-                    (global-uuo-link-label name frame-size)))))
+       ,@(inst:indirect-jump
+         (ea:address (global-uuo-link-label name frame-size)))))
 
 (define-rule statement
   (INVOCATION:CACHE-REFERENCE (? frame-size) (? continuation) (? extension))
@@ -1347,16 +1347,8 @@ USA.
                   (lambda (cache)
                     (let ((frame-size (car cache))
                           (label (cdr cache)))
-                      (case endianness
-                        ((BIG)
-                         `((,name . ,label)
-                           (#f . ,(allocate-constant-label))
-                           (,frame-size . ,(allocate-constant-label))))
-                        ((LITTLE)
-                         `((,frame-size . ,label)
-                           (,name . ,(allocate-constant-label))))
-                        (else
-                         (error "Unknown endianness:" endianness))))))
+                      `((,frame-size . ,(allocate-constant-label))
+                        (,name . ,label)))))
                 (cdr name.caches)))
              name.caches-list))
 
index 66f4d886b4a5a1dd914df2229e56ffbb815b0c80..d6c46a38e7134b4aa741bb5fef2ef835831f8164 100644 (file)
@@ -294,80 +294,27 @@ compiled_closure_entry_to_target (insn_t * entry)
    the calling process without having to find and change all the
    places in the compiled code that refer to it.
 
-   Prior to linking, the execution cache has two pieces of
-   information: (1) the name of the procedure being called (a symbol),
-   and (2) the number of arguments that will be passed to the
-   procedure.  It is laid out in memory like this (on a 32-bit
-   little-endian machine):
-
-   0x00    frame-size (fixnum)
-   0x04    name encoded as symbol
-
-   After linking, the cache is changed as follows:
-
-   0x00    frame-size (u16)
-   0x02    SVM1_INST_IJUMP_U8
-   0x03    offset = 0
-   0x04    32-bit address
-
-   On a 64-bit machine, the post-linking layout is:
-
-   0x00    frame-size (u16)
-   0x02    4 padding bytes
-   0x06    SVM1_INST_IJUMP_U8
-   0x07    offset = 0
-   0x08    64-bit address
-
-   On a big-endian machine, the frame size comes after the
-   name/instructions:
-
-   (unlinked, Scheme objects, any word size)
-           name encoded as symbol
-           padding #f
-           frame-size (fixnum below 2^16)
-
-   (linked, 32-bit)
-   0x00    2 padding bytes
-   0x02    SVM1_INST_IJUMP_U8
-   0x03    offset = 0
-   0x04    32-bit address
-   0x08    2 padding bytes
-   0x0a    frame-size (u16)
-
-   (linked, 64-bit)
-   0x00    6 padding bytes
-   0x06    SVM1_INST_IJUMP_U8
-   0x07    offset = 0
-   0x08    64-bit address
-   0x10    6 padding bytes
-   0x1e    frame-size (fixnum below 2^16)
-   */
+   Initially, the execution cache stores the frame size and the name of
+   the procedure being called (a symbol); after linking, the name is
+   replaced by the (untagged) address of the code to execute.
+
+   On real machines, execute caches usually have machine instructions
+   that perform the jump, but we have no need for that in SVM1 where we
+   already have an instruction to make an indirect jump to the address
+   stored at a PC-relative location in memory.  */
 
 unsigned int
 read_uuo_frame_size (SCHEME_OBJECT * saddr)
 {
-#ifdef WORDS_BIGENDIAN
-  insn_t * addr = (((insn_t *) (saddr + 3)) - 2);
-  unsigned hi = (addr[0]);
-  unsigned lo = (addr[1]);
-#else
-  insn_t * addr = ((insn_t *) saddr);
-  unsigned lo = (addr[0]);
-  unsigned hi = (addr[1]);
-#endif
-  return ((hi << 8) | lo);
+  return (OBJECT_DATUM (saddr[0]));
 }
 
 SCHEME_OBJECT
 read_uuo_symbol (SCHEME_OBJECT * saddr)
 {
-#ifdef WORDS_BIGENDIAN
-  return (saddr[0]);
-#else
   return (saddr[1]);
-#endif
 }
-\f
+
 insn_t *
 read_uuo_target (SCHEME_OBJECT * saddr)
 {
@@ -383,40 +330,7 @@ read_uuo_target_no_reloc (SCHEME_OBJECT * saddr)
 void
 write_uuo_target (insn_t * target, SCHEME_OBJECT * saddr)
 {
-  unsigned long frame_size = (read_uuo_frame_size (saddr));
-  insn_t * addr = ((insn_t *) saddr);
-  insn_t * end = ((insn_t *) (saddr + 1));
-
-#ifndef WORDS_BIGENDIAN
-  /* Write the frame size.  */
-  (*addr++) = (frame_size & 0x00FF);
-  (*addr++) = ((frame_size & 0xFF00) >> 8);
-#endif
-
-  /* Pad to a word boundary, minus two bytes.  */
-  while (addr < (end - 2))
-    (*addr++) = 0;
-
-  /* Write the instruction prefix.  */
-  (*addr++) = SVM1_INST_IJUMP_U8;
-  (*addr++) = 0;
-
-  /* We now have a word-aligned address.  Write the target here.  */
-  assert (addr == ((insn_t *) (saddr + 1)));
   (saddr[1]) = ((SCHEME_OBJECT) target);
-
-#ifdef WORDS_BIGENDIAN
-  /* Pad to a word boundary, minus one 16-bit quantity.  */
-  addr = ((insn_t *) (saddr + 2));
-  end = ((insn_t *) (saddr + 3));
-  while (addr < (end - 2))
-    (*addr++) = 0;
-
-  /* Write the frame size.  */
-  (*addr++) = ((frame_size & 0xFF00) >> 8);
-  (*addr++) = (frame_size & 0x00FF);
-  assert (addr == ((insn_t *) (saddr + 3)));
-#endif
 }
 \f
 unsigned long
index 09a556745b29b75f912c03b84a1b99bf61f810ce..67c1746c6872e0a6b6266f3dd4ed49c978451955 100644 (file)
@@ -62,11 +62,7 @@ typedef uint8_t insn_t;
 #define CLOSURE_ENTRY_SIZE 5
 
 /* Size of execution cache in SCHEME_OBJECTS.  */
-#ifdef WORDS_BIGENDIAN
-#define UUO_LINK_SIZE 3
-#else
 #define UUO_LINK_SIZE 2
-#endif
 #define READ_UUO_TARGET(a, r) read_uuo_target (a)
 
 #define UTILITY_RESULT_DEFINED 1