guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 01/01: Document new VM instructions


From: Andy Wingo
Subject: [Guile-commits] 01/01: Document new VM instructions
Date: Mon, 01 Feb 2016 20:22:15 +0000

wingo pushed a commit to branch master
in repository guile.

commit a653271f986316118961bb20f59f5c924b6cd523
Author: Andy Wingo <address@hidden>
Date:   Mon Feb 1 21:21:38 2016 +0100

    Document new VM instructions
    
    * doc/ref/vm.texi (Stack Layout): Add a note about unboxed values.
      (Instruction Set): Update for new instructions.
---
 doc/ref/vm.texi |  231 ++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 205 insertions(+), 26 deletions(-)

diff --git a/doc/ref/vm.texi b/doc/ref/vm.texi
index 097fb8b..528b66d 100644
--- a/doc/ref/vm.texi
+++ b/doc/ref/vm.texi
@@ -189,6 +189,12 @@ new call frame.
 In this way, the dynamic link links the current frame to the previous
 frame.  Computing a stack trace involves traversing these frames.
 
+Each stack local in Guile is 64 bits wide, even on 32-bit architectures.
+This allows Guile to preserve its uniform treatment of stack locals
+while allowing for unboxed arithmetic on 64-bit integers and
+floating-point numbers.  @xref{Instruction Set}, for more on unboxed
+arithmetic.
+
 As an implementation detail, we actually store the dynamic link as an
 offset and not an absolute value because the stack can move at runtime
 as it expands or during partial continuation calls.  If it were an
@@ -461,7 +467,7 @@ compiled @code{.go} files.  It's good times!
 @node Instruction Set
 @subsection Instruction Set
 
-There are currently about 130 instructions in Guile's virtual machine.
+There are currently about 175 instructions in Guile's virtual machine.
 These instructions represent atomic units of a program's execution.
 Ideally, they perform one task without conditional branches, then
 dispatch to the next instruction in the stream.
@@ -551,6 +557,16 @@ In addition, some Scheme primitives have their own inline
 implementations.  For example, in the previous section we saw
 @code{cons}.
 
+Finally, for instructions with operands that encode references to the
+stack, the interpretation of those stack values is up to the instruction
+itself.  Most instructions expect their operands to be tagged SCM values
+(@code{scm} representation), but some instructions expect unboxed
+integers (@code{u64} and @code{s64} representations) or floating-point
+numbers (@var{f64} representation).  Instructions have static types:
+they must receive their operands in the format they expect.  It's up to
+the compiler to ensure this is the case.  Unless otherwise mentioned,
+all operands and results are boxed as SCM values.
+
 @menu
 * Lexical Environment Instructions::
 * Top-Level Environment Instructions::
@@ -564,6 +580,8 @@ implementations.  For example, in the previous section we 
saw
 * Inlined Scheme Instructions::
 * Inlined Mathematical Instructions::
 * Inlined Bytevector Instructions::
+* Unboxed Integer Arithmetic::
+* Unboxed Floating-Point Arithmetic::
 @end menu
 
 
@@ -707,10 +725,8 @@ in which to save the @code{ip} and @code{fp}.
 
 Returning values is similar.  Multiple-value returns should have values
 already shuffled down to start from @code{fp}-relative slot 1 before
-emitting @code{return-values}.  There is a short-cut in the single-value
-case, in that @code{return} handles the trivial shuffling itself.  We
-start from slot 1 instead of slot 0 to make tail calls to @code{values}
-trivial.
+emitting @code{return-values}.  We start from slot 1 instead of slot 0
+to make tail calls to @code{values} trivial.
 
 In both calls and returns, the @code{sp} is used to indicate to the
 callee or caller the number of arguments or return values, respectively.
@@ -772,10 +788,6 @@ return values equals @var{nvalues} exactly.  After 
@code{receive-values}
 has run, the values can be copied down via @code{mov}, or used in place.
 @end deftypefn
 
address@hidden Instruction {} return s24:@var{src}
-Return a value.
address@hidden deftypefn
-
 @deftypefn Instruction {} return-values c24:@var{nlocals}
 Return a number of values from a call frame.  This opcode corresponds to
 an application of @code{values} in tail position.  As with tail calls,
@@ -935,6 +947,13 @@ not generated by the compiler.
 Load a builtin stub by index into @var{dst}.
 @end deftypefn
 
