	INCLUDE	C:TITLE.MAC
	.TITLE	<EXMEM -- Extended Memory Functions>
	.SBTTL	History

; exmem.asm  20 Dec 83  Craig Milo Rogers at USC/ISI
;	Added peek() and poke(), and variants.
; exmem.asm  15 Nov 83  Craig Milo Rogers at USC/ISI
;	Converted to PDP11-style TITLEs.
; exmem.asm  8 Sep 83  Craig Milo Rogers at USC/ISI
;	Converted to multi-model Lattice C.
; exmem.asm  24 Aug 83  Craig Milo Rogers at USC/ISI
;	Created this module to access extended memory.

	.SBHED	Declarations

;	This module defines subroutines for manipulating extended memory,
; by which I mean memory which can't normally be referenced by the Lattice
; C complier.

IF1
	INCLUDE	C:DOS.MAC		; C segments.
	INCLUDE C:BMAC.MAC		; C procedure calls.
ELSE
;	INCLUDE	C:DOS.MAC		; C segments.
;	INCLUDE C:BMAC.MAC		; C procedure calls.
ENDIF

	PSEG				; Only code from here on.

	.SBHED	<GETADDR -- Return a 20-bit Address>

; name		getaddr -- return a 20-bit address
;
; synopsis	a = getaddr(p);
;		PTR p;		points to something
;		long a;		returned value
;
; description	Converts a pointer to a 20-bit address, for DMA
;		transfers, peek/poke, etc.
;

IF LDATA
	BENTRY	GETADDR <OFFXX,SEGXX>
	MOV	BX,SEGXX	; Load segment part of pointer.
ELSE
	BENTRY	GETADDR <OFFXX>
	MOV	BX,DS		; Get segment part of address.
ENDIF
	MOV	AL,BH		; Copy byte with high 4 bits.
	XOR	AH,AH		; Clear rest of high-order return register.
	MOV	CL,4		; Get shift count.
	SAR	AX,CL		; Isolate high-order 4 bits.
	SHL	BX,CL		; Justify lower 12 bits.
	ADD	BX,OFFXX	; Add in lower bits of address.
	ADC	AX,0		; Propogate carry, if any.

	BEND	GETADDR		; Return with result in AX & BX.
				; (AX is high, BX is low)

	.SBHED	<PEEK -- Return the Contents of a Location>

; name		peek -- return the contents of a location
;
; synopsis	v = peek(a);
;		long a;		20-bit address
;		int v;		returned value
;
; description	Gets the contents of a location.  This routine is
;		inherently machine-specific.  The address is in
;		20-bit integer format.  The value returned is a
;		16-bit integer.
;

	BENTRY	PEEK <LOW16,HGH4>

	MOV	SI,LOW16	; Get low 16 bits of address.
	MOV	AX,HGH4		; Get high four bits (right justified).
	MOV	CX,12		; Need to left justify high bits
	SHL	AX,CL		;   to make segment part of addr.
	MOV	ES,AX		; Transfer into extra segment register.
	MOV	AX,ES:[SI]	; Get the value of the location.

	BEND	PEEK		; Return with result in AX.

	.SBHED	<CPEEK -- Return the Char Contents of a Location>

; name		cpeek -- return the character contents of a location
;
; synopsis	c = cpeek(a);
;		long a;		20-bit address
;		u_char c;	returned value
;
; description	Gets the contents of a location.  This routine is
;		inherently machine-specific.  The address is in
;		20-bit integer format.  The value returned is an
;		8-bit unsigned char.
;
;

	BENTRY	CPEEK <LOW16,HGH4>

	MOV	SI,LOW16	; Get low 16 bits of address.
	MOV	AX,HGH4		; Get high four bits (right justified).
	MOV	CX,12		; Need to left justify high bits
	SHL	AX,CL		;   to make segment part of addr.
	MOV	ES,AX		; Transfer into extra segment register.
	MOV	AL,ES:[SI]	; Get the value of the location.
	XOR	AH,AH		; Clear the high order bits.

	BEND	CPEEK		; Return with result in AX.

	.SBHED	<LPEEK -- Return the Long Contents of a Location>

