;
; insert.s
;
; Insert zero-filled chunks of data
;
;  1994-1998 Straylight
;

;----- Licensing note -------------------------------------------------------
;
; This file is part of Straylight's BASIC Assembler Supplement.
;
; BAS 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.
;
; BAS 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 BAS.  If not, write to the Free Software Foundation,
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

;----- Standard header ------------------------------------------------------

		GET	libs:header
		GET	libs:swis

		GET	libs:stream

;----- External dependencies ------------------------------------------------

		GET	sh.bas
		GET	sh.workspace

;----- Main code ------------------------------------------------------------

		AREA	|BAS$$Code|,CODE,READONLY

; --- insert_align ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Inserts `0' bytes to align O% and P% to the next word
;		boundary.

		EXPORT	insert_align
insert_align	ROUT

		STMFD	R13!,{R0,R14}		;Save some registers
		LDR	R14,[R7,#:INDEX:be__percents]
		LDR	R0,[R14,#('P'-'A')*4]	;Load current loc counter
		ANDS	R0,R0,#3		;Get non-word-alignedness
		RSBNE	R0,R0,#4		;Work out bytes to insert
		BLNE	insert_reserve		;Reserve so many bytes
		LDMFD	R13!,{R0,PC}^		;And return to caller

		LTORG

; --- insert_reserve ---
;
; On entry:	R0 == amount of memory to reserve
;
; On exit:	--
;
; Use:		Reserves R0 bytes of memory at the current position.  The
;		memory is filled with 0s.

		EXPORT	insert_reserve
insert_reserve	ROUT

		STMFD	R13!,{R0-R9,R12,R14}	;Save some registers
		MOV	R12,R7			;Get workspace in R12

		LDR	R14,be__percents	;Load the % variable address
		ADD	R14,R14,#('O'-'A')*4	;Find O% and P%
		LDMIA	R14,{R1,R3}		;Load them out nicely
		ADD	R2,R1,R0		;Bump along O%
		ADD	R3,R3,R0		;And bump along P%
		STMIA	R14,{R2,R3}		;Save them back again

		CMP	R0,#0			;Insert no bytes?
		BEQ	%90insert_reserve	;Yup -- do nothing then
		MOV	R2,#0			;A zero word

		TST	R1,#3			;Is destination word-aligned?
		BEQ	%10insert_reserve	;Yes -- skip onwards then
00		STRB	R2,[R1],#1		;Zero a single byte
		SUBS	R0,R0,#1		;Decrement counter
		BEQ	%90insert_reserve	;Done it all -- return
		TST	R1,#3			;Is destination word-aligned?
		BNE	%00insert_reserve	;No -- go round again

		; --- Now blast 0s out AQAP ---

10		MOV	R3,#0
		MOV	R4,#0
		MOV	R5,#0
		MOV	R6,#0
		MOV	R7,#0
		MOV	R8,#0
		MOV	R9,#0

		SUBS	R0,R0,#16		;4 or more words to do?
		BLT	%03insert_reserve
		SUBS	R0,R0,#16		;8 or more words to do?
		BLT	%02insert_reserve

01		STMIA	R1!,{R2-R9}		;Blank out 8 words
		SUBS	R0,R0,#32		;Decrement counter
		BGE	%01insert_reserve	;And keep going round

		CMP	R0,#-32			;Are we finished?
		BEQ	%90insert_reserve	;Yes -- return then

02		ADDS	R0,R0,#16		;4 whole words to do?
		BLT	%03insert_reserve
		STMIA	R1!,{R2-R5}		;Blank out 4 words
		BEQ	%90insert_reserve	;Done -- return then
		SUB	R0,R0,#16

03		ADDS	R0,R0,#8		;2 whole words to do?
		BLT	%04insert_reserve
		STMIA	R1!,{R2,R3}		;Blank out 2 words
		BEQ	%90insert_reserve	;Done -- return then
		SUB	R0,R0,#8

04		ADDS	R0,R0,#4		;1 word to do?
		BLT	%05insert_reserve
		STR	R2,[R1],#4		;Blank out 1 word
		BEQ	%90insert_reserve	;Done -- return then
		SUB	R0,R0,#4

05		ADDS	R0,R0,#4
		BEQ	%90insert_reserve	;Done -- return then

06		STRB	R2,[R1],#1		;Save 1 byte
		SUBS	R2,R2,#1
		BGT	%06insert_reserve

90		LDMFD	R13!,{R0-R9,R12,PC}^	;And return to caller

		LTORG

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

		END