address@hidden Instruction {} apply-non-program x24:@var{_}
+An instruction used only by a special trampoline that the VM uses to
+apply non-programs.  Using that trampoline allows profilers and
+backtrace utilities to avoid seeing the instruction pointer from the
+calling frame.
address@hidden deftypefn
+
 
 @node Branch Instructions
 @subsubsection Branch Instructions
@@ -990,10 +1009,9 @@ See @code{libguile/tags.h} for all the details.
 
 @deftypefn Instruction {} br-if-eq s24:@var{a} x8:@var{_} s24:@var{b} 
b1:@var{invert} x7:@var{_} l24:@var{offset}
 @deftypefnx Instruction {} br-if-eqv s24:@var{a} x8:@var{_} s24:@var{b} 
b1:@var{invert} x7:@var{_} l24:@var{offset}
address@hidden Instruction {} br-if-equal s24:@var{a} x8:@var{_} s24:@var{b} 
b1:@var{invert} x7:@var{_} l24:@var{offset}
-If the value in @var{a} is @code{eq?}, @code{eqv?}, or @code{equal?} to
-the value in @var{b}, respectively, add @var{offset} to the current
-instruction pointer.
+If the value in @var{a} is @code{eq?} or @code{eqv?} to the value in
address@hidden, respectively, add @var{offset} to the current instruction
+pointer.
 @end deftypefn
 
 @deftypefn Instruction {} br-if-= s24:@var{a} x8:@var{_} s24:@var{b} 
b1:@var{invert} x7:@var{_} l24:@var{offset}
@@ -1179,6 +1197,10 @@ Reference the fluid in @var{src}, and place the value in 
@var{dst}.
 Set the value of the fluid in @var{dst} to the value in @var{src}.
 @end deftypefn
 
address@hidden Instruction {} current-thread s24:@var{dst}
+Write the value of the current thread to @var{dst}.
address@hidden deftypefn
+
 
 @node Miscellaneous Instructions
 @subsubsection Miscellaneous Instructions
@@ -1234,12 +1256,14 @@ be filled with the value in slot @var{init}.
 @end deftypefn
 
 @deftypefn Instruction {} vector-length s12:@var{dst} s12:@var{src}
-Store the length of the vector in @var{src} in @var{dst}.
+Store the length of the vector in @var{src} in @var{dst}, as an unboxed
+unsigned 64-bit integer.
 @end deftypefn
 
 @deftypefn Instruction {} vector-ref s8:@var{dst} s8:@var{src} s8:@var{idx}
 Fetch the item at position @var{idx} in the vector in @var{src}, and
-store it in @var{dst}.
+store it in @var{dst}.  The @var{idx} value should be an unboxed
+unsigned 64-bit integer.
 @end deftypefn
 
 @deftypefn Instruction {} vector-ref/immediate s8:@var{dst} s8:@var{src} 
c8:@var{idx}
@@ -1248,7 +1272,8 @@ Fill @var{dst} with the item @var{idx} elements into the 
vector at
 @end deftypefn
 
 @deftypefn Instruction {} vector-set! s8:@var{dst} s8:@var{idx} s8:@var{src}
-Store @var{src} into the vector @var{dst} at index @var{idx}.
+Store @var{src} into the vector @var{dst} at index @var{idx}.  The
address@hidden value should be an unboxed unsigned 64-bit integer.
 @end deftypefn
 
 @deftypefn Instruction {} vector-set!/immediate s8:@var{dst} c8:@var{idx} 
s8:@var{src}
@@ -1263,16 +1288,19 @@ Store the vtable of @var{src} into @var{dst}.
 @deftypefn Instruction {} allocate-struct s8:@var{dst} s8:@var{vtable} 
s8:@var{nfields}
 Allocate a new struct with @var{vtable}, and place it in @var{dst}.  The
 struct will be constructed with space for @var{nfields} fields, which
-should correspond to the field count of the @var{vtable}.
+should correspond to the field count of the @var{vtable}.  The @var{idx}
+value should be an unboxed unsigned 64-bit integer.
 @end deftypefn
 
 @deftypefn Instruction {} struct-ref s8:@var{dst} s8:@var{src} s8:@var{idx}
 Fetch the item at slot @var{idx} in the struct in @var{src}, and store
