|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.