; name		lpeek -- return the long contents of a location
;
; synopsis	l = lpeek(a);
;		long a;		20-bit address
;		long l;		returned value
;
; description	Gets the contents of a location.  This routine is
;		inherently machine-specific.  The address is in
;		20-bit integer format.  The value returned is a
;		32-bit long integer.
;
;

	BENTRY	LPEEK <LOW16,HGH4>

	MOV	SI,LOW16	; Get low 16 bits of address.
	MOV	AX,HGH4		; Get high four bits (right justified).
	MOV	CX,12		; Need to left justify high bits
	SHL	AX,CL		;   to make segment part of addr.
	MOV	ES,AX		; Transfer into extra segment register.
	MOV	BX,ES:[SI]	; Get the value of the low 16 bits.
	ADD	SI,2		; Point to the high 16 bits.
	 JNC	LPEKNC		;   (no overflow)
	ADD	AX,1000H	; Propogate carry.
	MOV	ES,AX		; Transfer into extra segment register.
LPEKNC:	MOV	AX,ES:[SI]	; Get the value of the high 16 bits.

	BEND	LPEEK		; Return with result in AX and BX,
				; High 16 bits in AX, low 16 bits in BX.

	.SBHED	<POKE -- Change the Contents of a Location>

; name		poke -- change the contents of a location
;
; synopsis	poke(a, v);
;		long a;		20-bit address
;		int v;		new value
;
; description	Sets the contents of a location.  This routine is
;		inherently machine-specific.  The address is in
;		20-bit integer format.  The value changed is a
;		16-bit integer.
;

	BENTRY	POKE <LOW16,HGH4,VALU>

	MOV	SI,LOW16	; Get low 16 bits of address.
	MOV	AX,HGH4		; Get high four bits (right justified).
	MOV	CX,12		; Need to left justify high bits
	SHL	AX,CL		;   to make segment part of addr.
	MOV	ES,AX		; Transfer into extra segment register.
	MOV	AX,VALU		; Get the new value.
	MOV	ES:[SI],AX	; Set the value of the location.

	BEND	POKE		; Return.

	.SBHED	<CPOKE -- Change the Contents of a Char Location>

; name		cpoke -- change the contents of a char location
;
; synopsis	cpoke(a, c);
;		long a;		20-bit address
;		u_char c;	new value
;
; description	Sets the contents of a location.  This routine is
;		inherently machine-specific.  The address is in
;		20-bit integer format.  The value changed is an
;		8-bit unsigned char.
;

	BENTRY	CPOKE <LOW16,HGH4,VALU>

	MOV	SI,LOW16	; Get low 16 bits of address.
	MOV	AX,HGH4		; Get high four bits (right justified).
	MOV	CX,12		; Need to left justify high bits
	SHL	AX,CL		;   to make segment part of addr.
	MOV	ES,AX		; Transfer into extra segment register.
	MOV	AL,VALU		; Get the new value.
	MOV	ES:[SI],AL	; Set the value of the location.

	BEND	CPOKE		; Return.

	.SBHED	<LPOKE -- Change the Contents of a Long Location>

; name		lpoke -- change the contents of a long location
;
; synopsis	lpoke(a, v);
;		long a;		20-bit address
;		long v;		new value
;
; description	Sets the contents of a location.  This routine is
;		inherently machine-specific.  The address is in
;		20-bit integer format.  The value changed is a
;		32-bit long integer.
;

	BENTRY	LPOKE <LOW16,HGH4,LOVALU,HIVALU>

	MOV	SI,LOW16	; Get low 16 bits of address.
	MOV	AX,HGH4		; Get high four bits (right justified).
	MOV	CX,12		; Need to left justify high bits
	SHL	AX,CL		;   to make segment part of addr.
	MOV	ES,AX		; Transfer into extra segment register.
	MOV	BX,LOVALU	; Get the low 16 bits of the new value.
	MOV	ES:[SI],BX	; Set the value of the low 16 bits.
	ADD	SI,2		; Point to the high 16 bits.
	 JNC	LPOKNC		;   (no overflow)
	ADD	AX,1000H	; Propogate carry.
	MOV	ES,AX		; Transfer into extra segment register.
LPOKNC:	MOV	AX,HIVALU	; Get the high 16 bits of the new value.
	MOV	ES:[SI],AX	; Set the high 16 bits.

	BEND	LPOKE		; Return.
;
;
	ENDPS			; End of code segment.
	END
