File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / d / dmp4 / run_code.s
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:30:21 2019 UTC (6 years, 11 months ago) by root
Branches: bsd, MAIN
CVS tags: v121, HEAD
Power 6/32 Unix version 1.21


# ************************************************************************
# *		"RUN THE CODE" ROUTINE
# *
# *  This routine will test the current instruction. The instruction will
# *  be moved to a page boundary and executed and the results will be
# *  verified. The code will be tested twice, once with an instruction 
# *  cache miss and once with a cache hit. To insure instruction cache 
# *  hits, the code will be executed twice -once with all pages validated
# *  in the memory map and the 2nd time with them invalidated. The results
# *  will be checked after the 2nd execution. 
# *  Successive calls to this routine will set the page boundary on 
# *  different bytes in the code to check page faults at each byte.
# *  The general template of the 16 byte test code will be:
# *
# *      <op-code> [<addr-mode>] [<offset#1>] [<addr-mode>] [<offset#2>]
# *
# *  any unused bytes will be padded with NOPs. At the end of the test
# *  code is a jump back to the instruction execution routine (below).
# *
# *  25-Jun-85 : added MULL2 / MULL3 changes
# *   1-Jul-85 : restore operand 2 between executions for MULL2.
# *  17-Jul-85 : look for FPM traps as instruction completion
# ************************************************************************
	.text
	.align 1
	.globl _run_code
_run_code:
	.word	0
	movpsl	_run_code_psl		/* save the current PSL            */
	callf	$4,_fill_code_buff	/* stuff the code buffer           */
	callf	$4,_set_psl		/* set up the initial PSL to use   */
# Save operand 2 for MULL2
	movl	*$_dmp_byte_op_2,_rc_bop2 /* save byte operand #2          */
	movl	*$_dmp_op_2,_rc_op2	/* save operand #2                 */
# Set the return from an FPP emulation trap
	clrl	_event_return
	tstl	_emulated_inst		/* should we get an FPM trap?      */
	beql	1f
	moval	_run_code_mtpr,_event_return	/* set the return address  */
1:
# Run with an instruction cache miss
	clrl	_i_cache_hit		/* 1st pass gets a cache miss      */
	callf	$4,_run_test		/* run the test code w/ cache miss */
# Run with an instruction cache hit
	movl	$1,_i_cache_hit		/* 2nd pass gets a cache hit       */
	movl	_rc_bop2,*$_dmp_byte_op_2 /* restore byte operand #2       */
	movl	_rc_op2,*$_dmp_op_2	/* restore operand #2              */
	callf	$4,_run_test		/* run the test code again         */
	ret				/* return                          */





# ************************************************************************
# *
# *		"RUN THE TEST" ROUTINE
# *
# *  This routine will set up the Instruction Code Cache Key and the
# *  memory map. It will call the routine that actually executes the
# *  test code ('_execute_code').
# *  looping on error is done in this routine.
# *
# ************************************************************************
	.text
	.align 1
	.globl _run_test
_run_test:
	.word	0
	clrl	_trans_acc_error	/* clear bad-acc-after-pg-flt flag */
	clrl	_fpm_trap_occurred	/* clear got-an-fpm-trap flag */
  
#########################################################################
# The error loop starts here:
# Get a new Code Cache Key to invalidate the instruction cache,
# Invalidate the instruction and data pages in the page table,
# and execute the test instrcution.
#########################################################################
_shift_loop:
	incl	_Codek			/* Bump code cache key         */
	cmpl	_Codek,$255		/* Last key yet ?              */
	jlss	1f
	movl	$1,_Codek		/* Reset Code key to 1         */
	mtpr	$1,$PACC		/* Purge all code cache        */
	nop
1:
	mtpr	_Codek,$CCK		/* Set new key                 */
 
#########################################################################
# If we're running in user mode, set up the stack pointer
# Invalidate the instruction and data pages in the page table,
# and execute the test instrcution.
#########################################################################
	tstl	_user_mode		/* are we in User mode?        */
	beql	1f
	callf	$4,_set_user_stack	/* set up the user stack data  */
