DEFINITION MODULE LowLevel;

	(********************************************************)
	(*							*)
	(*	   Miscellaneous low-level procedures		*)
	(*							*)
	(*  Programmer:		P. Moylan			*)
	(*  Last edited:	11 March 1995			*)
	(*  Status:		OK				*)
	(*							*)
	(*	This is a "documentation" version of		*)
	(*	LowLevel.DEF.  It is provided because the	*)
	(*	original is hard to read, being full of		*)
	(*	compiler pragmas and in-line machine code.	*)
	(*							*)
	(********************************************************)

FROM SYSTEM IMPORT
    (* type *)	BYTE, WORD, ADDRESS;

FROM Types IMPORT
    (* type *)	FarPointer;

(************************************************************************)
(*			    BITWISE LOGIC				*)
(************************************************************************)

PROCEDURE IAND (first, second: WORD): WORD;

    (* Bit-by-bit logical AND.	*)

PROCEDURE IANDB (first, second: BYTE): BYTE;

    (* Bit-by-bit logical AND for bytes. *)

PROCEDURE IOR (first, second: WORD): WORD;

    (* Bit-by-bit inclusive OR.	*)

PROCEDURE IORB (first, second: BYTE): BYTE;

    (* Bit-by-bit inclusive OR.	*)

PROCEDURE IXOR (first, second: WORD): WORD;

    (* Bit-by-bit exclusive OR.	*)

PROCEDURE IXORB (first, second: BYTE): BYTE;

    (* Bit-by-bit exclusive OR.	*)

PROCEDURE INOT (value: WORD): WORD;

    (* Bit-by-bit Boolean complement.	*)

PROCEDURE INOTB (value: BYTE): BYTE;

    (* Bit-by-bit Boolean complement.	*)

PROCEDURE ROL (value: WORD;  count: CARDINAL): WORD;

    (* Left rotation of "value" by "count" bit positions.	*)

PROCEDURE ROLB (value: BYTE;  count: CARDINAL): BYTE;

    (* Left rotation of "value" by "count" bit positions.	*)

PROCEDURE LS (value: WORD;  count: CARDINAL): WORD;

    (* Left shift of "value" by "count" bit positions, with zero fill.	*)

PROCEDURE LSB (value: BYTE;  count: CARDINAL): BYTE;

    (* Left shift of "value" by "count" bit positions, with zero fill.	*)

PROCEDURE ROR (value: WORD;  count: CARDINAL): WORD;

    (* Right rotation of "value" by "count" bit positions.	*)

PROCEDURE RORB (value: BYTE;  count: CARDINAL): BYTE;

    (* Right rotation of "value" by "count" bit positions.	*)

PROCEDURE RS (value: WORD;  count: CARDINAL): WORD;

    (* Right shift of "value" by "count" bit positions, with zero fill.	*)

PROCEDURE RSB (value: BYTE;  count: CARDINAL): BYTE;

    (* Right shift of "value" by "count" bit positions, with zero fill.	*)

(************************************************************************)
(*			    POINTER OPERATIONS				*)
(************************************************************************)

PROCEDURE Far (A: ADDRESS): FarPointer;

    (* Converts a pointer to a far pointer. *)

PROCEDURE MakePointer (segment, offset: WORD): FarPointer;

    (* Creates a pointer, given the segment and offset within segment.	*)

PROCEDURE SEGMENT (A: ADDRESS): WORD;

    (* Returns the segment part of an address.	*)

PROCEDURE FarSEGMENT (A: FarPointer): WORD;

    (* Returns the segment part of an address.	*)

PROCEDURE OFFSET (A: ADDRESS): WORD;

    (* Returns the offset part of an address.	*)

PROCEDURE AddOffset (A: ADDRESS;  increment: CARDINAL): ADDRESS;

    (* Returns a pointer to the memory location whose physical address	*)
    (* is Physical(A)+increment.  In the present version, it is assumed	*)
    (* that the caller will never try to run off the end of a segment.	*)

PROCEDURE SubtractOffset (A: ADDRESS;  decrement: CARDINAL): ADDRESS;

    (* Like AddOffset, except that we go backwards in memory.  Running	*)
    (* off the beginning of the segment is an undetected error.		*)

PROCEDURE FarAddOffset (A: FarPointer;  increment: CARDINAL): FarPointer;

    (* Like AddOffset, except for the parameter types. *)

PROCEDURE FarSubtractOffset (A: FarPointer; decrement: CARDINAL): FarPointer;

    (* Like SubtractOffset, except for the parameter types. *)

PROCEDURE Virtual (PA: LONGCARD): FarPointer;

    (* Converts a physical address to a virtual address, if possible.	*)
    (* There are no guarantees in the case where there is no such	*)
    (* virtual address.							*)

PROCEDURE Physical (A: ADDRESS): LONGCARD;

    (* Converts a virtual address to a physical address.  Use with care!*)

(************************************************************************)
(*			BYTE/WORD/LONGCARD CONVERSIONS			*)
(************************************************************************)

PROCEDURE LowByte (w: WORD): BYTE;

    (* Returns the low-order byte of its argument.	*)

