language-Modula2-0.1: examples/Modula-2_Libraries/PMOS/sources/general/lowlevel.def
DEFINITION MODULE LowLevel;
(********************************************************)
(* *)
(* Miscellaneous low-level procedures *)
(* *)
(* Programmer: P. Moylan *)
(* Last edited: 11 March 1995 *)
(* Status: OK *)
(* *)
(* Note that the implementation of this module *)
(* is heavily compiler-dependent. This version *)
(* is for use with the TopSpeed compiler, *)
(* version 1 or version 3. *)
(* *)
(* Now making changes so that I can use it with *)
(* more compilers. *)
(* *)
(********************************************************)
FROM SYSTEM IMPORT
(* type *) BYTE, WORD, ADDRESS;
FROM Types IMPORT
(* type *) FarPointer;
(*<TopSpeed3*)
(*# module (init_code => off) *)
CONST
(*%T _fcall *)
Ret = 0CBH;
(*%E *)
(*%F _fcall *)
Ret = 0C3H;
(*%E *)
TYPE
Code1=ARRAY [0..0] OF BYTE;
Code2=ARRAY [0..1] OF BYTE;
Code3=ARRAY [0..2] OF BYTE;
Code5=ARRAY [0..4] OF BYTE;
Code7=ARRAY [0..6] OF BYTE;
Code9=ARRAY [0..8] OF BYTE;
(*>*)
(************************************************************************)
(* BITWISE LOGIC *)
(************************************************************************)
(*<TopSpeed3*)
(*# save, call(inline => on, reg_param => (ax, bx), reg_return => (ax)) *)
(*# call(reg_saved => (bx,cx,dx,si,di,ds,es,st1,st2)) *)
INLINE (*>*)
PROCEDURE IAND (first, second: WORD): WORD
(* Bit-by-bit logical AND. *)
(*<TopSpeed3*) = Code3 (21H, 0D8H, Ret) (* and ax, bx *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE IANDB (first, second: BYTE): BYTE
(* Bit-by-bit logical AND for bytes. *)
(*<TopSpeed3*) = Code3 (21H, 0D8H, Ret) (* and ax, bx *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE IOR (first, second: WORD): WORD
(* Bit-by-bit inclusive OR. *)
(*<TopSpeed3*) = Code3 (09H, 0D8H, Ret) (* or ax, bx *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE IORB (first, second: BYTE): BYTE
(* Bit-by-bit inclusive OR. *)
(*<TopSpeed3*) = Code3 (09H, 0D8H, Ret) (* or ax, bx *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE IXOR (first, second: WORD): WORD
(* Bit-by-bit exclusive OR. *)
(*<TopSpeed3*) = Code3 (31H, 0D8H, Ret) (* xor ax, bx *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE IXORB (first, second: BYTE): BYTE
(* Bit-by-bit exclusive OR. *)
(*<TopSpeed3*) = Code3 (31H, 0D8H, Ret) (* xor ax, bx *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE INOT (value: WORD): WORD
(* Bit-by-bit Boolean complement. *)
(*<TopSpeed3*) = Code3 (0F7H, 0D0H, Ret) (* not ax *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE INOTB (value: BYTE): BYTE
(* Bit-by-bit Boolean complement. *)
(*<TopSpeed3*) = Code3 (0F7H, 0D0H, Ret) (* not ax *) (*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on, reg_param => (ax, cx), reg_return => (ax)) *)
INLINE (*>*)
PROCEDURE ROL (value: WORD; count: CARDINAL): WORD
(* Left rotation of "value" by "count" bit positions. *)
(*<TopSpeed3*) = Code3 (0D3H, 0C0H, Ret) (* rol ax, cl *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE ROLB (value: BYTE; count: CARDINAL): BYTE
(* Left rotation of "value" by "count" bit positions. *)
(*<TopSpeed3*) = Code3 (0D2H, 0C0H, Ret) (* rol al, cl *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE LS (value: WORD; count: CARDINAL): WORD
(* Left shift of "value" by "count" bit positions, with zero fill. *)
(*<TopSpeed3*) = Code3 (0D3H, 0E0H, Ret) (* shl ax, cl *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE LSB (value: BYTE; count: CARDINAL): BYTE
(* Left shift of "value" by "count" bit positions, with zero fill. *)
(*<TopSpeed3*) = Code3 (0D2H, 0E0H, Ret) (* shl al, cl *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE ROR (value: WORD; count: CARDINAL): WORD
(* Right rotation of "value" by "count" bit positions. *)
(*<TopSpeed3*) = Code3 (0D3H, 0C8H, Ret) (* ror ax, cl *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE RORB (value: BYTE; count: CARDINAL): BYTE
(* Right rotation of "value" by "count" bit positions. *)
(*<TopSpeed3*) = Code3 (0D2H, 0C8H, Ret) (* ror al, cl *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE RS (value: WORD; count: CARDINAL): WORD
(* Right shift of "value" by "count" bit positions, with zero fill. *)
(*<TopSpeed3*) = Code3 (0D3H, 0E8H, Ret) (* shr ax, cl *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE RSB (value: BYTE; count: CARDINAL): BYTE
(* Right shift of "value" by "count" bit positions, with zero fill. *)
(*<TopSpeed3*)
= Code3 (0D2H, 0E8H, Ret) (* shr al, cl *)
(*>*);
(************************************************************************)
(* POINTER OPERATIONS *)
(************************************************************************)
(*<TopSpeed3*)
(*# call(reg_param => (ax,dx), reg_return => (ax,dx)) *)
(*# call(reg_saved => (bx,cx,si,di,ds,es,st1,st2)) *)
INLINE (*>*)
PROCEDURE Far (A: ADDRESS): FarPointer
(* Converts a pointer to a far pointer. *)
(*<TopSpeed3*)
(*%T _fptr *)
= Code1 (Ret)
(*%E*)
(*%F _fptr *)
= Code3 (8CH,0DAH,Ret) (* mov dx, ds *)
(*%E*)
(*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(reg_param => (dx, ax), reg_return => (ax,dx)) *)
INLINE (*>*)
PROCEDURE MakePointer (segment, offset: WORD): FarPointer
(* Creates a pointer, given the segment and offset within segment. *)
(*<TopSpeed3*)
= Code1 (Ret)
(*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(reg_param => (ax,bx), reg_return => (bx)) *)
(*# call(reg_saved => (cx,dx,si,di,ds,es,st1,st2)) *)
INLINE (*>*)
PROCEDURE SEGMENT (A: ADDRESS): WORD
(* Returns the segment part of an address. *)
(*<TopSpeed3*)
(*%T _fptr *)
= Code1 (Ret)
(*%E*)
(*%F _fptr *)
= Code3 (8CH, 0DBH, Ret) (* mov bx, ds *)
(*%E*)
(*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(reg_saved => (ax,bx,cx,dx,si,di,ds,es,st1,st2)) *)
INLINE (*>*)
PROCEDURE FarSEGMENT (A: FarPointer): WORD
(* Returns the segment part of an address. *)
(*<TopSpeed3*)
= Code1 (Ret)
(*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on, reg_param => (ax,bx), reg_return => (ax)) *)
INLINE (*>*)
PROCEDURE OFFSET (A: ADDRESS): WORD
(* Returns the offset part of an address. *)
(*<TopSpeed3*)
= Code1 (Ret)
(*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(reg_saved => (bx,cx,dx,si,di,ds,es,st1,st2)) *)
(*# call(reg_return => (ax,dx)) *)
(*%T _fptr *)
(*# call(reg_param => (ax,dx,bx)) *)
(*%E*)
(*%F _fptr *)
(*# call(reg_param => (ax,bx)) *)
(*%E*)
INLINE (*>*)
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. *)
(*<TopSpeed3*) = Code3 (01H, 0D8H, Ret) (* add ax, bx *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
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. *)
(*<TopSpeed3*) = Code3 (29H, 0D8H, Ret) (* sub ax, bx *) (*>*);
(************************************************************************)
(*<TopSpeed3*) (*# call(reg_param => (ax,dx,bx)) *)
INLINE (*>*)
PROCEDURE FarAddOffset (A: FarPointer; increment: CARDINAL): FarPointer
(* Like AddOffset, except for the parameter types. *)
(*<TopSpeed3*) = Code3 (01H, 0D8H, Ret) (* add ax, bx *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE FarSubtractOffset (A: FarPointer; decrement: CARDINAL): FarPointer
(* Like SubtractOffset, except for the parameter types. *)
(*<TopSpeed3*) = Code3 (29H, 0D8H, Ret) (* sub ax, bx *) (*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => off) *)
(*# call(reg_param => (ax, dx), reg_return => (dx, ax)) *)
(*# call(reg_saved => (bx,cx,si,di,ds,es,st1,st2)) *)
(*>*)
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. *)
(************************************************************************)
(*<TopSpeed3*)
(*# call(reg_param => (ax,bx), reg_return => (ax, bx)) *)
(*# call(reg_saved => (cx,dx,si,di,ds,es,st1,st2)) *)
(*>*)
PROCEDURE Physical (A: ADDRESS): LONGCARD;
(* Converts a virtual address to a physical address. Use with care!*)
(************************************************************************)
(* BYTE/WORD/LONGCARD CONVERSIONS *)
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on, reg_param => (ax), reg_return => (ax)) *)
(*# call(reg_saved => (bx,cx,dx,si,di,ds,es,st1,st2)) *)
INLINE (*>*)
PROCEDURE LowByte (w: WORD): BYTE
(* Returns the low-order byte of its argument. *)
(*<TopSpeed3*) = Code1 (Ret) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE HighByte (w: WORD): BYTE
(* Returns the high-order byte of its argument. *)
(*<TopSpeed3*) = Code3 (88H, 0E0H, Ret) (* mov al, ah *) (*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(reg_param => (bx, ax), reg_return => (ax)) *)
INLINE (*>*)
PROCEDURE MakeWord (high, low: BYTE): WORD
(* Combines two bytes into a word. The first argument becomes the *)
(* most significant byte of the result. *)
(*<TopSpeed3*)
= Code3 (8AH, 0E3H, Ret) (* mov ah, bl *)
(*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(reg_param => (ax), reg_return => (ax)) *)
INLINE (*>*)
PROCEDURE SignExtend (val: BYTE): INTEGER
(* Converts a signed 8-bit number to signed integer. *)
(*<TopSpeed3*)
= Code2 (98H, Ret) (* cbw *)
(*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on, reg_param => (ax,bx), reg_return => (ax)) *)
INLINE (*>*)
PROCEDURE LowWord (w: LONGCARD): WORD
(* Returns the low-order word of its argument. *)
(*<TopSpeed3*)
= Code1 (Ret)
(*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on, reg_param => (bx, ax), reg_return => (ax)) *)
INLINE (*>*)
PROCEDURE HighWord (w: LONGCARD): WORD
(* Returns the high-order word of its argument. *)
(*<TopSpeed3*)
= Code1 (Ret)
(*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on, reg_param => (dx,ax), reg_return => (ax,dx)) *)
INLINE (*>*)
PROCEDURE MakeLongword (high, low: WORD): LONGCARD
(* Combines two words into a longword. The first argument becomes *)
(* the most significant word of the result. *)
(*<TopSpeed3*)
= Code1 (Ret)
(*>*);
(************************************************************************)
(* MISCELLANEOUS ARITHMETIC *)
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on, reg_return => (ax)) *)
(*%T _fptr *)
(*%T _fdata*)
(*# call(reg_param => (si,ds,ax)) *)
(*%E*)
(*%F _fdata*)
(*# call(reg_param => (si,bx,ax)) *)
(*%E*)
(*%E*)
(*%F _fptr *)
(*# call(reg_param => (si,ax)) *)
(*%E*)
INLINE (*>*)
PROCEDURE INCV (VAR (*INOUT*) dest: CARDINAL; src: CARDINAL): BOOLEAN
(* Computes dest := dest + src, and returns TRUE iff the addition *)
(* produced a carry. *)
(*<TopSpeed3*)
(*%F _fptr *)
= Code5 (01H, 04H, 1BH, 0C0H, Ret) (* add [si], ax; sbb ax, ax *)
(*%E*)
(*%T _fptr *)
(*%T _fdata*)
= Code5 (01H, 04H, 1BH, 0C0H, Ret) (* add [si], ax; sbb ax, ax *)
(*%E*)
(*%F _fdata*)
= Code9 (01EH, 08EH, 0DBH, (* push ds; mov ds, bx; *)
01H, 04H, 1BH, 0C0H, (* add [si], ax; sbb ax, ax; *)
01FH, Ret) (* pop ds *)
(*%E*)
(*%E*)
(*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE INCVB (VAR (*INOUT*) dest: BYTE; src: BYTE): BOOLEAN
(* Computes dest := dest + src, and returns TRUE iff the addition *)
(* produced a carry. *)
(*<TopSpeed3*)
(*%F _fptr *)
= Code5 (00H, 04H, 1BH, 0C0H, Ret) (* add [si], al; sbb ax, ax *)
(*%E*)
(*%T _fptr *)
(*%T _fdata*)
= Code5 (00H, 04H, 1BH, 0C0H, Ret) (* add [si], al; sbb ax, ax *)
(*%E*)
(*%F _fdata*)
= Code9 (01EH, 08EH, 0DBH, (* push ds; mov ds, bx; *)
00H, 04H, 1BH, 0C0H, (* add [si], al; sbb ax, ax; *)
01FH, Ret) (* pop ds *)
(*%E*)
(*%E*)
(*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE DECV (VAR (*INOUT*) dest: CARDINAL; src: CARDINAL): BOOLEAN
(* Computes dest := dest - src, and returns TRUE iff the *)
(* subtraction produced a borrow. *)
(*<TopSpeed3*)
(*%F _fptr *)
= Code5 (29H, 04H, 1BH, 0C0H, Ret) (* sub [si], ax; sbb ax, ax *)
(*%E*)
(*%T _fptr *)
(*%T _fdata*)
= Code5 (29H, 04H, 1BH, 0C0H, Ret) (* sub [si], ax; sbb ax, ax *)
(*%E*)
(*%F _fdata*)
= Code9 (01EH, 08EH, 0DBH, (* push ds; mov ds, bx; *)
29H, 04H, 1BH, 0C0H, (* sub [si], ax; sbb ax, ax; *)
01FH, Ret) (* pop ds *)
(*%E*)
(*%E*)
(*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE DECVB (VAR (*INOUT*) dest: BYTE; src: BYTE): BOOLEAN
(* Computes dest := dest - src, and returns TRUE iff the *)
(* subtraction produced a borrow. *)
(*<TopSpeed3*)
(*%F _fptr *)
= Code5 (28H, 04H, 1BH, 0C0H, Ret) (* sub [si], al; sbb ax, ax *)
(*%E*)
(*%T _fptr *)
(*%T _fdata*)
= Code5 (28H, 04H, 1BH, 0C0H, Ret) (* sub [si], al; sbb ax, ax *)
(*%E*)
(*%F _fdata*)
= Code9 (01EH, 08EH, 0DBH, (* push ds; mov ds, bx; *)
28H, 04H, 1BH, 0C0H, (* sub [si], al; sbb ax, ax; *)
01FH, Ret) (* pop ds *)
(*%E*)
(*%E*)
(*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on, reg_param => (ax, bx), reg_return => (ax,dx)) *)
(*# call(reg_saved => (bx,cx,si,di,ds,es,st1,st2)) *)
INLINE (*>*)
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. *)
(*<TopSpeed3*) = Code3 (0F7H, 0E3H, Ret) (* mul bx *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
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. *)
(*<TopSpeed3*) = Code3 (0F6H, 0E3H, Ret) (* mul bl *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE IMul (A, B: INTEGER): LONGINT
(* Like Mul, but signed. *)
(*<TopSpeed3*) = Code3 (0F7H, 0EBH, Ret) (* imul bx *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE IMulB (A, B: BYTE): INTEGER
(* Like MulB, but signed. *)
(*<TopSpeed3*) = Code3 (0F6H, 0EBH, Ret) (* imul bl *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
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. *)
(*<TopSpeed3*)
= Code3 (0F6H, 0F3H, Ret) (* div bl *)
(*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on, reg_param => (ax,dx,bx), reg_return => (ax)) *)
INLINE (*>*)
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. *)
(*<TopSpeed3*)
= Code3 (0F7H, 0F3H, Ret) (* div bx *)
(*>*);
(************************************************************************)
(* BLOCK MOVES *)
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on) *)
(*# call(reg_saved => (ax,bx,dx,ds,st1,st2)) *)
(*%T _fptr*)
(*%T _fdata*)
(*# call(reg_param => (si, ds, di, es, cx)) *)
(*%E*)
(*%F _fdata*)
(*# call(reg_param => (si, ax, di, es, cx)) *)
(*%E*)
(*%E*)
(*%F _fptr*)
(*# call(reg_param => (si, di, cx)) *)
(*%E*)
INLINE (*>*)
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. *)
(*<TopSpeed3*)
(*%T _fptr*)
(*%T _fdata*)
= Code3 (0F3H, 0A4H, Ret) (* rep movsb *)
(*%E*)
(*%F _fdata*)
= Code7 (01EH, 08EH, 0D8H, (* push ds; mov ds, ax; *)
0F3H, 0A4H, 01FH, Ret) (* rep movsb; pop ds *)
(*%E*)
(*%E*)
(*%F _fptr*)
= Code5 (01EH,07H,0F3H,0A4H,Ret) (* push ds; pop es; rep movsb *)
(*%E*)
(*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on) *)
(*# call(reg_saved => (ax,bx,dx,ds,es,st1,st2)) *)
(*%T _fdata*)
(*# call(reg_param => (si, ds, di, es, cx)) *)
(*%E*)
(*%F _fdata*)
(*# call(reg_param => (si, ax, di, es, cx)) *)
(*%E*)
INLINE (*>*)
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. *)
(*<TopSpeed3*)
(*%T _fdata*)
= Code3 (0F3H, 0A4H, Ret) (* rep movsb *)
(*%E*)
(*%F _fdata*)
= Code7 (01EH, 08EH, 0D8H, (* push ds; mov ds, ax; *)
0F3H, 0A4H, 01FH, Ret) (* rep movsb; pop ds *)
(*%E*)
(*>*);
(************************************************************************)
(*<TopSpeed3*)(*# call(inline => off) *) (*>*)
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. *)
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on, reg_param => (di, es, cx, ax)) *)
(*# call(reg_saved => (ax,bx,dx,si,ds,es,st1,st2)) *)
INLINE (*>*)
PROCEDURE BlockFill (destination: FarPointer;
bytecount: CARDINAL; value: BYTE)
(* Fills the destination array with the given value. *)
(*<TopSpeed3*) = Code3 (0F3H, 0AAH, Ret) (* rep stosb *) (*>*);
(************************************************************************)
(*<TopSpeed3*) INLINE (*>*)
PROCEDURE BlockFillWord (destination: FarPointer; wordcount: CARDINAL;
value: WORD)
(* Fills the destination array with the given value. *)
(*<TopSpeed3*)
= Code3 (0F3H, 0ABH, Ret) (* rep stosw *)
(*>*);
(************************************************************************)
(* INPUT AND OUTPUT *)
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on, reg_param => (dx, ax)) *)
(*# call(reg_saved => (bx,cx,dx,si,di,ds,es,st1,st2)) *)
INLINE (*>*)
PROCEDURE OutByte (port: CARDINAL; value: BYTE)
(* Puts the value out to an output port. *)
(*<TopSpeed3*) = Code2 (0EEH, Ret) (*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => on, reg_param => (dx), reg_return => (ax)) *)
INLINE (*>*)
PROCEDURE InByte (port: CARDINAL): BYTE
(* Reads a byte from an input port. *)
(*<TopSpeed3*)
= Code2 (0ECH, Ret)
(*>*);
(************************************************************************)
(*<TopSpeed3*)
(*# call(inline => off) *)
(*# call(reg_saved => (ax,bx,dx,si,di,ds,es,st1,st2)) *)
(*%T _fptr *)
(*# call(reg_param => (dx, di, es, cx)) *)
(*%E*)
(*%F _fptr *)
(*# call(reg_param => (dx, di, cx)) *)
(*%E*)
(*>*)
PROCEDURE InStringWord (port: CARDINAL; BufferAddress: ADDRESS;
count: CARDINAL);
(* Reads count words from an input port. *)
(************************************************************************)
(*<TopSpeed3*)
(*%T _fptr*)
(*%T _fdata*)
(*# call(reg_param => (dx, si, ds, cx)) *)
(*%E*)
(*%F _fdata*)
(*# call(reg_param => (dx, si, ax, cx)) *)
(*%E*)
(*%E*)
(*%F _fptr*)
(*# call(reg_param => (dx, si, cx)) *)
(*%E*)
(*>*)
PROCEDURE OutStringWord (port: CARDINAL; BufferAddress: ADDRESS;
count: CARDINAL);
(* Writes count words to an output port. *)
(************************************************************************)
(*<TopSpeed3*) (*# restore *) (*>*)
END LowLevel.