From e44423bd982a31c6b7db77eaa7f96bbfbc503935 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Fri, 11 Jan 2019 04:53:02 +0000 Subject: [PATCH] Design big-endian uuo link execute caches. The little-endian hack to overwrite the tag with instructions doesn't work on big-endian because it's the datum, not the tag, that's at the end of the word in the frame size. There's no room for the instructions before anything here, so add another word and move the frame size to the end. Kinda wasteful -- for that matter, it's not clear why we need to have any instructions here at all, when we could just have INVOCATION:UUO-LINK compile to an IJUMP instruction itself. --- src/compiler/machines/svm/rules.scm | 25 +++++--- src/microcode/cmpintmd/svm1.c | 88 +++++++++++++++++++++-------- src/microcode/cmpintmd/svm1.h | 4 ++ 3 files changed, 85 insertions(+), 32 deletions(-) diff --git a/src/compiler/machines/svm/rules.scm b/src/compiler/machines/svm/rules.scm index 895897422..23d892481 100644 --- a/src/compiler/machines/svm/rules.scm +++ b/src/compiler/machines/svm/rules.scm @@ -1341,14 +1341,23 @@ USA. (LAP)))) (define (generate/uuos name.caches-list) - (append-map (lambda (name.caches) - (append-map (let ((name (car name.caches))) - (lambda (cache) - (let ((frame-size (car cache)) - (label (cdr cache))) - `((,frame-size . ,label) - (,name . ,(allocate-constant-label)))))) - (cdr name.caches))) + (append-map + (lambda (name.caches) + (append-map (let ((name (car name.caches))) + (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)))))) + (cdr name.caches))) name.caches-list)) (define (make-linkage-type-marker linkage-type n-entries) diff --git a/src/microcode/cmpintmd/svm1.c b/src/microcode/cmpintmd/svm1.c index 73b32fbdd..66f4d886b 100644 --- a/src/microcode/cmpintmd/svm1.c +++ b/src/microcode/cmpintmd/svm1.c @@ -298,7 +298,7 @@ compiled_closure_entry_to_target (insn_t * entry) 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 - machine): + little-endian machine): 0x00 frame-size (fixnum) 0x04 name encoded as symbol @@ -318,34 +318,60 @@ compiled_closure_entry_to_target (insn_t * entry) 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) */ unsigned int read_uuo_frame_size (SCHEME_OBJECT * saddr) { - return (read_u16 ((insn_t *) 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); } SCHEME_OBJECT read_uuo_symbol (SCHEME_OBJECT * saddr) { +#ifdef WORDS_BIGENDIAN + return (saddr[0]); +#else return (saddr[1]); +#endif } insn_t * read_uuo_target (SCHEME_OBJECT * saddr) { - insn_t * addr = ((insn_t *) (saddr + 2)); - insn_t * end = ((insn_t *) (saddr + 1)); - unsigned long eaddr = 0; - - while (true) - { - eaddr |= (*--addr); - if (addr == end) - return ((insn_t *) eaddr); - eaddr <<= 8; - } + return ((insn_t *) (saddr[1])); } insn_t * @@ -357,28 +383,42 @@ read_uuo_target_no_reloc (SCHEME_OBJECT * saddr) void write_uuo_target (insn_t * target, SCHEME_OBJECT * saddr) { - unsigned long eaddr = ((unsigned long) target); - unsigned long frame_size = (OBJECT_DATUM (saddr[0])); + 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; - end = ((insn_t *) (saddr + 2)); - while (true) - { - (*addr++) = (eaddr & 0xFF); - if (addr == end) - break; - eaddr >>= 8; - } -} + /* 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 +} + unsigned long trampoline_entry_size (unsigned long n_entries) { diff --git a/src/microcode/cmpintmd/svm1.h b/src/microcode/cmpintmd/svm1.h index 67c1746c6..09a556745 100644 --- a/src/microcode/cmpintmd/svm1.h +++ b/src/microcode/cmpintmd/svm1.h @@ -62,7 +62,11 @@ 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 -- 2.25.1