1:	callf	$4,_invalidate_pages	/* invalidate page tbl entries */
	callf	$4,_execute_code	/* execute code with pg faults */
  
#########################################################################
# If the Force Loop flag is set then loop on the error
#########################################################################
	tstl	_force_loop		/* Is "force_loop" set?   */
	beql	1f
	brw	_shift_loop		/* then loop on the error */
1:
#########################################################################
#  Now verify the results of the instruction. 'test_ptr' points to the 
#  test routine to use. Check the Force Loop flag again to see if we
#  just had an error. If we don't start looping then exit.
#  If we're testing an emulated instruction then call the FPM checking
#  routine rather than the instruction's normal test routine.
#########################################################################
	callf	$4,_get_stored_value	/* get results of any store */
	tstl	_emulated_inst		/* emulated instruction?    */
	beql	1f
	callf	$4,_chk_fpm_trap	/* check the FPM interface  */
	brb	2f
1:	calls	$4,*_test_ptr		/* verify the final results */
2:	tstl	_force_loop		/* Is "force_loop" set?     */
	beql	1f
	jmp	_shift_loop		/* then loop on the error   */
1:
	ret				/* return */





# **************************************************************************
# *
# *	"ENABLE MEMORY MANAGEMENT AND EXECUTE THE CODE" Routine
# *
# *   Enable Memory Management, Load the ACC. and Execute the Test Code 
# *
# **************************************************************************
	.text
	.align	1
	.globl	_execute_code
_execute_code:
	.word	0
	moval	(r13),_ex_code_fp	/* save the frame pointer     */
	moval	(r14),_ex_code_sp	/* save the stack pointer     */
	clrl	_no_page_faults		/* clear the page fault count   */
	mtpr	$1,$TBIA		/* purge all Trans Buff entries */
	mtpr	$1,$MME			/* enable memory management     */
	jmp	1f			/* start the memory management  */
1:
	cmpl	_acc_ld_size,$DBL
	beql	1f
	ldf	_dbl_ld_acc		/* load the sgl accumulator    */
	brb	2f			/* or */
1:	ldd	_dbl_ld_acc		/* load the dbl accumulator    */
2:
	loadr	$0x3fff,_load_regs	/* load regs 0 - 13 (FP)       */
	movl	_init_psl,-(sp)		/* push the PSL to use         */
	movl	_code_addr,-(sp)	/* push the test code's PC     */
	clrl	_clock_event		/* clear diagnostic clock flag */
	tstl	_emulated_inst		/* check if inst is emulated   */
	beql	1f
	movl	$FPM_CODE,_exp_event	/* expect an FPM event         */
1:
	rei				/* switch modes & execute code */
	halt				/* we shouldn't ever get here  */
 
##########################################################################
# The only way here (knock on wood) is after the Translation faults.
# - Save the PSL, the registers, and the accumulator
##########################################################################
	.globl _ex_code_return
_ex_code_return:
	movpsl	_psl_val		/* save the final PSL        */
	clrl	_exp_event		/* clear event-expected flag */
	storer	$0x3fff,_store_regs	/* store regs 0 - 13         */
	cmpl	_acc_st_size,$DBL
	beql	1f
	stf	_dbl_st_acc		/* store the sgl accumulator */
	brb	2f
1:	std	_dbl_st_acc		/* store the dbl accumulator */
2:
##########################################################################
#  Disable Memory Management and Return
#     If we are in User mode the priveleged instruction fault handler will 
#     put us back into the Kernal Mode.
#    ( Return here after a floating point emulation (FPM) trap )
##########################################################################
	.globl _run_code_mtpr
_run_code_mtpr:
	mtpr	$2,$MME			/* disable memory management */
	nop
	mtpr	$_pcb0,$PCBB		/* set the current PCB addr  */
	movl	_ex_code_fp,fp		/* reload the frame pointer  */
	movl	_ex_code_sp,sp		/* reload the stack pointer  */
	ret				/* return */




