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

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