DEFINITION MODULE LowLevel; (********************************************************) (* *) (* Miscellaneous low-level procedures *) (* *) (* Programmer: P. Moylan *) (* Last edited: 1 September 1998 *) (* Status: Working *) (* *) (* 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: Much of this module was originally *) (* designed for 16-bit words, and I'm gradually *) (* changing 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 *) CARD8, INT8, CARD16, INT16, LOC, ADDRESS; FROM Types IMPORT (* type *) FarPointer; (************************************************************************) (* MISCELLANEOUS *) (************************************************************************) PROCEDURE EVAL (f: ARRAY OF LOC); (* A do-nothing procedure - we use it for evaluating a function and *) (* ignoring the result. *) PROCEDURE Assert (arg: BOOLEAN); (* Halts the program if arg is FALSE. *) (************************************************************************) (* STORAGE ALLOCATION *) (************************************************************************) PROCEDURE ALLOCATE64 (VAR (*OUT*) p: ADDRESS; amount: CARDINAL); (* Like Storage.ALLOCATE, but this procedure tries to ensure that *) (* the allocated block does not cross a 64K boundary in memory. *) (* This restriction is required when passing data to and from the *) (* 16-bit API procedures (Vio, etc.) *) (************************************************************************) (* BITWISE LOGIC *) (************************************************************************) PROCEDURE IAND (first, second: CARDINAL): CARDINAL; (* Bit-by-bit logical AND. *) PROCEDURE IANDB (first, second: CARD8): CARD8; (* Bit-by-bit logical AND for bytes. *) PROCEDURE IOR (first, second: CARDINAL): CARDINAL; (* Bit-by-bit inclusive OR. *) PROCEDURE IORB (first, second: CARD8): CARD8; (* Bit-by-bit inclusive OR. *) PROCEDURE IXOR (first, second: CARDINAL): CARDINAL; (* Bit-by-bit exclusive OR. *) PROCEDURE IXORB (first, second: CARD8): CARD8; (* Bit-by-bit exclusive OR. *) PROCEDURE INOT (value: CARDINAL): CARDINAL; (* Bit-by-bit Boolean complement. *) PROCEDURE INOTB (value: CARD8): CARD8; (* Bit-by-bit Boolean complement. *) PROCEDURE ROL (value: CARDINAL; count: CARDINAL): CARDINAL; (* Left rotation of "value" by "count" bit positions. *) PROCEDURE ROLB (value: CARD8; count: CARDINAL): CARD8; (* Left rotation of "value" by "count" bit positions. *) PROCEDURE LS (value: CARDINAL; count: CARDINAL): CARDINAL; (* Left shift of "value" by "count" bit positions, with zero fill. *) PROCEDURE LSB (value: CARD8; count: CARDINAL): CARD8; (* Left shift of "value" by "count" bit positions, with zero fill. *) PROCEDURE ROR (value: CARDINAL; count: CARDINAL): CARDINAL; (* Right rotation of "value" by "count" bit positions. *) PROCEDURE RORB (value: CARD8; count: CARDINAL): CARD8; (* 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: CARD8; count: CARDINAL): CARD8; (* 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: CARD16; offset: CARDINAL): 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): CARDINAL; (* 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: CARDINAL): CARD8; (* Returns the low-order byte of its argument. *) PROCEDURE HighByte (w: CARD16): CARD8; (* Returns the high-order byte of its argument. *) PROCEDURE MakeWord (high, low: CARD8): CARD16; (* Combines two bytes into a word. The first argument becomes the *) (* most significant byte of the result. *) PROCEDURE SignExtend (val: INT8): INTEGER; (* Converts a signed 8-bit number to signed integer. *) PROCEDURE LowWord (w: CARDINAL): CARD16; (* Returns the low-order word of its argument. *) PROCEDURE HighWord (w: CARDINAL): CARD16; (* Returns the high-order word of its argument. *) PROCEDURE MakeLongword (high, low: CARD16): CARDINAL; (* 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: CARD8; src: CARD8): 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: CARD8; src: CARD8): 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: CARD8): 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: INT8): INT16; (* Like MulB, but signed. *) PROCEDURE DivB (A: CARD16; B: CARD8): CARD8; (* 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: CARD8); (* Fills the destination array with the given value. *) PROCEDURE BlockFillWord (destination: FarPointer; wordcount: CARDINAL; value: CARD16); (* Fills the destination array with the given value. *) (************************************************************************) (* INPUT AND OUTPUT *) (* I haven't yet worked out how to do this in OS/2 *) (************************************************************************) (*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.