# *************************************************************************
# *
# *			FILL IN THE CODE BUFFER ROUTINE
# *
# *  Set up the instruction code sequence  -shifted by 'shift_count'.
# *  After the instruction code, put a jump back to "run_code" and
# *  fill the rest of the code buffer with NOPs.
# *
# *************************************************************************
	.set	NOP_JMP,0x1010719f	/* jump to an absolute address */
	.text
	.align	1
	.globl	_fill_code_buff
_fill_code_buff:
	.word	0
	movl	$START_OF_CODE,r0
	addl2	_shift_count,r0		/* get the 1st addr for the code */
	movl	r0,_code_addr		/* save the starting address     */
	movab	_inst_buf,r1		/* get the address of the code   */
1:	movb	(r1),(r0)		/* move the code to the code buf */
	incl	r0
	aoblss	$_end_of_inst_buf,r1,1b
 
########################################################################
# Fill the rest of the buffer with NOPs
########################################################################
	movl	$0x10,r1		/* 0x10 = NOP op-code         */
1:	movb	r1,(r0)			/* put NOPs in the code space */
	aobleq	$END_OF_CODE,r0,1b
  
########################################################################
# After the instruction code, put a jump back to "_ex_code_return"
########################################################################
	movl	$NOP_JMP,_sgl_dummy1	/* "<nop><nop><jmp><abs addr>" */
	clrl	r1
1:	movb	_sgl_dummy1(r1),(r0)	/* move 'jmp' to the code buf */
	incl	r0
	aoblss	$4,r1,1b
  
	moval	_ex_code_return,_sgl_dummy1 /* jmp to 'ex_code_return' */
	clrl	r1
1:	movb	_sgl_dummy1(r1),(r0)	/* move the code to the code buf */
	incl	r0
	aoblss	$4,r1,1b
	ret				/* return */





# ***********************************************************************
# *
# *	SET UP THE INITIAL PSL TO BE USED WITH THE TEST 
# *
# ***********************************************************************
	.text
	.align	1
	.globl	_set_psl
_set_psl:
	.word	0
	tstl	_dbl_ld_acc		/* set the PSL flag bits */
	movpsl	_init_psl		/* current PSL = base PSL      */
	andl2   $0xffffff7f,_init_psl	/* clear the DBL acc bit       */
	cmpl	_acc_ld_size,$DBL	/* are we loading a DBL acc?   */
	bneq	1f			/*    -NO, jump                */
	orl2	$PSL_DBL,_init_psl	/*    -Yes, set the DBL bit    */
1:
	mfpr	$PCBB,r0		/* get the current PCB pointer */
	tstl	_user_mode		/* Run process in USER mode?   */
	bneq	1f			/*   - yes                     */
	andl2	$0xfeffffff,_init_psl	/* clear the User Mode bit     */
	brb	2f
1:
	andl2	$0xfbe0ffff,_init_psl	/* clear Int. Stack bit & IPL  */
	orl2	$0x01000000,_init_psl	/* set the PSL's User Mode bit */
2:
	ret				/* return */ 





# *************************************************************************
# *
# * 	SET UP THE STACK POINTER AND THE STACK DATA FOR TESTS IN USER MODE
# *
# *  Set up the user stack pointer and set up the stack data for POP's
# *************************************************************************
	.text
	.align	1
	.globl	_set_user_stack
_set_user_stack:
	.word	0
	mfpr	$PCBB,r0		/* get the current PCB pointer */
	cmpl	$0x7e,_addr_code	/* PUSH addressing mode ?      */
	bneq	1f
	movl	$_sp_page,PCB_USP(r0)	/* set init PCB_USP for PUSH   */
	brb	2f
1:	cmpl	$0x67,_op_code		/* PUSHD instruction?          */
	bneq	3f
	movl	$_sp_plus,PCB_USP(r0)	/* set init PCB_USP for PUSHD  */
	brb	2f
3:	movl	$_sp_minus,PCB_USP(r0)	/* set init PCB_USP for other  */
 