-it in @var{dst}.
+it in @var{dst}.  The @var{idx} value should be an unboxed unsigned
+64-bit integer.
 @end deftypefn
 
 @deftypefn Instruction {} struct-set! s8:@var{dst} s8:@var{idx} s8:@var{src}
-Store @var{src} into the struct @var{dst} at slot @var{idx}.
+Store @var{src} into the struct @var{dst} at slot @var{idx}.  The
address@hidden value should be an unboxed unsigned 64-bit integer.
 @end deftypefn
 
 @deftypefn Instruction {} allocate-struct/immediate s8:@var{dst} 
s8:@var{vtable} c8:@var{nfields}
@@ -1291,12 +1319,14 @@ Make a new array with @var{type}, @var{fill}, and 
@var{bounds}, storing it in @v
 @end deftypefn
 
 @deftypefn Instruction {} string-length s12:@var{dst} s12:@var{src}
-Store the length of the string in @var{src} in @var{dst}.
+Store the length of the string in @var{src} in @var{dst}, as an unboxed
+unsigned 64-bit integer.
 @end deftypefn
 
 @deftypefn Instruction {} string-ref s8:@var{dst} s8:@var{src} s8:@var{idx}
-Fetch the character at position @var{idx} in the string in @var{src}, and store
-it in @var{dst}.
+Fetch the character at position @var{idx} in the string in @var{src},
+and store it in @var{dst}.  The @var{idx} value should be an unboxed
+unsigned 64-bit integer.
 @end deftypefn
 
 @deftypefn Instruction {} cons s8:@var{dst} s8:@var{car} s8:@var{cdr}
@@ -1340,16 +1370,16 @@ All of these operations place their result in their 
first operand,
 Add @var{a} to @var{b}.
 @end deftypefn
 
address@hidden Instruction {} add1 s12:@var{dst} s12:@var{src}
-Add 1 to the value in @var{src}.
address@hidden Instruction {} add/immediate s8:@var{dst} s8:@var{src} 
c8:@var{imm}
+Add the unsigned integer @var{imm} to the value in @var{src}.
 @end deftypefn
 
 @deftypefn Instruction {} sub s8:@var{dst} s8:@var{a} s8:@var{b}
 Subtract @var{b} from @var{a}.
 @end deftypefn
 
address@hidden Instruction {} sub1 s12:@var{dst} s12:@var{src}
-Subtract 1 from @var{src}.
address@hidden Instruction {} sub/immediate s8:@var{dst} s8:@var{src} 
s8:@var{imm}
+Subtract the unsigned integer @var{imm} from the value in @var{src}.
 @end deftypefn
 
 @deftypefn Instruction {} mul s8:@var{dst} s8:@var{a} s8:@var{b}
@@ -1388,6 +1418,10 @@ Compute the bitwise inclusive @code{or} of @var{a} with 
@var{b}.
 Compute the bitwise exclusive @code{or} of @var{a} with @var{b}.
 @end deftypefn
 
address@hidden Instruction {} logsub s8:@var{dst} s8:@var{a} s8:@var{b}
+Place the bitwise @code{and} of @var{a} and the bitwise @code{not} of
address@hidden into @var{dst}.
address@hidden deftypefn
 
 @node Inlined Bytevector Instructions
 @subsubsection Inlined Bytevector Instructions
@@ -1398,6 +1432,11 @@ a clear path for eventual native compilation. Without 
this, Scheme
 programs would need other primitives for accessing raw bytes -- but
 these primitives are as good as any.
 
address@hidden Instruction {} bv-length s12:@var{dst} s12:@var{src}
+Store the length of the bytevector in @var{src} in @var{dst}, as an
+unboxed unsigned 64-bit integer.
address@hidden deftypefn
+
 @deftypefn Instruction {} bv-u8-ref s8:@var{dst} s8:@var{src} s8:@var{idx}
 @deftypefnx Instruction {} bv-s8-ref s8:@var{dst} s8:@var{src} s8:@var{idx}
 @deftypefnx Instruction {} bv-u16-ref s8:@var{dst} s8:@var{src} s8:@var{idx}
@@ -1411,6 +1450,12 @@ these primitives are as good as any.
 
 Fetch the item at byte offset @var{idx} in the bytevector @var{src}, and
 store it in @var{dst}.  All accesses use native endianness.
