;
; flex.sh
;
; Flexible memory handling
;
;  1994-1998 Straylight
;

;----- Licensing note -------------------------------------------------------
;
; This file is part of Straylight's Flex.
;
; Flex is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2, or (at your option)
; any later version.
;
; Flex is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with Flex.  If not, write to the Free Software Foundation,
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

;----- Overview -------------------------------------------------------------
;
; Functions provided:
;
;  flex_reduce
;  flex_compact
;  flex_free
;  flex_alloc
;  flex_size
;  flex_extend
;  flex_midExtend
;  flex_init
;  flex_save
;  flex_load
;  flex_dump
;
; Macros provided:
;
;   FSAVE
;   FLOAD

;+		LIB	sapphire:^.bsh.flex

; --- flex_reduce ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Compacts the flex heap by one iteration.

		IMPORT	flex_reduce

; --- flex_compact ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Completely compacts the flex heap.

		IMPORT	flex_compact

; --- flex_free ---
;
; On entry:	R0 == pointer to the flex anchor
;
; On exit:	--
;
; Use:		Frees a flex block allocated by flex_alloc.

		IMPORT	flex_free

; --- flex_alloc ---
;
; On entry:	R0 == pointer to a flex anchor
;		R1 == desired size of flex block
;
; On exit:	CS if no memory could be allocated, CC otherwise
;
; Use:		Allocates a block in the shifting heap.

		IMPORT	flex_alloc

; --- flex_size ---
;
; On entry:	R0 == pointer to flex anchor
;
; On exit:	R0 == size of allocated block
;
; Use:		Reads the size of a flex block.

		IMPORT	flex_size

; --- flex_extend ---
;
; On entry:	R0 == pointer to flex anchor
;		R1 == new size of block to set
;
; On exit:	CS if it failed due to lack of memory, CC otherwise
;
; Use:		Alters the size of a block to the given value.

		IMPORT	flex_extend

; --- flex_midExtend ---
;
; On entry:	R0 == pointer to a flex anchor
;		R1 == `at' -- position in block to extend from
;		R2 == `by' -- how many bytes to extend (may be -ve)
;
; On exit:	CS if it failed due to lack of memory, CC otherwise
;
; Use:		Either creates a gap in a block (by>0) or deletes bytes
;		from a block.  This is always done in such a way that the
;		byte originally at offset `at' is now at offset `at'+`by'.

		IMPORT	flex_midExtend

; --- flex_init ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Initialises the flex heap for use.

		IMPORT	flex_init

; --- flex_save ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Saves some registers on the flex relocation stack.  R13
;		and R14 cannot be saved -- these registers are corrupted
;		during this routine's execution.
;
;		Values saved on the flex relocation stack are adjusted as
;		flex moves blocks of memory around, so that they still point
;		to the same thing as they did before.  Obviously, values
;		which aren't pointers into flex blocks may be corrupted.
;		Values pointing to objects deleted (either free blocks, or
;		areas removed by flex_midExtend) may also be corrupted.
;
;		Since this routine takes no arguments, some other method has
;		to be used.  The method chosen is to follow the call to
;		flex_save with a LDM or STM instruction containing the
;		registers to be saved.  This instruction is skipped by the
;		routine, and thus not executed.
;
;		Note that if you give the LDM or STM the same condition code
;		as the BL preceding it, it will never be executed, since
;		flex_save skips it if the condition is true and it can't be
;		executed if the condition is false.

		[	:DEF:FLEX_STACK
		IMPORT	flex_save
		]

; --- flex_load ---
;
; On entry:	--
;
; On exit:	Registers loaded from relocation stack as requested
;
; Use:		Restores registers saved on flex's relocation stack.  See
;		flex_save for calling information and details about the
;		relocation stack.

		[	:DEF:FLEX_STACK
		IMPORT	flex_load
		]

;----- Useful macros --------------------------------------------------------

; --- Macro: FSAVE ---
;
; Arguments:	rList == quoted register list to save on relocation stack
;
; Use:		Assembles code to write the given register list on the
;		flex relocation stack.  The register list should be in the
;		same form as that for an STM or LDM instruction.
;
;		For full details about the flex relocation stack, see
;		flex_save.

		[	:DEF:FLEX_STACK

		MACRO
$label		FSAVE	$rList

		BL	flex_save
		STMEA	R14!,{$rList}

		MEND

		]

; --- Macro: FLOAD ---
;
; Arguments:	rList == quoted register list to read from relocation stack
;
; Use:		Assembles code to read the given register list from the
;		flex relocation stack.  The register list should be in the
;		same form as that for an STM or LDM instruction.
;
;		For full details about the flex relocation stack, see
;		flex_save.

		[	:DEF:FLEX_STACK

		MACRO
$label		FLOAD	$rList

		BL	flex_load
		LDMEA	R14!,{$rList}

		MEND

		]

;----- That's all, folks ----------------------------------------------------

		END
