DEFINITION MODULE LowLevel;

        (********************************************************)
        (*                                                      *)
        (*         Miscellaneous low-level procedures           *)
        (*                                                      *)
        (*  Programmer:         P. Moylan                       *)
        (*  Last edited:        30 July 1996                    *)
        (*  Status:             Working on XDS port             *)
        (*                                                      *)
        (*      Now appears to be working, but:                 *)
        (*       (a) untested, more checking needed;            *)
        (*       (b) it's still not clear that what's           *)
        (*           provided is what the clients needed,       *)
        (*           particularly in relation to 16 bit/32 bit  *)
        (*           distinctions.                              *)
        (*                                                      *)
        (*      Note that the implementation of this module     *)
        (*      is heavily compiler-dependent.  This version    *)
        (*      is for use with the XDS compiler,               *)
        (*                                                      *)
        (*      NOTE: Many of the procedures in this module     *)
        (*      assume a 16-bit word, so I'll have to change    *)
        (*      that.  What I need to look at is what the       *)
        (*      client modules really need (e.g. who really     *)
        (*      uses a procedure like "HighByte").              *)
        (*                                                      *)
        (*      NOTE: Some procedures commented out, because I  *)
        (*      haven't yet worked out the details.             *)
        (*                                                      *)
        (********************************************************)

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

FROM Types IMPORT
    (* type *)  FarPointer;

TYPE
    LONGCARD = CARDINAL;
    LONGINT = INTEGER;

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

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

    (* 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, count: CARDINAL): CARDINAL;

    (* 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): CARD16;

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

PROCEDURE FarSEGMENT (A: FarPointer): CARD16;

    (* 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): CARD16;

    (* 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: CARD16): 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 MulB (A, B: BYTE): CARD16;

    (* 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: INT16): INTEGER;

    (* Like Mul, but signed. *)

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

    (* Like MulB, but signed. *)

PROCEDURE DivB (A: CARD16;  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: CARDINAL;  B: CARD16): CARD16;

    (* 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.