+
+The @var{idx} value should be an unboxed unsigned 64-bit integer.
+
+The results are all written to the stack as unboxed values, either as
+signed 64-bit integers, unsigned 64-bit integers, or IEEE double
+floating point numbers.
 @end deftypefn
 
 @deftypefn Instruction {} bv-u8-set! s8:@var{dst} s8:@var{idx} s8:@var{src}
@@ -1426,4 +1471,138 @@ store it in @var{dst}.  All accesses use native 
endianness.
 
 Store @var{src} into the bytevector @var{dst} at byte offset @var{idx}.
 Multibyte values are written using native endianness.
+
+The @var{idx} value should be an unboxed unsigned 64-bit integer.
+
+The @var{src} values are all unboxed, either as signed 64-bit integers,
+unsigned 64-bit integers, or IEEE double floating point numbers.
address@hidden deftypefn
+
+
address@hidden Unboxed Integer Arithmetic
address@hidden Unboxed Integer Arithmetic
+
+Guile supports two kinds of unboxed integers: unsigned 64-bit integers,
+and signed 64-bit integers.  Guile prefers unsigned integers, in the
+sense that Guile's compiler supports them better and the virtual machine
+has more operations that work on them.  Still, signed integers are
+supported at least to allow @code{bv-s64-ref} and related instructions
+to avoid boxing their values.
+
address@hidden Instruction {} scm->u64 s12:@var{dst} s12:@var{src}
+Unbox the SCM value at @var{src} to a unsigned 64-bit integer, placing
+the result in @var{dst}.  If the @var{src} value is not an exact integer
+in the unsigned 64-bit range, signal an error.
address@hidden deftypefn
+
address@hidden Instruction {} u64->scm s12:@var{dst} s12:@var{src}
+Box the unsigned 64-bit integer at @var{src} to a SCM value and place
+the result in @var{dst}.  The result will be a fixnum or a bignum.
address@hidden deftypefn
+
address@hidden Instruction {} load-u64 s24:@var{dst} au32:@var{high-bits} 
au32:@var{low-bits}
+Load a 64-bit value formed by joining @var{high-bits} and
address@hidden, and write it to @var{dst}.
address@hidden deftypefn
+
address@hidden Instruction {} scm->s64 s12:@var{dst} s12:@var{src}
address@hidden Instruction {} s64->scm s12:@var{dst} s12:@var{src}
address@hidden Instruction {} load-s64 s24:@var{dst} as32:@var{high-bits} 
as32:@var{low-bits}
+Like @code{scm->u64}, @code{u64->scm}, and @code{load-u64}, but for
+signed 64-bit integers.
address@hidden deftypefn
+
+Sometimes the compiler can know that we will only need a subset of the
+bits in an integer.  In that case we can sometimes unbox an integer even
+if it might be out of range.
+
address@hidden Instruction {} scm->u64/truncate s12:@var{dst} s12:@var{src}
+Take the SCM value in @var{dst} and @code{logand} it with @code{(1- (ash
+1 64))}.  Place the unboxed result in @var{dst}.
 @end deftypefn
