home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pmos2002.zip / SRC / LOWLEVEL.MOD < prev    next >
Text File  |  1996-09-27  |  25KB  |  838 lines

  1. IMPLEMENTATION MODULE LowLevel;
  2.  
  3.         (********************************************************)
  4.         (*                                                      *)
  5.         (*         Miscellaneous low-level procedures           *)
  6.         (*                                                      *)
  7.         (*  Programmer:         P. Moylan                       *)
  8.         (*  Last edited:        27 September 1996               *)
  9.         (*  Status:             Working on XDS port             *)
  10.         (*                                                      *)
  11.         (*      Now appears to be working, but:                 *)
  12.         (*       (a) untested, more checking needed;            *)
  13.         (*       (b) it's still not clear that what's           *)
  14.         (*           provided is what the clients needed,       *)
  15.         (*           particularly in relation to 16 bit/32 bit  *)
  16.         (*           distinctions.                              *)
  17.         (*                                                      *)
  18.         (********************************************************)
  19.  
  20. FROM SYSTEM IMPORT
  21.     (* type *)  CARD8, INT8, CARD16, INT16, ADDRESS,
  22.     (* proc *)  ROTATE, SHIFT, ADDADR, SUBADR, MOVE, FILL;
  23.  
  24. FROM Types IMPORT
  25.     (* type *)  FarPointer;
  26.  
  27. FROM Storage IMPORT
  28.     (* proc *)  ALLOCATE, DEALLOCATE;
  29.  
  30. (************************************************************************)
  31.  
  32. TYPE
  33.     t01 = [0..1];  t02 = [0..2];  t03 = [0..3];
  34.  
  35.     Word8 =  RECORD
  36.                 CASE :t01 OF
  37.                   | 0:  bits: SET OF [0..7];
  38.                   | 1:  c: CARD8;
  39.                 END (*CASE*);
  40.              END (*RECORD*);
  41.  
  42.     Word16 =  RECORD
  43.                 CASE :t02 OF
  44.                   | 0:  bits: BITSET;
  45.                   | 1:  low, high: CARD8;
  46.                   | 2:  c: CARD16;
  47.                 END (*CASE*);
  48.               END (*RECORD*);
  49.  
  50.     Word32 =  RECORD
  51.                 CASE :t03 OF
  52.                   | 0:  bits: BITSET;
  53.                   | 1:  low, high, higher, highest: CARD8;
  54.                   | 2:  c: CARDINAL;
  55.                   | 3:  a: ADDRESS;
  56.                 END (*CASE*);
  57.               END (*RECORD*);
  58.  
  59.     Double = RECORD
  60.                 CASE :t02 OF
  61.                   | 0:  low, high: CARD16;
  62.                   | 1:  lw: CARDINAL;
  63.                   | 2:  a: ADDRESS;
  64.                 END (*CASE*);
  65.              END (*RECORD*);
  66.  
  67. (************************************************************************)
  68. (*                      INTERNAL TYPE CONVERSIONS                       *)
  69. (************************************************************************)
  70.  
  71. (*
  72. PROCEDURE ByteToWord (b: CARD8): CARDINAL;
  73.  
  74.     (* Converts a byte to a word (with no sign extension). *)
  75.  
  76.     VAR result: Word32;
  77.  
  78.     BEGIN
  79.         result.c := 0;
  80.         result.low := b;
  81.         RETURN result.c;
  82.     END ByteToWord;
  83. *)
  84.  
  85. (************************************************************************)
  86.  
  87. (*
  88. PROCEDURE ByteToCard (b: BYTE): CARDINAL;
  89.  
  90.     (* Converts a byte to a cardinal. *)
  91.  
  92.     BEGIN
  93.         RETURN VAL(CARDINAL,CAST(CARD8,b));
  94.     END ByteToCard;
  95. *)
  96. (************************************************************************)
  97. (*                          BITWISE LOGIC                               *)
  98. (************************************************************************)
  99.  
  100. PROCEDURE IAND (first, second: CARDINAL): CARDINAL;
  101.  
  102.     (* Bit-by-bit logical AND.  *)
  103.  
  104.     VAR a, b, result: Word32;
  105.  
  106.     BEGIN
  107.         a.c := first;  b.c := second;
  108.         result.bits := a.bits * b.bits;
  109.         RETURN result.c;
  110.     END IAND;
  111.  
  112. (************************************************************************)
  113.  
  114. PROCEDURE IANDB (first, second: CARD8): CARD8;
  115.  
  116.     (* Bit-by-bit logical AND for bytes.        *)
  117.  
  118.     BEGIN
  119.         RETURN LowByte(IAND(first, second));
  120.     END IANDB;
  121.  
  122. (************************************************************************)
  123.  
  124. PROCEDURE IOR (first, second: CARDINAL): CARDINAL;
  125.  
  126.     (* Bit-by-bit inclusive OR. *)
  127.  
  128.     VAR a, b, result: Word32;
  129.  
  130.     BEGIN
  131.         a.c := first;  b.c := second;
  132.         result.bits := a.bits + b.bits;
  133.         RETURN result.c;
  134.     END IOR;
  135.  
  136. (************************************************************************)
  137.  
  138. PROCEDURE IORB (first, second: CARD8): CARD8;
  139.  
  140.     (* Bit-by-bit inclusive OR. *)
  141.  
  142.     BEGIN
  143.         RETURN LowByte(IOR(first, second));
  144.     END IORB;
  145.  
  146. (************************************************************************)
  147.  
  148. PROCEDURE IXOR (first, second: CARDINAL): CARDINAL;
  149.  
  150.     (* Bit-by-bit exclusive OR. *)
  151.  
  152.     VAR a, b, result: Word32;
  153.  
  154.     BEGIN
  155.         a.c := first;  b.c := second;
  156.         result.bits := a.bits / b.bits;
  157.         RETURN result.c;
  158.     END IXOR;
  159.  
  160. (************************************************************************)
  161.  
  162. PROCEDURE IXORB (first, second: CARD8): CARD8;
  163.  
  164.     (* Bit-by-bit exclusive OR. *)
  165.  
  166.     BEGIN
  167.         RETURN LowByte(IXOR(first, second));
  168.     END IXORB;
  169.  
  170. (************************************************************************)
  171.  
  172. PROCEDURE INOT (value: CARDINAL): CARDINAL;
  173.  
  174.     (* Bit-by-bit Boolean complement.   *)
  175.  
  176.     BEGIN
  177.         RETURN MAX(CARDINAL)-value;
  178.     END INOT;
  179.  
  180. (************************************************************************)
  181.  
  182. PROCEDURE INOTB (value: CARD8): CARD8;
  183.  
  184.     (* Bit-by-bit Boolean complement.   *)
  185.  
  186.     BEGIN
  187.         RETURN 0FFH-value;
  188.     END INOTB;
  189.  
  190. (************************************************************************)
  191.  
  192. PROCEDURE ROL (value: CARDINAL;  count: CARDINAL): CARDINAL;
  193.  
  194.     (* Left rotation of "value" by "count" bit positions.       *)
  195.  
  196.     VAR temp: Word32;
  197.  
  198.     BEGIN
  199.         count := count MOD 32;
  200.         temp.c := value;
  201.         temp.bits := ROTATE (temp.bits, VAL(INTEGER,count));
  202.         RETURN temp.c;
  203.     END ROL;
  204.  
  205. (************************************************************************)
  206.  
  207. PROCEDURE ROLB (value: CARD8;  count: CARDINAL): CARD8;
  208.  
  209.     (* Left rotation of "value" by "count" bit positions.       *)
  210.  
  211.     VAR temp: Word8;
  212.  
  213.     BEGIN
  214.         count := count MOD 8;
  215.         temp.c := value;
  216.         temp.bits := ROTATE (temp.bits, VAL(INTEGER,count));
  217.         RETURN temp.c;
  218.     END ROLB;
  219.  
  220. (************************************************************************)
  221.  
  222. PROCEDURE LS (value: CARDINAL;  count: CARDINAL): CARDINAL;
  223.  
  224.     (* Left shift of "value" by "count" bit positions, with zero fill.  *)
  225.  
  226.     VAR temp: Word32;
  227.  
  228.     BEGIN
  229.         temp.c := value;
  230.         IF count > 31 THEN temp.c := 0;
  231.         ELSIF count > 0 THEN
  232.             temp.bits := SHIFT (temp.bits, VAL(INTEGER,count));
  233.         END (*IF*);
  234.         RETURN temp.c;
  235.     END LS;
  236.  
  237. (************************************************************************)
  238.  
  239. PROCEDURE LSB (value: CARD8;  count: CARDINAL): CARD8;
  240.  
  241.     (* Left shift of "value" by "count" bit positions, with zero fill.  *)
  242.  
  243.     VAR temp: Word8;
  244.  
  245.     BEGIN
  246.         temp.c := value;
  247.         IF count > 7 THEN temp.c := 0;
  248.         ELSIF count > 0 THEN
  249.             temp.bits := SHIFT (temp.bits, VAL(INTEGER,count));
  250.         END (*IF*);
  251.         RETURN temp.c;
  252.     END LSB;
  253.  
  254. (************************************************************************)
  255.  
  256. PROCEDURE ROR (value: CARDINAL;  count: CARDINAL): CARDINAL;
  257.  
  258.     (* Right rotation of "value" by "count" bit positions.      *)
  259.  
  260.     VAR temp: Word32;
  261.  
  262.     BEGIN
  263.         count := count MOD 32;
  264.         temp.c := value;
  265.         temp.bits := ROTATE (temp.bits, -VAL(INTEGER,count));
  266.         RETURN temp.c;
  267.     END ROR;
  268.  
  269. (************************************************************************)
  270.  
  271. PROCEDURE RORB (value: CARD8;  count: CARDINAL): CARD8;
  272.  
  273.     (* Right rotation of "value" by "count" bit positions.      *)
  274.  
  275.     VAR temp: Word8;
  276.  
  277.     BEGIN
  278.         count := count MOD 8;
  279.         temp.c := value;
  280.         temp.bits := ROTATE (temp.bits, -VAL(INTEGER,count));
  281.         RETURN temp.c;
  282.     END RORB;
  283.  
  284. (************************************************************************)
  285.  
  286. PROCEDURE RS (value, count: CARDINAL): CARDINAL;
  287.  
  288.     (* Right shift of "value" by "count" bit positions, with zero fill. *)
  289.  
  290.     VAR temp: Word32;
  291.  
  292.     BEGIN
  293.         temp.c := value;
  294.         IF count > 31 THEN temp.c := 0;
  295.         ELSIF count > 0 THEN
  296.             temp.bits := SHIFT (temp.bits, -VAL(INTEGER,count));
  297.         END (*IF*);
  298.         RETURN temp.c;
  299.     END RS;
  300.  
  301. (************************************************************************)
  302.  
  303. PROCEDURE RSB (value: CARD8;  count: CARDINAL): CARD8;
  304.  
  305.     (* Right shift of "value" by "count" bit positions, with zero fill. *)
  306.  
  307.     VAR temp: Word8;
  308.  
  309.     BEGIN
  310.         temp.c := value;
  311.         IF count > 7 THEN temp.c := 0;
  312.         ELSIF count > 0 THEN
  313.             temp.bits := SHIFT (temp.bits, -VAL(INTEGER,count));
  314.         END (*IF*);
  315.         RETURN temp.c;
  316.     END RSB;
  317.  
  318. (************************************************************************)
  319. (*                          POINTER OPERATIONS                          *)
  320. (*   Remark: this group of procedures was originally designed for a     *)
  321. (*   segmented memory model.  XDS uses flat 32-bit addresses, and we    *)
  322. (*   handle this by treating the segment part of an address as a dummy. *)
  323. (************************************************************************)
  324.  
  325. PROCEDURE Far (A: ADDRESS): FarPointer;
  326.  
  327.     (* Converts a pointer to a far pointer. *)
  328.  
  329.     BEGIN
  330.         RETURN A;
  331.     END Far;
  332.  
  333. (************************************************************************)
  334.  
  335. PROCEDURE MakePointer (segment: CARD16;  offset: CARDINAL): FarPointer;
  336.  
  337.     (* Creates a pointer, given the segment and offset within segment.  *)
  338.  
  339.     VAR value: Word32;
  340.  
  341.     BEGIN
  342.         value.c := offset;
  343.         RETURN value.a;
  344.     END MakePointer;
  345.  
  346. (************************************************************************)
  347.  
  348. PROCEDURE SEGMENT (A: ADDRESS): CARD16;
  349.  
  350.     (* Returns the segment part of an address.  *)
  351.  
  352.     BEGIN
  353.         RETURN 0;
  354.     END SEGMENT;
  355.  
  356. (************************************************************************)
  357.  
  358. PROCEDURE FarSEGMENT (A: FarPointer): CARD16;
  359.  
  360.     (* Returns the segment part of an address.  *)
  361.  
  362.     BEGIN
  363.         RETURN 0;
  364.     END FarSEGMENT;
  365.  
  366. (************************************************************************)
  367.  
  368. PROCEDURE OFFSET (A: ADDRESS): CARDINAL;
  369.  
  370.     (* Returns the offset part of an address.   *)
  371.  
  372.     VAR value: Word32;
  373.  
  374.     BEGIN
  375.         value.a := A;
  376.         RETURN value.c;
  377.     END OFFSET;
  378.  
  379. (************************************************************************)
  380.  
  381. (*
  382. PROCEDURE Virtual (PA: LONGCARD): FarPointer;
  383.  
  384.     (* Converts a physical address to a virtual address, if possible.   *)
  385.     (* There are no guarantees in the case where there is no such       *)
  386.     (* virtual address.                                                 *)
  387.  
  388.     CONST Sixteen = (*<FST 16L >*)  (*<~FST*) 16 (*>*);
  389.  
  390.     VAR value: Double;
  391.  
  392.     BEGIN
  393.         value.low := LowWord(PA MOD Sixteen);
  394.         value.high := LowWord(PA DIV Sixteen);
  395.         RETURN value.a;
  396.     END Virtual;
  397. *)
  398. (************************************************************************)
  399. (*
  400. PROCEDURE Physical (A: ADDRESS): LONGCARD;
  401.  
  402.     (* Converts a virtual address to a physical address.  Use with care!*)
  403.     (* WARNING: This is going to give the wrong answer in a protected   *)
  404.     (* mode environment.  I'm still not sure how to fix this.           *)
  405.  
  406.     VAR value: Double;
  407.  
  408.     BEGIN
  409.         value.a := A;
  410.         RETURN 16*CARDINAL(value.high) + CARDINAL(value.low);
  411.     END Physical;
  412. *)
  413. (************************************************************************)
  414.  
  415. PROCEDURE AddOffset (A: ADDRESS;  increment: CARDINAL): ADDRESS;
  416.  
  417.     (* Returns a pointer to the memory location whose physical address  *)
  418.     (* is Physical(A)+increment.  In the present version, it is assumed *)
  419.     (* that the caller will never try to run off the end of a segment.  *)
  420.  
  421.     BEGIN
  422.         RETURN ADDADR (A, increment);
  423.     END AddOffset;
  424.  
  425. (************************************************************************)
  426.  
  427. PROCEDURE SubtractOffset (A: ADDRESS;  decrement: CARDINAL): ADDRESS;
  428.  
  429.     (* Like AddOffset, except that we go backwards in memory.  Running  *)
  430.     (* off the beginning of the segment is an undetected error.         *)
  431.  
  432.     BEGIN
  433.         RETURN SUBADR (A, decrement);
  434.     END SubtractOffset;
  435.  
  436. (************************************************************************)
  437.  
  438. PROCEDURE FarAddOffset (A: FarPointer;  increment: CARDINAL): FarPointer;
  439.  
  440.     (* Like AddOffset, except for the parameter types. *)
  441.  
  442.     BEGIN
  443.         RETURN ADDADR (A, increment);
  444.     END FarAddOffset;
  445.  
  446. (************************************************************************)
  447.  
  448. PROCEDURE FarSubtractOffset (A: FarPointer; decrement: CARDINAL): FarPointer;
  449.  
  450.     (* Like SubtractOffset, except for the parameter types. *)
  451.  
  452.     BEGIN
  453.         RETURN SUBADR (A, decrement);
  454.     END FarSubtractOffset;
  455.  
  456. (************************************************************************)
  457. (*                      BYTE/WORD/LONGCARD CONVERSIONS                  *)
  458. (************************************************************************)
  459.  
  460. PROCEDURE LowByte (w: CARDINAL): CARD8;
  461.  
  462.     (* Returns the low-order byte of its argument.      *)
  463.  
  464.     VAR value: Word32;
  465.  
  466.     BEGIN
  467.         value.c := w;
  468.         RETURN value.low;
  469.     END LowByte;
  470.  
  471. (************************************************************************)
  472.  
  473. PROCEDURE HighByte (w: CARD16): CARD8;
  474.  
  475.     (* Returns the high-order byte of its argument.     *)
  476.  
  477.     VAR value: Word16;
  478.  
  479.     BEGIN
  480.         value.c := w;
  481.         RETURN value.high;
  482.     END HighByte;
  483.  
  484. (************************************************************************)
  485.  
  486. PROCEDURE MakeWord (high, low: CARD8): CARD16;
  487.  
  488.     (* Combines two bytes into a word.  The first argument becomes the  *)
  489.     (* most significant byte of the result.                             *)
  490.  
  491.     VAR value: Word16;
  492.  
  493.     BEGIN
  494.         value.low := low;
  495.         value.high := high;
  496.         RETURN value.c;
  497.     END MakeWord;
  498.  
  499. (************************************************************************)
  500.  
  501. PROCEDURE SignExtend (val: INT8): INTEGER;
  502.  
  503.     (* Converts a signed 8-bit number to signed integer. *)
  504.  
  505.     BEGIN
  506.         RETURN val;
  507.     END SignExtend;
  508.  
  509. (************************************************************************)
  510.  
  511. PROCEDURE LowWord (w: CARDINAL): CARD16;
  512.  
  513.     (* Returns the low-order word of its argument.      *)
  514.  
  515.     VAR value: Double;
  516.  
  517.     BEGIN
  518.         value.lw := w;
  519.         RETURN ORD(value.low);
  520.     END LowWord;
  521.  
  522. (************************************************************************)
  523.  
  524. PROCEDURE HighWord (w: CARDINAL): CARD16;
  525.  
  526.     (* Returns the high-order word of its argument.     *)
  527.  
  528.     VAR value: Double;
  529.  
  530.     BEGIN
  531.         value.lw := w;
  532.         RETURN ORD(value.high);
  533.     END HighWord;
  534.  
  535. (************************************************************************)
  536.  
  537. PROCEDURE MakeLongword (high, low: CARD16): CARDINAL;
  538.  
  539.     (* Combines two words into a longword.  The first argument becomes  *)
  540.     (* the most significant word of the result.                         *)
  541.  
  542.     VAR value: Double;
  543.  
  544.     BEGIN
  545.         value.low := VAL(CARD16,low);
  546.         value.high := VAL(CARD16,high);
  547.         RETURN value.lw;
  548.     END MakeLongword;
  549.  
  550. (************************************************************************)
  551. (*                      MISCELLANEOUS ARITHMETIC                        *)
  552. (************************************************************************)
  553.  
  554. PROCEDURE INCV (VAR (*INOUT*) dest: CARDINAL;  src: CARDINAL): BOOLEAN;
  555.  
  556.     (* Computes dest := dest + src, and returns TRUE iff the addition   *)
  557.     (* produced a carry.                                                *)
  558.  
  559.     BEGIN
  560.         IF dest > MAX(CARDINAL) - src THEN
  561.             DEC (dest, MAX(CARDINAL) - src + 1);
  562.             RETURN TRUE;
  563.         ELSE
  564.             INC (dest, src);
  565.             RETURN FALSE;
  566.         END (*IF*);
  567.     END INCV;
  568.  
  569. (************************************************************************)
  570.  
  571. PROCEDURE INCVB (VAR (*INOUT*) dest: CARD8;  src: CARD8): BOOLEAN;
  572.  
  573.     (* Computes dest := dest + src, and returns TRUE iff the addition   *)
  574.     (* produced a carry.                                                *)
  575.  
  576.     VAR sum: CARDINAL;
  577.  
  578.     BEGIN
  579.         sum := dest + src;
  580.         dest := LowByte (sum);
  581.         RETURN sum>255;
  582.     END INCVB;
  583.  
  584. (************************************************************************)
  585.  
  586. PROCEDURE DECV (VAR (*INOUT*) dest: CARDINAL;  src: CARDINAL): BOOLEAN;
  587.  
  588.     (* Computes dest := dest - src, and returns TRUE iff the            *)
  589.     (* subtraction produced a borrow.                                   *)
  590.  
  591.     BEGIN
  592.         IF dest < src THEN
  593.             INC (dest, MAX(CARDINAL) - src + 1);  RETURN TRUE;
  594.         ELSE
  595.             DEC (dest, src);  RETURN FALSE;
  596.         END (*IF*);
  597.     END DECV;
  598.  
  599. (************************************************************************)
  600.  
  601. PROCEDURE DECVB (VAR (*INOUT*) dest: CARD8;  src: CARD8): BOOLEAN;
  602.  
  603.     (* Computes dest := dest - src, and returns TRUE iff the            *)
  604.     (* subtraction produced a borrow.                                   *)
  605.  
  606.     VAR sval, dval: CARDINAL;
  607.  
  608.     BEGIN
  609.         sval := src;
  610.         dval := dest;
  611.         IF dval < sval THEN
  612.             dest := LowByte(dval + (256 - sval));
  613.             RETURN TRUE;
  614.         ELSE
  615.             dest := LowByte(dval - sval);
  616.             RETURN FALSE;
  617.         END (*IF*);
  618.     END DECVB;
  619.  
  620. (************************************************************************)
  621.  
  622. PROCEDURE Mul (A, B: CARD16): CARDINAL;
  623.  
  624.     (* Same as A*B, except for the type of the result.  We provide this *)
  625.     (* as a general-purpose function since this combination of operands *)
  626.     (* is often precisely what is wanted.                               *)
  627.  
  628.     BEGIN
  629.         RETURN A * B;
  630.     END Mul;
  631.  
  632. (************************************************************************)
  633.  
  634. PROCEDURE MulB (A, B: CARD8): CARD16;
  635.  
  636.     (* Same as A*B, except for the type of the result.  We provide this *)
  637.     (* as a general-purpose function since this combination of operands *)
  638.     (* is often precisely what is wanted.                               *)
  639.  
  640.     BEGIN
  641.         RETURN A * B;
  642.     END MulB;
  643.  
  644. (************************************************************************)
  645.  
  646. PROCEDURE IMul (A, B: INT16): INTEGER;
  647.  
  648.     (* Like Mul, but signed. *)
  649.  
  650.     BEGIN
  651.         RETURN VAL(INTEGER,A) * VAL(INTEGER,B);
  652.     END IMul;
  653.  
  654. (************************************************************************)
  655.  
  656. PROCEDURE IMulB (A, B: INT8): INT16;
  657.  
  658.     (* Like MulB, but signed. *)
  659.  
  660.     BEGIN
  661.         RETURN SignExtend(A) * SignExtend(B);
  662.     END IMulB;
  663.  
  664. (************************************************************************)
  665.  
  666. PROCEDURE DivB (A: CARD16;  B: CARD8): CARD8;
  667.  
  668.     (* Same as A DIV B, except for the type of A.  We provide this as   *)
  669.     (* a general-purpose function since this combination of operands    *)
  670.     (* is often precisely what is wanted.                               *)
  671.  
  672.     BEGIN
  673.         RETURN LowByte(A DIV B);
  674.     END DivB;
  675.  
  676. (************************************************************************)
  677.  
  678. PROCEDURE Div (A: CARDINAL;  B: CARD16): CARD16;
  679.  
  680.     (* Same as A DIV B, except for the type of A.  We provide this as   *)
  681.     (* a general-purpose function since this combination of operands    *)
  682.     (* is often precisely what is wanted.                               *)
  683.  
  684.     BEGIN
  685.         RETURN VAL(CARD16, A DIV VAL(CARDINAL,B));
  686.     END Div;
  687.  
  688. (************************************************************************)
  689. (*                           BLOCK MOVES                                *)
  690. (************************************************************************)
  691.  
  692. PROCEDURE Copy (source, destination: ADDRESS;  bytecount: CARDINAL);
  693.  
  694.     (* Copies an array of bytes from the source address to the          *)
  695.     (* destination address.  In the case where the two arrays overlap,  *)
  696.     (* the destination address should be lower in physical memory than  *)
  697.     (* the source address.                                              *)
  698.  
  699.     BEGIN
  700.         MOVE (source, destination, bytecount);
  701.     END Copy;
  702.  
  703. (************************************************************************)
  704.  
  705. PROCEDURE FarCopy (source, destination: FarPointer;  bytecount: CARDINAL);
  706.  
  707.     (* Copies an array of bytes from the source address to the          *)
  708.     (* destination address.  In the case where the two arrays overlap,  *)
  709.     (* the destination address should be lower in physical memory than  *)
  710.     (* the source address.                                              *)
  711.  
  712.     BEGIN
  713.         MOVE (source, destination, bytecount);
  714.     END FarCopy;
  715.  
  716. (************************************************************************)
  717.  
  718. PROCEDURE CopyUp (source, destination: FarPointer;  bytecount: CARDINAL);
  719.  
  720.     (* A variant of Copy which does the move backwards, in order        *)
  721.     (* to handle the case where the destination address is inside the   *)
  722.     (* source array.  In this special case Copy cannot be used,         *)
  723.     (* because it would overwrite data it was about to copy.            *)
  724.  
  725.     (* Workaround: for now we don't have access to a suitable SYSTEM    *)
  726.     (* procedure for backwards copying, so I'm doing the job by copying *)
  727.     (* to an intermediate buffer.                                       *)
  728.  
  729.     VAR p: FarPointer;
  730.  
  731.     BEGIN
  732.         IF bytecount > 0 THEN
  733.             ALLOCATE (p, bytecount);
  734.             MOVE (source, p, bytecount);
  735.             MOVE (p, destination, bytecount);
  736.             DEALLOCATE (p, bytecount);
  737.         END (*IF*);
  738.     END CopyUp;
  739.  
  740. (************************************************************************)
  741.  
  742. PROCEDURE BlockFill (destination: FarPointer;
  743.                                 bytecount: CARDINAL;  value: CARD8);
  744.  
  745.     (* Fills the destination array with the given value.        *)
  746.  
  747.     BEGIN
  748.         FILL (destination, value, bytecount);
  749.     END BlockFill;
  750.  
  751. (************************************************************************)
  752.  
  753. PROCEDURE BlockFillWord (destination: FarPointer;  wordcount: CARDINAL;
  754.                                                         value: CARD16);
  755.  
  756.     (* Fills the destination array with the given value.        *)
  757.  
  758.     VAR p: POINTER TO CARD16;  j: CARDINAL;
  759.  
  760.     BEGIN
  761.         p := destination;
  762.         FOR j := 1 TO wordcount DO
  763.             p^ := value;  p := AddOffset(p, 2);
  764.         END (*FOR*);
  765.     END BlockFillWord;
  766.  
  767. (************************************************************************)
  768. (*                          INPUT AND OUTPUT                            *)
  769. (************************************************************************)
  770. (*
  771. PROCEDURE OutByte (port: CARDINAL; value: BYTE);
  772.  
  773.     (* Puts the value out to an output port.    *)
  774.  
  775.     BEGIN
  776.         (*<TopSpeed*) SYSTEM.Out (port, value); (*>*)
  777.         (*<FST
  778.         ASM
  779.             MOV DX, port
  780.             MOV AL, value
  781.             OUT DX, AL
  782.         END (*ASM*);
  783.         >*)
  784.     END OutByte;
  785.  
  786. (************************************************************************)
  787.  
  788. PROCEDURE InByte (port: CARDINAL): BYTE;
  789.  
  790.     (* Reads a byte from an input port. *)
  791.  
  792.     (*<FST VAR result: BYTE; >*)
  793.  
  794.     BEGIN
  795.         RETURN SYSTEM.In (port);
  796.     END InByte;
  797.  
  798. *)
  799.  
  800. (************************************************************************)
  801. (*
  802. PROCEDURE InStringWord (port: CARDINAL;  BufferAddress: ADDRESS;
  803.                                                 count: CARDINAL);
  804.  
  805.     (* Reads count words from an input port.    *)
  806.  
  807.     VAR j: CARDINAL;  p: POINTER TO WORD;
  808.         lobyte, hibyte: BYTE;
  809.  
  810.     BEGIN
  811.         p := BufferAddress;
  812.         FOR j := 1 TO count DO
  813.             p^ := SYSTEM.InW (port);
  814.             Lib.IncAddr (p, 2);
  815.         END (*FOR*);
  816.     END InStringWord;
  817. *)
  818. (************************************************************************)
  819. (*
  820. PROCEDURE OutStringWord (port: CARDINAL;  BufferAddress: ADDRESS;
  821.                                                 count: CARDINAL);
  822.  
  823.     (* Writes count words to an output port.    *)
  824.  
  825.     VAR j: CARDINAL;  p: POINTER TO WORD;
  826.  
  827.     BEGIN
  828.         p := BufferAddress;
  829.         FOR j := 1 TO count DO
  830.             SYSTEM.OutW (port, p^);
  831.             Lib.IncAddr (p, 2);
  832.         END (*FOR*);
  833.     END OutStringWord;
  834. *)
  835. (************************************************************************)
  836.  
  837. END LowLevel.
  838.