	# The executable start address is patched to refer to this code.

	# Register use:
	#  s0 = length of startup code rounded to an 8 byte boundary
	#  s1 = loop1
	#  s2 = real entry point
	# Stack use:
	#  sp...sp+32		register save
	#  sp+32...sp+128	copy loop
	#  sp+128...		original program data

#include <regdef.h>
#include "ultrix-defs.h"

	.text

	addi	sp,sp,-2048
	sw	a0,0(sp)
	sw	a1,4(sp)
	sw	a2,8(sp)
	sw	a3,12(sp)
	la	v0,decrypt_data		# set to decrypt_start-$L1
	lw	s0,off_decrypt_code_length(v0)
	lw	a0,off_decrypt_start_addr(v0)
	lw	a1,off_decrypt_data_length(v0)
	lw	s1,12(v0)		# loop1
	lw	s2,off_entry(v0)
	addi	a2,sp,128		# 256 bytes to hold start of data
					# segment
	move	a3,s0

	jal	decrypt

	# copy remaining code to stack
	addi	a1,sp,32		# copy dest base
	add	a2,a1,96		# copy dest limit
	move	a0,s1			# copy source
$L1:
	lw	v0,0(a0)
	lw	v1,4(a0)
	addi	a0,a0,8
	sw	v0,0(a1)
	sw	v1,4(a1)
	addi	a1,a1,8
	sltu	v0,a1,a2
	bne	v0,$0,$L1

	addi	v0,sp,32
	j	v0

loop1:	addi	a0,sp,128		# source
	li	a1,0x10000000		# dest
	add	a2,a1,s0		# end
$L5:	lw	v0,0(a0)
	lw	v1,4(a0)
	addi	a0,a0,8
	sw	v0,0(a1)
	sw	v1,4(a1)
	addi	a1,a1,8
	sltu	v0,a1,a2
	bne	v0,$0,$L5

	# data section has been restored; now restore registers
	# and branch to C startup code

	lw	a0,0(sp)
	lw	a1,4(sp)
	lw	a2,8(sp)
	lw	a3,12(sp)
	addi	sp,sp,2048
	j	s2

	.globl	_exit
_exit:
	li	v0,1
	syscall

	# To keep this code small, include a version of read that does
	# not set errno.
	.globl	read
read:
	li	v0,3
	syscall
	beq	a3,zero,$L6
	li	v0,-1
$L6:
	j	ra

#ifdef DEBUG
	.globl	write
write:
	li	v0,4
	syscall
	beq	a3,zero,$L6
	li	v0,-1
#endif

	.rdata
decrypt_data:
	.word	0,0,0,loop1,0
