(;; SCCS : @(#)DONOR.LSP 1.4 2/3/86 ;;; File : $xerox/donor.lsp ;;; Author : Richard A. O'Keefe ;;; Purpose: Access \{GET,PUT}BASE{,PTR} PROGN ;;; ------------------------------------------------------------------------ ;; ;; WARNING: This material is CONFIDENTIAL and proprietary to Quintus ;; Computer Systems Inc. This notice is protection against inadvertent ;; disclosure and does not constitute publication or reflect any intent ;; to publish. ;; ;; Copyright (C) 1985, by Quintus Computer Systems, Inc. ;; All rights reserved. ;; ;; CAVEAT LECTOR: This software is under development. No warrantee is ;; made that it is any use for anything at all. ;; ;;; ------------------------------------------------------------------------ ;; The name of this file is a joke because the contents aren't. ;; The four extended instructions found in this file provide access ;; to the Lisp primitives ;; ;; \GETBASE (get.word) = get←clause←word, get←proc←word ;; \GETBASEPTR (get.addr) = get←clause←addr, get←proc←addr ;; \PUTBASE (put.word) = put←clause←word, put←proc←word ;; \PUTBASEPTR (put.addr) = put←clause←addr, put←proc←addr ;; ;; In chemistry, a "base" (a generalisation of "alkali") is an ;; electron donor, hence "donor" is a mnemonic for "base". (Just ;; as "acceptor" would be a mnemonic for "acid", but Lisp has no ;; \GETACID primitives. Some of the primitives who made it may ;; have been taking acid, however.) ;; These instructions are like the "arg", "functor", and "compare" ;; instructions. Their arguments are put in A registers as if they ;; were ordinary predicates, and then the instruction appears in ;; place of a call. In the case of these specific instructions, ;; the first argument is always bound to a pointer to a block of ;; storage (usually a procedure record or a clause record), but ;; may need dereferencing, and the second argument is always a ;; SMALLP which needs no dereferencing. The third argument of the ;; "put" instructions is bound to a constant, but may need to be ;; dereferenced. The interpreter uses the "get" instructions ;; heavily, and consulting uses the "put" ones a lot, so they are ;; coded to go as fast as I can make them in Lisp. For now it is ;; not important to micro-code them. If we really wanted to be ;; hairy about it, we could pass the offset, not in a register, ;; but as a 16-bit constant following the instruction. ;; NOTE THAT THESE INSTRUCTIONS DO NO REFERENCE COUNT MAINTENANCE. ;; The objects pointers to which are manipulated by these opcodes ;; are assumed to be nailed down by other references which Lisp can ;; seen. See in particular PROCS.LSP and SKEL.LSP. ;; NOTE THAT if a variable is passed in A1 (or A3 for "put.xxxx") ;; these instructions will loop forever; not a particularly good ;; idea. They are ONLY for use in COMPLETELY TRUSTED system code! (def.both.mode get.word (extend) (while (EQ (tag.of A1) ref.tag.8) (put.24 R (untag.ref A1)) (put.32 A1 (get.cell R 0)) ) (put.32 T1 (tag.immed (\GETBASE (untag.anything A1) (untag.immed A2)) )) (put.32 T0 (get.Aval 3)) (unify.and.continue 0) ) (def.both.mode get.addr (extend) (while (EQ (tag.of A1) ref.tag.8) (put.24 R (untag.ref A1)) (put.32 A1 (get.cell R 0)) ) (put.32 T1 (tag.other (\GETBASEPTR (untag.anything A1) (untag.immed A2)) )) (put.32 T0 (get.Aval 3)) (unify.and.continue 0) ) (def.both.mode put.word (extend) (while (EQ (tag.of A1) ref.tag.8) (put.24 R (untag.ref A1)) (put.32 A1 (get.cell R 0)) ) (while (EQ (tag.of A3) ref.tag.8) (put.24 R (untag.ref A3)) (put.32 A3 (get.cell R 0)) ) (\PUTBASE (untag.anything A1) (untag.immed A2) (untag.immed A3)) (continue 0) ) (def.both.mode put.addr (extend) (while (EQ (tag.of A1) ref.tag.8) (put.24 R (untag.ref A1)) (put.32 A1 (get.cell R 0)) ) (while (EQ (tag.of A3) ref.tag.8) (put.24 R (untag.ref A3)) (put.32 A3 (get.cell R 0)) ) (\PUTBASEPTR (untag.anything A1) (untag.immed A2) (untag.anything A3)) (continue 0) ) ;; The following two instructions are a stop-gap to ensure that reading ;; and writing global flags will not go through the full-scale Lisp call. ;; I do not like the fact that they go through the arithmetic interface, ;; and this was not my original intention, but it proved quickest to do ;; this than to modify the compiler to generate what I really want, and ;; this has the advantage that the existing Lisp interface can be kept. ;; (Not that it is especially good, but it is a fair bit of work to put ;; another version in its place.) These two instructions are (atom) as ;; there wasn't time to tell LOAD.LSP about (extend atom). (def.both.mode gettopval (atom) (put.32 T1 (get.32 T0)) (put.32 T0 (tag.other (GETTOPVAL (\VAG2 0 (get.code P 0)) )) ) (continue 1) ) (def.both.mode settopval (atom) (SETTOPVAL (\VAG2 0 (get.code P 0)) (untag.immed T0)) (continue 1) ) ) STOP