+
address@hidden Instruction {} br-if-u64-= s24:@var{a} x8:@var{_} s24:@var{b} 
b1:@var{invert} x7:@var{_} l24:@var{offset}
address@hidden Instruction {} br-if-u64-< s24:@var{a} x8:@var{_} s24:@var{b} 
b1:@var{invert} x7:@var{_} l24:@var{offset}
address@hidden Instruction {} br-if-u64-<= s24:@var{a} x8:@var{_} s24:@var{b} 
b1:@var{invert} x7:@var{_} l24:@var{offset}
+If the unboxed unsigned 64-bit integer value in @var{a} is @code{=},
address@hidden<}, or @code{<=} to the unboxed unsigned 64-bit integer value in
address@hidden, respectively, add @var{offset} to the current instruction
+pointer.
address@hidden deftypefn
+
address@hidden Instruction {} br-if-u64-=-scm s24:@var{a} x8:@var{_} 
s24:@var{b} b1:@var{invert} x7:@var{_} l24:@var{offset}
address@hidden Instruction {} br-if-u64-<-scm s24:@var{a} x8:@var{_} 
s24:@var{b} b1:@var{invert} x7:@var{_} l24:@var{offset}
address@hidden Instruction {} br-if-u64-<=-scm s24:@var{a} x8:@var{_} 
s24:@var{b} b1:@var{invert} x7:@var{_} l24:@var{offset}
+If the unboxed unsigned 64-bit integer value in @var{a} is @code{=},
address@hidden<}, or @code{<=} to the SCM value in @var{b}, respectively, add
address@hidden to the current instruction pointer.
address@hidden deftypefn
+
address@hidden Instruction {} uadd s8:@var{dst} s8:@var{a} s8:@var{b}
address@hidden Instruction {} usub s8:@var{dst} s8:@var{a} s8:@var{b}
address@hidden Instruction {} umul s8:@var{dst} s8:@var{a} s8:@var{b}
+Like @code{add}, @code{sub}, and @code{mul}, except taking
+the operands as unboxed unsigned 64-bit integers, and producing the
+same.  The result will be silently truncated to 64 bits.
address@hidden deftypefn
+
address@hidden Instruction {} uadd/immediate s8:@var{dst} s8:@var{a} c8:@var{b}
address@hidden Instruction {} usub/immediate s8:@var{dst} s8:@var{a} c8:@var{b}
address@hidden Instruction {} umul/immediate s8:@var{dst} s8:@var{a} c8:@var{b}
+Like @code{uadd}, @code{usub}, and @code{umul}, except the second
+operand is an immediate unsigned 8-bit integer.
address@hidden deftypefn
+
address@hidden Instruction {} ulogand s8:@var{dst} s8:@var{a} s8:@var{b}
address@hidden Instruction {} ulogior s8:@var{dst} s8:@var{a} s8:@var{b}
address@hidden Instruction {} ulogsub s8:@var{dst} s8:@var{a} s8:@var{b}
+Like @code{logand}, @code{logior}, and @code{logsub}, but operating on
+unboxed unsigned 64-bit integers.
address@hidden deftypefn
+
address@hidden Instruction {} ulsh s8:@var{dst} s8:@var{a} s8:@var{b}
+Shift the unboxed unsigned 64-bit integer in @var{a} left by @var{b}
+bits, also an unboxed unsigned 64-bit integer.  Truncate to 64 bits and
+write to @var{dst} as an unboxed value.  Only the lower 6 bits of
address@hidden are used.
address@hidden deftypefn
+
address@hidden Instruction {} ursh s8:@var{dst} s8:@var{a} s8:@var{b}
+Like @code{ulsh}, but shifting right.
address@hidden deftypefn
+
address@hidden Instruction {} ulsh/immediate s8:@var{dst} s8:@var{a} c8:@var{b}
address@hidden Instruction {} ursh/immediate s8:@var{dst} s8:@var{a} c8:@var{b}
+Like @code{ulsh} and @code{ursh}, but encoding @code{b} as an immediate
+8-bit unsigned integer.
address@hidden deftypefn
+
+
address@hidden Unboxed Floating-Point Arithmetic
address@hidden Unboxed Floating-Point Arithmetic
+
address@hidden Instruction {} scm->f64 s12:@var{dst} s12:@var{src}
+Unbox the SCM value at @var{src} to an IEEE double, placing the result
+in @var{dst}.  If the @var{src} value is not a real number, signal an
+error.
address@hidden deftypefn
+
address@hidden Instruction {} f64->scm s12:@var{dst} s12:@var{src}
+Box the IEEE double at @var{src} to a SCM value and place the result in
address@hidden
address@hidden deftypefn
+
address@hidden Instruction {} load-f64 s24:@var{dst} au32:@var{high-bits} 
au32:@var{low-bits}
+Load a 64-bit value formed by joining @var{high-bits} and
address@hidden, and write it to @var{dst}.
address@hidden deftypefn
+
address@hidden Instruction {} fadd s8:@var{dst} s8:@var{a} s8:@var{b}
address@hidden Instruction {} fsub s8:@var{dst} s8:@var{a} s8:@var{b}
address@hidden Instruction {} fmul s8:@var{dst} s8:@var{a} s8:@var{b}
address@hidden Instruction {} fdiv s8:@var{dst} s8:@var{a} s8:@var{b}
+Like @code{add}, @code{sub}, @code{div}, and @code{mul}, except taking
+the operands as unboxed IEEE double floating-point numbers, and producing
+the same.
address@hidden deftypefn
+



reply via email to

[Prev in Thread] Current Thread [Next in Thread]