dos_compilers/Artek Ada v125/MEMORY.ADA
2024-07-08 09:31:49 -07:00

212 lines
6.3 KiB
Ada
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

--
-- MEMORY.ADA
--
-- Memory management package for Artek Ada
--
-- Copyright (C) 1986 Artek Corporation
-- Author: V. Thorsteinsson
--
-- This generic package enables users of Artek Ada to access all
-- 640 Kb of available memory under DOS.
--
-- It is implemented as a set of five operations:
-- ALLOCATE, DEALLOCATE, MODIFY_ALLOCATION, READ, and WRITE.
-- The allocated memory is modeled as an array (indexed from 0)
-- of the generic type DATA. Elements of the array may be written
-- or read using the READ and WRITE operations. The size
-- of the array may be set using ALLOCATE and the memory used
-- by the array can be freed with DEALLOCATE. If the user
-- wishes to modify the size of an already allocated array,
-- he should use the MODIFY_ALLOCATION procedure. This will
-- preserve the memory contents up to the latest original element
-- or the latest new element, whichever is lower in memory.
-- Any error in usage causes a MEMORY_ERROR exception to be
-- raised.
--
-- Example of usage:
--
-- with TEXT_IO; use TEXT_IO;
-- procedure MEMORY_DEMO is
--
-- type SYMBOL is record
-- IDENTIFIER : STRING (1..32);
-- SYMTYPE : (OBJECT, PROGRAM, LABEL);
-- CONTENTS : INTEGER;
-- end record;
--
-- package SYMTABLE is new MEMORY (SYMBOL);
--
-- S : SYMBOL;
--
-- begin
-- SYMTABLE.ALLOCATE (2000); -- This allocates about 70K of data
-- S . IDENTIFIER := "IDENTIFIER ";
-- S . SYMTYPE := PROGRAM;
-- for I in 0..1999 loop -- NOTE: not 1 to 2000!
-- S . CONTENTS := I;
-- SYMTABLE.WRITE (I, S); -- Write S into array element I
-- end loop;
-- SYMTABLE.READ (1555, S); -- Read S from array element 1555
-- SYMTABLE.DEALLOCATE;
-- PUT_LINE (INTEGER'IMAGE (S . CONTENTS)); -- Should write 1555
-- exception
-- when MEMORY_ERROR =>
-- PUT_LINE ("Error while working with MEMORY package");
-- end MEMORY_DEMO;
--
with SYSTEM; use SYSTEM;
generic
type DATA is private;
package MEMORY is
procedure ALLOCATE (NUMBER_OF_ELEMENTS : in POSITIVE);
procedure DEALLOCATE;
procedure MODIFY_ALLOCATION (NUMBER_OF_ELEMENTS : in POSITIVE);
procedure READ (NUMBER_OF_ELEMENT : in NATURAL; ELEMENT : out DATA);
procedure WRITE (NUMBER_OF_ELEMENT : in NATURAL; ELEMENT : in DATA);
MEMORY_ERROR : exception;
end MEMORY;
with DOS_INTERFACE; use DOS_INTERFACE;
with LONG_OPERATIONS; use LONG_OPERATIONS;
with SYSTEM;
package body MEMORY is
use SYSTEM;
type LONG_PTR is record
OFF : WORD;
SEG : WORD;
end record;
subtype SEGMENT is WORD;
NIL : constant SEGMENT := 0;
ELEMENT_SIZE : constant INTEGER := DATA'SIZE / STORAGE_UNIT;
BASE : SEGMENT := NIL;
POOLSIZE : NATURAL := 0;
R : REG_8086;
function DOS_ALLOCATE (SIZE : INTEGER) return SEGMENT is
begin
R . AX := 16#4800#;
R . BX := WORD (SIZE);
CALL_DOS (R);
if R . FLAGS mod 2 = 1 then -- Carry set
raise MEMORY_ERROR;
end if;
return R . AX;
end;
procedure DOS_DEALLOCATE (S : SEGMENT) is
begin
R . AX := 16#4900#;
R . ES := S;
CALL_DOS (R);
if R . FLAGS mod 2 = 1 then
raise MEMORY_ERROR;
end if;
end;
procedure DOS_MODIFY_ALLOCATION (S : SEGMENT; SIZE : INTEGER) is
begin
R . AX := 16#4A00#;
R . ES := S;
R . BX := WORD (SIZE);
CALL_DOS (R);
if R . FLAGS mod 2 = 1 then
raise MEMORY_ERROR;
end if;
end;
procedure ALLOCATE (NUMBER_OF_ELEMENTS : in POSITIVE) is
SIZE : LONG_INTEGER;
begin
if BASE /= NIL then
raise MEMORY_ERROR;
end if;
SIZE := SHR (NUMBER_OF_ELEMENTS * ELEMENT_SIZE, 4);
BASE := DOS_ALLOCATE (SIZE . LOW + 1);
POOLSIZE := NUMBER_OF_ELEMENTS;
end ALLOCATE;
procedure DEALLOCATE is
begin
if BASE = NIL then
raise MEMORY_ERROR;
end if;
DOS_DEALLOCATE (BASE);
POOLSIZE := 0;
end DEALLOCATE;
procedure MODIFY_ALLOCATION (NUMBER_OF_ELEMENTS : in POSITIVE) is
SIZE : LONG_INTEGER;
begin
if BASE = NIL then
raise MEMORY_ERROR;
end if;
SIZE := SHR (NUMBER_OF_ELEMENTS * ELEMENT_SIZE, 4);
DOS_MODIFY_ALLOCATION (BASE, SIZE . LOW + 1);
POOLSIZE := NUMBER_OF_ELEMENTS;
end MODIFY_ALLOCATION;
procedure MOVE_SHORT_LONG (FROM : in INTEGER; TO : in LONG_INTEGER; SIZE : in INTEGER) is
begin
pragma NATIVE (
16#55#, 16#06#, 16#8B#, 16#EE#, 16#8B#, 16#76#, 16#00#, 16#8B#,
16#56#, 16#02#, 16#8B#, 16#FA#, 16#81#, 16#E7#, 16#0F#, 16#00#,
16#81#, 16#E2#, 16#F0#, 16#FF#, 16#B1#, 16#04#, 16#D3#, 16#EA#,
16#8B#, 16#46#, 16#04#, 16#B1#, 16#0C#, 16#D3#, 16#E0#, 16#0B#,
16#C2#, 16#8B#, 16#4E#, 16#06#, 16#8E#, 16#C0#, 16#FC#, 16#F3#,
16#A4#, 16#07#, 16#5D#);
null;
end MOVE_SHORT_LONG;
procedure MOVE_LONG_SHORT (FROM : in LONG_INTEGER; TO : in INTEGER; SIZE : in INTEGER) is
begin
pragma NATIVE (
16#1E#, 16#55#, 16#8B#, 16#EE#, 16#8B#, 16#7E#, 16#04#, 16#8B#,
16#56#, 16#00#, 16#8B#, 16#F2#, 16#81#, 16#E6#, 16#0F#, 16#00#,
16#81#, 16#E2#, 16#F0#, 16#FF#, 16#B1#, 16#04#, 16#D3#, 16#EA#,
16#8B#, 16#46#, 16#02#, 16#B1#, 16#0C#, 16#D3#, 16#E0#, 16#0B#,
16#C2#, 16#8B#, 16#4E#, 16#06#, 16#8E#, 16#D8#, 16#FC#, 16#F3#,
16#A4#, 16#5D#, 16#1F#);
null;
end MOVE_LONG_SHORT;
procedure READ (NUMBER_OF_ELEMENT : in NATURAL; ELEMENT : out DATA) is
ADDRESS : LONG_INTEGER;
begin
if BASE = NIL or NUMBER_OF_ELEMENT >= POOLSIZE then
raise MEMORY_ERROR;
end if;
ADDRESS := INTEGER (BASE) * 16;
ADDRESS := NUMBER_OF_ELEMENT * ELEMENT_SIZE + ADDRESS;
MOVE_LONG_SHORT (ADDRESS, ELEMENT'ADDRESS, ELEMENT_SIZE);
end READ;
procedure WRITE (NUMBER_OF_ELEMENT : in NATURAL; ELEMENT : in DATA) is
ADDRESS : LONG_INTEGER;
begin
if BASE = NIL or NUMBER_OF_ELEMENT >= POOLSIZE then
raise MEMORY_ERROR;
end if;
ADDRESS := INTEGER (BASE) * 16;
ADDRESS := NUMBER_OF_ELEMENT * ELEMENT_SIZE + ADDRESS;
MOVE_SHORT_LONG (ELEMENT'ADDRESS, ADDRESS, ELEMENT_SIZE);
end WRITE;
end MEMORY;