#########################################################################
#	Now set up the data for POP addressing modes
#
#  This bit of code assumes that if op #1 is a popped that op #2 is too.
#  It also assumes that op #3 is never poppped -just it's address.
#########################################################################
2:
	cmpl	$0x8e,_addr_code	/* POP SP addressing?          */
	beql	1f
	cmpl	$0x9e,_addr_code	/* POP SP deferred addr.?      */
	bneq	2f			/* not POP -skip the rest      */
	cmpl	$3,_no_ops		/* check for 3 operands.       */
	bneq	1f
	movl	_sgl_value_10,_sp_plus	/* set up 3rd POP operand      */
1:	cmpl	$1,_no_ops		/* check for 1 operand.        */
	beql	1f
	movl	_sgl_value_9,_sp_page	/* set up 2nd POP operand      */
1:	movl	_sgl_value_8,_sp_minus	/* set up 1st POP operand      */
2:
	ret				/* return */ 




# ************************************************************************
# *
# *	INVALIDATE THE TEST PAGES IN THE PAGE TABLE ROUTINE
# *
# ************************************************************************
	.text
	.align	1
	.globl	_invalidate_pages
_invalidate_pages:
	.word	0
	movl	$START_OF_CODE,r0	/* get 1st code buffer address  */
	shar	$PGSHIFT,r0,r0		/* get 1st page # to invalidate */
	addl3	$15,r0,r1		/* invalidate 15 pages          */
1:
	andl2	$0x7fffffff,_Sysmap[r0]	/* mask out the Valid bit       */
	aoblss	r1,r0,1b		/*  ... for all test code pages */
	ret				/* return */




# *************************************************************************
# *
# *	GET THE STORED VALUE FOR STORE OPERATIONS
# *
# *  The stored data will be put into 'dbl_value_3'.
# *  If the instruction is MULL2 or MULL3 call the appropriate routine.
# *  Otherwise, the store would have been onto the stack, to register(s) 0/1,
# *  or to memory -either in operand #1 or in byte-operand #1.
# *  If the instruction being tested isn't either MULL2, MULL3, or a 
# *  floating point store instruction then this routine will just exit.
# *
# *************************************************************************
	.text
	.align	1
	.globl	_get_stored_value
_get_stored_value:
	.word	0
	cmpl	_op_code,$MULL2_OP_CODE	/* Are we testing MULL2?      */
	bneq	1f
	callf	$4,_get_mull2_store	/* then get MULL2's result    */
	ret				/* return */
1:
	cmpl	_op_code,$MULL3_OP_CODE	/* Are we testing MULL2?      */
	bneq	1f
	callf	$4,_get_mull3_store	/* then get MULL3's result    */
	ret				/* return */
1:
	cmpl	$STORE,_op_type		/* was it a store operation?  */
	beql	1f
	ret				/* return if not a store inst */
1:
	cmpl	$0x7e,_addr_code	/* PUSH addressing mode ?     */
	beql	1f
	cmpl	$0x67,_op_code		/* PUSHD instruction?         */
	bneq	2f
	movl	_sp_page,_dbl_value_3+4	/* get the LS value pushed    */
1:
	movl	_sp_minus,_dbl_value_3	/* get the operand pushed     */
	brw	3f
2:
#########################################################################
#    - Next check to see if the store would be to register 0/1
#########################################################################
	cmpl	$ADR_REG,_addr_mode	/* register addressing mode?  */
	bneq	1f			/*   -no                      */
	clrl	r0			/*   -yes, get the MSW stored */
	movl	_store_regs[r0],_dbl_value_3	/* from the final r0. */
	incl	r0			/* get the LSW value stored   */
	movl	_store_regs[r0],_dbl_value_3+4	/* from the final r1. */
	brw	3f
1:
#########################################################################
#    - If not Stack or Register addressing, then the store went to memory
#########################################################################
	cmpl	$ADR_B_DSP,_addr_mode	/* byte displacement addressing? */
	bneq	1f			/* branch if not byte addr.    */
	movl	$_dmp_byte_op_1,r0	/* get the addr of the operand */
	movl	(r0),_dbl_value_3	/* get the MS longwored stored */
	addl2	$4,r0
	movl	(r0),_dbl_value_3+4	/* get the LS longwored stored */
	brw	3f
