# system initialization tables, modified from Intel ASM960 manual
# pages 3-140 thru 3-146.

	  .file     "startup.s"
	  .globl    system_address_table
	  .globl    prcb_ptr
	  .globl    start_ip
	  # .globl    cs1
	  .globl    user_stack
	  .globl    sup_stack
	  .globl    intr_stack

# define IAC address
     .set      local_IAC, 0xff000010

# core initialization block -- address 0
     .sect	code,text
     .word     system_address_table   # SAT pointer
     .word     prcb_ptr               # PRCB pointer
     .word     0
     .word     start_ip               # pointer to first IP
     .word     -(system_address_table + prcb_ptr + start_ip)	# cs1
     .word     0                      # cs1= -(segtab+PRCB+startup)
     .word     0
     .word     -1

# ----- initial PRCB
#
# this is your startup PRCB.  After initialization, this will be
# -- copied to ram.
prcb_ptr:
     .word     0x0                    # 0 - reserved
     .word     0xc                    # 4 - initialize to 0xc
     .word     0x0                    # 8 - reserved
     .word     0x0                    # 12 - reserved
     .word     0x0                    # 16 - reserved
     .word     intr_table             # 20 - interrupt table address
     .word     intr_stack             # 24 - interrupt stack pointer
     .word     0x0                    # 28 - reserved
     .word     0x0000027f             # 32
     .word     0x0000027f             # 36
     .word     fault_table            # 40 - fault table
     .word     0x0                    # 44 - reserved
     .space    12                     # 48 - reserved
     .word     0x0                    # 60 - reserved
     .space    8                      # 64 - reserved
     .word     0x0                    # 72 - reserved
     .word     0x0                    # 76 - reserved
     .space    48                     # 80 - scratch space (resumption)
     .space    44                     # 128 - scratch space (error)

# The system procedure table will only be used if software puts the
# -- processor into user mode and makes a supervisor procedure call

     .align    6
sys_proc_table:
     .word     0                      # reserved
     .word     0                      # reserved
     .word     0                      # reserved
     .word     sup_stack              # supervisor stack pointer
     .word     0                      # preserved
     .word     0                      # preserved
     .word     0                      # preserved
     .word     0                      # preserved
     .word     0                      # preserved
     .word     0                      # preserved
     .word     0                      # preserved
     .word     0                      # preserved
     .word     proc_entry_0           # procedure entry 0 (user)
     .word     (proc_entry_1 + 0x2)   # procedure entry 1 (sup.)

# ------------------------- initial segment table

		.align 6
system_address_table:
     .space    136                    # reserve 136 bytes
     .word     system_address_table
     .word     0x00fc00fb             # initialization words
     .space    8
     .word     sys_proc_table         # initialization words
     .word     0x304400fb

#
# ---Below are two "dummy" system procedures. In reality, these
# ---should contain the real system code, rather than returns
		.align 4
		.sect	code
proc_entry_0:
		ret
proc_entry_1:
		ret

# ---Processor stats execution at this spot after reset.
#---
start_ip:

#--
#-- copy the interrupt table to RAM
#--
	lda	1024,g0			#load length of int.table
	lda	0,g4			#init offset to 0
	lda	intr_table,g1		#load source
	lda	intr_ram,g2		#load addrs of new table
	bal	loop_here		#branch to move routine

#--
#--processor will copy PRCB to ram space, located at prcb_ram
#--
	lda	176,g0			#load length of prcb
	lda	0,g4			#initialize offset to 0
	lda	prcb_ptr,g1		#load source
	lda	prcb_ram,g2		#load destination
	bal	loop_here		#branch to move routine

#--
#--fix up the prcb to point to a new interrupt table
#--
	lda	intr_ram,g12		#load address
	st	g12,20(g2)		#store into PRCB

#
#--At this point, the prcb, and the interrupt table have been moved into
#--RAM.  It is time to issue a REINITIALIZE IAC, which will start us anew
#--with our RAM based prcb.
#--
#--The IAC msg, found in the 4 words located at the reinitialize_iac
#--label, contain pointers to the current System address table, the new
#--RAM based PRCB, and to the instruction pointer labeled start_again_ip
#

iac:
	lda	local_IAC,g5
	lda	reinitialize_iac,g6
	synmovq g5,g6

# --
#  -- Below is the software loop to move data
# --
loop_here:
	ldq	(g1)[g4*1],g8		#load 4 words into g8
	stq	g8,(g2)[g4*1]		#store to ram proc block
	addi	g4,16,g4		#increment index
	cmpibg	g0,g4,loop_here		#loop until done
	bx	(g14)

#
# -- The processor will begin execution here after being
# -- reinitialized.  We will now set up the stacks and continue

start_again_ip:
	lda	user_stack,fp		#set up user stack space
	lda	-0x40(fp),pfp		#load pfp just in case
	lda	0x40(fp),sp		#set up current stack ptr

	mov	0,g14			#g14 used by C compiler for
							#arguement lists past 13 argements.
							#initialize to 0

	lda	0x3b001000, g0	#set up arith, controls
	modac	g0, g0, g0		#to mask
								#unwanted exceptions

#
# -- call main code from here
#
# -- Note: This setup assumes a main module "main()" written in C.  Also
# -- no opens are done for stdin,stdout,stderr.  If I/O is required, the 
# -- devices would need to be opened before the call to main.

	callx	_main


reinitialize_iac:
	.word	0x93000000		#reinit IAC msg
	.word	system_address_table
	.word	prcb_ram		#use newly copied prcb
	.word	start_again_ip


#--------------other misc. stuff

	.sect	vars,data

#---define RAM area to copy the prcb & intr to after initial bootup

	.align 	6
intr_ram:
	.space 1024

prcb_ram:
	.space 176

	.align 6



	.align 6

user_stack:	#reserved area for the user stack
		#this can be located anywhere in memory
		#size is set depending on application needs

	.space 0x800

intr_stack:	#reserved area for the interrupt stack
		#this can be located anywhere in memory
	.space 0x200

#
sup_stack:
	.space	0x400		#reserve stack space for supv stack


#the end
