In order to relocate to high memory we must first determine how much memory is available. Hercules allows us to define a memory size from 1 to 16 megabytes in 1 megabyte increments.
To determine the memory we have available at IPL time we will simply scan through all memory beginning at location zero until we reach 16 Meg or we get an error attempting to access memory.
We will use the SSK (Set Storage Key) instruction to test for vaild storage. It has the format SSK R1,R2. Bits 21-27 of R2 specify a 2k (2048) block memory. The storage key is set to the value specified by bits 24-30 of R1. If the storage block does not exist an Access Specification interrupt is generated.
By using the SSK instruction we not only determine how much memory is available but we also set the access key for all memory to zero.
* * LA R2,0 LA R3,0 L R4,=A(X'01000000') 16 MEG LA R1,2048 2K * MVC 104(8),=A(0,MDONE) PROGRAM CHECK NEW PSW * MLOOP DS 0H SSK R2,R3 SET STORAGE KEY AR R3,R1 NEXT 2K PAGE CR R3,R4 HIT 16 MEG? BL MLOOP LOOP BACK * MDONE DS 0H MVC 104(8),=A(X'00020000',X'00010BAD') PC NEW PSW * *
We start by setting our access key value to zero in Register 2. We set the initial address in Register 3 to zero (storage location zero). Register 4 is set to the maximum memory size (16 Meg) and Register 1 is set to 2k for our increment value.
Before beginning the loop we specify a New Program Check PSW. If a program check interruption occurs, the CPU will load the value contained at location 104 into the PSW. Here we specify a PSW with MDONE as the instruction address value. If a program check occurs it will effectively cause a branch to the label MDONE.
The loop is very simple. We use the SSK instruction to set the storage key of a 2k block of storage. If the storage address does not exist a program check interruption occurs which causes a branch in execution to MDONE. If the SSK was successful we add 2k to the address, check to see if we have reached the maximum memory size (16 Meg) and then loop back.
When we reach MDONE either because of a program check interruption or because fell through the branch, Register 3 contains the high memory address and tells us how much memory is available.
The first thing we need to do is to set a new program check PSW. Here we load a PSW with the wait bit set and an error code of x’010BAD’. If we failed to specify a new program check PSW and a a program check occurred, we could possibly end up in an endless loop.
* ST R3,WORK4 SAVE MEMORY SIZE UNPK WORK8(9),WORK4(5) UNPACK TR WORK8,TRTAB-C'0' MAKE PRINTABLE * * LR R1,R3 COPY MEMORY SIZE SLR R0,R0 D R0,=A(X'00100000') DIVIDE BY 1MEG CVD R1,DOUBLE SAVE RESULT AS DECIMAL ED EDWK,DOUBLE+6 MVC MEMSIZE2,EDWK+1 * * MVC MEMSIZE1,WORK8 MOVE IN MEMORY SIZE * @PRINT MSG1,LEN=L'MSG1 @PRINT MSG2,LEN=L'MSG2 @PRINT MSG1,LEN=L'MSG1 * * LPSW DONE *
For testing we can us UNPK and then TR to get a printable hex value. We then divide the max memory size by 1 Meg, and use CVD and ED to get a decimal value. These values are moved into our print line and then printed.
DONE DC A(X'00020000',X'0099FACE') WAIT STATE PSW * MSG1 DC C'*****************************************************' MSG2 DC CL132' ' ORG MSG2 DC C' MEMORY SIZE=X''' MEMSIZE1 DC CL8'********',C''' ' MEMSIZE2 DC CL3'***',C' MEG' ORG , * DOUBLE DS D FSA DS 18F WORK4 DS F WORK8 DC CL8'********',C'**' * EDWK DC X'40202020' * TRTAB DC C'0123456789ABCDEF' *
The complete program is available at DBOOT1.
[Next – Copy To High Memory]