1:					/* byte disp. rel. addr. mode  */
	movl	$_dmp_op_1,r0		/* get the addr of the operand */
	movl	(r0),_dbl_value_3	/* get the MS longwored stored */
	addl2	$4,r0
	movl	(r0),_dbl_value_3+4	/* get the LS longwored stored */
3:
	ret				/* return */




# *************************************************************************
# *
# *	GET THE STORED VALUE FOR THE MULL2 INSTRUCTION
# *
# *  The stored data will be put into 'dbl_value_2'.
# *  The store would have been into register 4, or to memory -either in 
# *  operand #2 or in byte-operand #2.
# *
# *************************************************************************
	.text
	.align	1
	.globl	_get_mull2_store
_get_mull2_store:
	.word	0
#########################################################################
#    - Check to see if the store would be to register 6
#########################################################################
	cmpl	$ADR_REG,_addr_mode	/* register addressing mode?  */
	bneq	1f			/*   -no                      */
	movl	$4,r0			/*   -yes, get the data       */
	movl	_store_regs[r0],_dbl_value_3	/* from the final R4. */
	brw	3f
1:
#########################################################################
#    - If not Register addressing, then the store went to memory
#########################################################################
	cmpl	$ADR_B_DSP,_addr_mode	/* byte displacement addressing? */
	bneq	1f			/* branch if not byte addr.    */
	movl	$_dmp_byte_op_2,r0	/* get the addr of the operand */
	movl	(r0),_dbl_value_3	/* get the data stored         */
	brw	3f
1:
	movl	$_dmp_op_2,r0		/* get the addr of the operand */
	movl	(r0),_dbl_value_3	/* get the data stored         */
3:
	ret				/* return */




# *************************************************************************
# *
# *	GET THE STORED VALUE FOR THE MULL3 INSTRUCTION
# *
# *  The stored data will be put into 'dbl_value_3'.
# *  The store would have been onto the stack, to a register ( R6 or R8 ),
# *  or to memory -either in operand #3 or in byte-operand #3.
# *
# *************************************************************************
	.text
	.align	1
	.globl	_get_mull3_store
_get_mull3_store:
	.word	0
	cmpl	$0x7e,_addr_code3	/* PUSH addressing mode ?  */
	bneq	1f
	movl	_sp_page,_dbl_value_3	/* get the pushed result   */
	brw	3f
1:
#########################################################################
#    - Next check to see if the store would be to a register 
#########################################################################
	cmpl	$ADR_REG,_addr_mode	/* register addressing mode?  */
	bneq	4f			/*   -no                      */
	cmpl	$0x56,_addr_code3	/* store to register 6?       */
	bneq	1f			/*   -no                      */
	movl	$6,r0			/*   -yes, check register 6.  */
	brb	2f
1:	movl	$8,r0			/*  get data from register 8. */
2:	movl	_store_regs[r0],_dbl_value_3  /* get result from reg  */
	brw	3f
4:
#########################################################################
#    - If not Stack or Register addressing, then the store went to memory
#########################################################################
	cmpl	$ADR_B_DSP,_addr_mode	/* byte displacement addressing? */
	bneq	1f			/* branch if not byte addr.    */
	movl	$_dmp_byte_op_3,r0	/* get the addr of the operand */
	movl	(r0),_dbl_value_3	/* get the data stored         */
	brw	3f
1:
	movl	$_dmp_op_3,r0		/* get the addr of the operand */
	movl	(r0),_dbl_value_3	/* get the data stored         */
3:
	ret				/* return */



###########################################################################
# 			DATA STORAGE
###########################################################################
	.align 2
_ex_code_sp:				/* save stack pointer value here */
	.long	0
_ex_code_fp:				/* save frame pointer value here */
	.long	0
_rc_bop2:				/* save byte operand #2 here     */
	.long	0
_rc_op2:				/* save operand #2 here          */
	.long	0



unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.