PROCEDURE HighByte (w: WORD): BYTE;

    (* Returns the high-order byte of its argument.	*)

PROCEDURE MakeWord (high, low: BYTE): WORD;

    (* Combines two bytes into a word.  The first argument becomes the	*)
    (* most significant byte of the result.				*)

PROCEDURE SignExtend (val: BYTE): INTEGER;

    (* Converts a signed 8-bit number to signed integer. *)

PROCEDURE LowWord (w: LONGCARD): WORD;

    (* Returns the low-order word of its argument.	*)

PROCEDURE HighWord (w: LONGCARD): WORD;

    (* Returns the high-order word of its argument.	*)

PROCEDURE MakeLongword (high, low: WORD): LONGCARD;

    (* Combines two words into a longword.  The first argument becomes	*)
    (* the most significant word of the result.				*)

(************************************************************************)
(*			MISCELLANEOUS ARITHMETIC			*)
(************************************************************************)

PROCEDURE INCV (VAR (*INOUT*) dest: CARDINAL;  src: CARDINAL): BOOLEAN;

    (* Computes dest := dest + src, and returns TRUE iff the addition	*)
    (* produced a carry.						*)

PROCEDURE INCVB (VAR (*INOUT*) dest: BYTE;  src: BYTE): BOOLEAN;

    (* Computes dest := dest + src, and returns TRUE iff the addition	*)
    (* produced a carry.						*)

PROCEDURE DECV (VAR (*INOUT*) dest: CARDINAL;  src: CARDINAL): BOOLEAN;

    (* Computes dest := dest - src, and returns TRUE iff the		*)
    (* subtraction produced a borrow.					*)

PROCEDURE DECVB (VAR (*INOUT*) dest: BYTE;  src: BYTE): BOOLEAN;

    (* Computes dest := dest - src, and returns TRUE iff the		*)
    (* subtraction produced a borrow.					*)

PROCEDURE Mul (A, B: CARDINAL): LONGCARD;

    (* Same as A*B, except for the type of the result.  We provide this	*)
    (* as a general-purpose function since this combination of operands	*)
    (* is often precisely what is wanted.				*)

PROCEDURE MulB (A, B: BYTE): CARDINAL;

    (* Same as A*B, except for the type of the result.  We provide this	*)
    (* as a general-purpose function since this combination of operands	*)
    (* is often precisely what is wanted.				*)

PROCEDURE IMul (A, B: INTEGER): LONGINT;

    (* Like Mul, but signed. *)

PROCEDURE IMulB (A, B: BYTE): INTEGER;

    (* Like MulB, but signed. *)

PROCEDURE DivB (A: CARDINAL;  B: BYTE): BYTE;

    (* Same as A DIV B, except for the type of A.  We provide this as	*)
    (* a general-purpose function since this combination of operands	*)
    (* is often precisely what is wanted.				*)

PROCEDURE Div (A: LONGCARD;  B: CARDINAL): CARDINAL;

    (* Same as A DIV B, except for the type of A.  We provide this as	*)
    (* a general-purpose function since this combination of operands	*)
    (* is often precisely what is wanted.				*)

(************************************************************************)
(*			     BLOCK MOVES				*)
(************************************************************************)

PROCEDURE Copy (source, destination: ADDRESS;  bytecount: CARDINAL);

    (* Copies an array of bytes from the source address to the		*)
    (* destination address.  In the case where the two arrays overlap,	*)
    (* the destination address should be lower in physical memory than	*)
    (* the source address.						*)

PROCEDURE FarCopy (source, destination: FarPointer;  bytecount: CARDINAL);

    (* Copies an array of bytes from the source address to the		*)
    (* destination address.  In the case where the two arrays overlap,	*)
    (* the destination address should be lower in physical memory than	*)
    (* the source address.						*)

PROCEDURE CopyUp (source, destination: FarPointer;  bytecount: CARDINAL);

    (* A variant of Copy which does the move backwards, in order	*)
    (* to handle the case where the destination address is inside the	*)
    (* source array.  In this special case Copy cannot be used,		*)
    (* because it would overwrite data it was about to copy.		*)

PROCEDURE BlockFill (destination: FarPointer;
				bytecount: CARDINAL;  value: BYTE);

    (* Fills the destination array with the given value.	*)

PROCEDURE BlockFillWord (destination: FarPointer;  wordcount: CARDINAL;
							value: WORD);

    (* Fills the destination array with the given value.	*)

(************************************************************************)
(*			    INPUT AND OUTPUT				*)
(************************************************************************)

PROCEDURE OutByte (port: CARDINAL; value: BYTE);

    (* Puts the value out to an output port.	*)

PROCEDURE InByte (port: CARDINAL): BYTE;

    (* Reads a byte from an input port.	*)

PROCEDURE InStringWord (port: CARDINAL;  BufferAddress: ADDRESS;
						count: CARDINAL);

    (* Reads count words from an input port.	*)

PROCEDURE OutStringWord (port: CARDINAL;  BufferAddress: ADDRESS;
						count: CARDINAL);

    (* Writes count words to an output port.	*)

END LowLevel.
