Module: dfmc-modeling Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND define variable *target-machine-word-mask* :: false-or() = #f; /// Compute the proper mask to extract a for the target system /// from a on the local system. We need to use this mask as the /// target and local system word sizes may differ. define function target-machine-word-mask () => (mask :: ) *target-machine-word-mask* | begin local method build (n :: ) => (mask :: ) iterate loop (i :: = n, m = coerce-integer-to-machine-word(0)) if (i = 0) m else loop(i - 1, machine-word-logior(machine-word-unsigned-shift-left(m, 8), coerce-integer-to-machine-word(#xFF))) end end end method; let native-word-size = truncate/($machine-word-size, 8); *target-machine-word-mask* := make(, low: build(min(native-word-size, word-size())), high: build(max(0, word-size() - native-word-size))) end end function target-machine-word-mask; define variable *sign-extension-shift* :: false-or() = #f; /// Compute the shift count needed to sign extend a for the /// target system in a on the local system. define function sign-extension-shift () => (shift :: ) *sign-extension-shift* | begin *sign-extension-shift* := 2 * $machine-word-size - 8 * word-size() end end function sign-extension-shift; /// Extracts the operand to a primitive as an /// taking care to mask the value of the operand to the size of a /// on the target system. define inline-only function extract-mw-operand-unsigned (rx :: <&raw-machine-word>) => (x :: ) select (rx by instance?) <&raw-integer> => generic/logand(^raw-object-value(rx), target-machine-word-mask()); <&raw-byte-character> => // No need to mask as s are always positive and "small" ... as(, ^raw-object-value(rx)); <&raw-machine-word> => let x = ^raw-object-value(rx); select (x by instance?) => generic/logand(x, target-machine-word-mask()); => // No need to mask as s are always positive and "small" ... as(, x); => //---*** NOTE: Should be coerce-machine-word-to-unsigned-abstract-integer(x) //---*** but the primitive that implements it is broken! generic/logand(make(, low: x, high: coerce-integer-to-machine-word(0)), target-machine-word-mask()) end end end function extract-mw-operand-unsigned; define inline-only function sign-extend (x :: ) => (x :: ) generic/ash(generic/lsh(generic/logand(x, target-machine-word-mask()), sign-extension-shift()), - sign-extension-shift()) end function sign-extend; /// Extracts the operand to a primitive as an /// while ensuring that the operand's sign is properly extended. define inline-only function extract-mw-operand-signed (rx :: <&raw-machine-word>) => (x :: ) select (rx by instance?) <&raw-integer> => ^raw-object-value(rx); <&raw-byte-character> => as(, ^raw-object-value(rx)); <&raw-machine-word> => let x = ^raw-object-value(rx); select (x by instance?) => x; => // TODO: the compiler should figure this out, but it doesn't let x :: = x; sign-extend(x); => // No need to mask as s are always positive and "small" ... as(, x); => //---*** NOTE: Should be coerce-machine-word-to-unsigned-abstract-integer(x) //---*** but the primitive that implements it is broken! sign-extend(make(, low: x, high: coerce-integer-to-machine-word(0))); end end end function extract-mw-operand-signed; /// Identical to make-raw-literal but checks that the value will actually /// fit into a on the target system for use by folders for /// primitives which are supposed to signal overflow. define inline-only function make-raw-literal-with-overflow (object :: ) => (literal :: <&raw-machine-word>) if (instance?(object, )) make-raw-literal(object) elseif (begin let inverse-mask = generic/lognot(target-machine-word-mask()); let sign = generic/ash(generic/logand(object, inverse-mask), - sign-extension-shift()); let signed-result = sign-extend(object); (sign = 0 & ~negative?(signed-result)) | (sign = -1 & negative?(signed-result)) end) make-raw-literal(object) else // Should cause the folder/optimizer to punt ... error(" won't fit in ") end end function make-raw-literal-with-overflow;