;-------------------------------------------------------
;	Iron Spring PL/I Runtime Library Version 0.5
;	   Distributed under the Gnu LGPL License
;
;	RANDOM - PL/I runtime support routines
;       Version 0.1 Alpha -- June 2016
;       Copyright Peter Flass
;
;       This module implements the RANDOM builtin     
;       compatibly with IBM Enterprise PL/I
;       Description:   "The values generated by RANDOM are uniformly
;                      distributed between 0 and 1 with
;                      0<random(x)<1. They are generated as follows
;                      using the multiplicative congruential
;                      method.
;                        seed(x) = mod( 950706376 * seed(x-1), 2147483647 )
;                        random(x) = seed(x) / 2147483647"
;                                               -SC27-1400-04, p.451
;       This had to be written in assembler because it
;       requires a full 64-bit product.
;
; Entries:
;       _pli_Rand0 - RAMDOM()
;       _pli_RAND1 - RANDOM(seed)
;
; To Do:	
;       
;       Arguments (Rand1)
;         EBP+8   (param 1) address of seed                  
;	
;       Modifications:	
;	
;-------------------------------------------------------
	.486P
	.model flat,syscall
        public _pli_Rand0
        public _pli_Rand1

	include framedef.inc	; Standard PL/I stack frame
;------------------------------------------------+
;  Unique Stack Data for _pli_Randx              |
;------------------------------------------------+
frm_loc equ     frm_bos		; Start of locals 
;       (none)
loc_end equ	frm_loc-4	; End of locals
loc_len equ	frm_loc-loc_end	;
frm_siz equ	frm_len+loc_len	; Total stack frame length         

        .data
_pli_data equ $
seed_1    dd   1                ; seed(x-1), intital value is 1

	.code			; PL/I Compatible entry code
_pli_code equ $
	db 20h,16h,06h,15h,10h,00h,00h,00h
;
;       Rand1 - RANDOM with seed    
;
	db '_pli_Rand1'
	db 10
_pli_Rand1:
	call dword ptr 0[edi]
	dd  frm_siz			; DSA size
	mov word ptr [ebp-28],81E1h	; Condition prefix flags         
        mov ecx,dword ptr 8[ebp]	; Load value(seed)        
	mov seed_1,ecx              	; store value
        cmp ecx,0                       ; 0 < x < 2147483646
        jng error
        cmp ecx,2147483646
        jl  rand                        ; continue with rand0
error:
        push 9                          ; ERROR OnCode
        mov edi,dword ptr [ebp-4]
        mov esi,dword ptr [ebp-8]
        call dword ptr 64[edi]          ; Signal ERROR
        add esp,4        
;
;       Rand0 - RANDOM without seed 
;
	db '_pli_Rand0'
	db 10
_pli_Rand0:
	call dword ptr 0[edi]
	dd  frm_siz			; DSA size
	mov word ptr [ebp-28],81E1h	; Condition prefix flags
        
rand:   mov eax,seed_1                  ; load seed(x-1)
        mul X950                        ; multiply x 950706376
        div X214                        ; MOD() function
        mov seed_1,edx                  ; save updated seed
        fild seed_1                     ; dividend ST(1)
        fild X214                       ; divisor  ST(0)
        fdivp ST(1),ST(0)               ; seed / 2147483647
; Result value in ST(0)            
return:					; 
	mov ebx,dword ptr [ebp-12]	;			20091202
	mov esi,dword ptr [ebp-8]	;			20091202
	mov edi,dword ptr [ebp-4]	;			20091202
	leave
	ret

_pli_endc equ $
	.data
X950    dd  950706376
X214    dd  2147483647
	org _pli_data+00h
_pli_endd equ $
	end
