MiniUnix/usr/sys/mxsys/emul.s
.globl nofault,emtrap,trapem
rti = 2
PS = 177776
/
/
trapem:
mov *$PS,-4(sp) / trap type
mov r0,-(sp)
tst -(sp)
mov r1,-(sp)
mov $12.,-(sp)
add sp,*sp
mov 4(sp),-(sp)
bic $!17,*sp
jsr pc,trapems
tst (sp)+
mov (sp)+,r0 / return stack pointer
mov (sp)+,r1
tst (sp)+
add $6,sp
mov -(sp),-(r0)
mov -(sp),-(r0)
mov -(sp),-(r0)
mov r0,sp
mov (sp)+,r0
rti / return from emulation
/
/
/
/
/
/
/ EXTENDED INSTRUCTION SET EMULATOR FOR PDP 11/10
/
/
/ This program is designed to allow the use
/ of the PDP 11/40 instruction set on the PDP 11/10
/ in an environment which handles traps in the
/ same manner as the UNIX operating system.
/ This program returns the same results
/ and condition codes that the internal DEC
/ instruction does on the PDP 11/40. This allows
/ programs which run under UNIX on an 11/40 to
/ be run on an 11/10 with a UNIX-like system.
/ The functions implimented are listed below:
/ multiply (MUL)
/ divide (DIV)
/ arithmetic shift (ASH)
/ arithmetic shift combined (ASHC)
/ exclusive OR (XOR)
/ subtract one and branch (SOB)
/
/
/
/
/ Upon entry to this program the stack is assumed
/ to look as follows:
/
/ < bottom portion of stack >
/ UPS -- user's program status word at time of trap
/ UPC -- user's program counter at time of trap
/ UR0 -- user's r0 at time of trap
/ --- -- not used by this program
/ UR1 -- user's r1
/ USP -- user's stack pointer
/ DEV -- trap type
/ RPC -- return address to trap routine
/ < top of stack >
/
/
/
/
/ After it is determined that the trap is an illegal
/ instruction trap ( DEV = 1 ), a register save routine
/ is used which saves the other user registers and
/ allocates temporary space for variables.
/
/ This causes the stack to look as follows:
/
/ < bottom portion of stack >
/ UPS
/ UPC
/ UR0
/ ---
/ UR1
/ USP
/ DEV
/ RPC
/ UR5 : user's r5 <--- register 5 points here
/ UR4 : user's r4
/ UR3 : user's r3
/ UR2 : user's r2
/ nfaddr : used to hold old nofault address
/ PCFLG : used to hold value to increment UPC by
/ DSTN : used to hold address of destination field
/ MODMAP : used to hold interim condition codes
/ INST: used to hold instruction being emulated <--- stack pointer
/ < top of stack >
/
/
/
/
/
UPC =16
UPS =20
MODMAP =2
INST =0
DSTN =4
PCFLG =6
nfaddr =10
/
/
/
.text
/
/
.globl csv, cret
/
/
/
emul2.o = .
/
trapems:
jsr r5,csv
sub $12,sp
/ set up to catch traps which occur during emululation
mov nofault,nfaddr(sp)
mov $errrtn,nofault
/ find instruction which caused trap
mov UPC(r5),r0
mov -(r0),(sp)
/ is it one to be emululated?
cmp (sp),$070000 / 170000 for 40 testing
/ 070000 for 10 use
bgt 1f / bhis for 40 testing
/ bgt for 10 use
mov (sp),r0
bic $77,r0
cmp r0,$6700
beq ssxt
jmp errrtn
ssxt:
jsr pc,getsrc
bis $4,(r4) /set z-bit
clr *DSTN(sp)
bit $10,UPS(r5) /n-bit on?
beq 0f
dec *DSTN(sp)
bic $4,(r4) /clear z-bit
0:
mov $4,r2
jmp setcc
1:
/
/
/
/
/ this routine gets the even-odd register pair
/ specified in the instruction and moves
/ them into r0 and r1
/
/ find register number = n
mov (sp),r4
bic $177077,r4
asl r4
asl r4
swab r4
/ move register(n) into r0
movb regs(r4),r3
add r5,r3
mov (r3),r0
/ move register(n ORed with 1) into r1
bis $1,r4
movb regs(r4),r3
add r5,r3
mov (r3),r1
/
/
/ find out which function is to be performed
mov (sp),r4
bic $170777,r4
swab r4
jmp *fcntbl(r4)
fcntbl:
smul / multiply
sdiv / divide
sash / arithmetic shift
sashc / arithmetic shift combined
sxor / exclusive OR
errrtn / unimplimented
errrtn / unimplimented
ssob / subtract one and branch
/
/
/
/ this routine performs the multiply function
/
smul:
jsr pc,getsrc
/ set up flags for proper sign management
mov r0,r1
bge 1f
neg r1
inc r3
1:
clr r0
tst r2
bge 1f
neg r2
dec r3
1:
/ set counter for 17 cycles
mov $21,-(sp)
2:
/ use shift and add algorithm
clc
ror r0
ror r1
bcc 1f
add r2,r0
1:
dec (sp)
bne 2b
/ were signs the same?
cmp r3,(sp)+
beq 1f
/ no, negate the product
neg r0
neg r1
sbc r0
1:
/ was product greater than 15 bits long?
tst r1
bpl 1f
cmp $-1,r0
bne 2f
br 3f
1:
tst r0
beq 3f
2:
/ if so, set the C bit
bis $1,*r4
3:
/ was the register odd?
bit $100,(sp)
beq 1f
/ if so, move product to r0
mov r1,r0
1:
/ set up flags and quit
mov $1,r3
mov $17,r2
jmp strreg
/
/
/
/
/ this routine performs the division function
/ the algorithm used is taken directly
/ from the DEC microcode flow in order
/ to make all condition codes and results
/ agree in all cases.
/
sdiv:
/ if an odd register instruction, error
bit (sp),$100
beq 1f
jmp errrtn
1:
jsr pc,getsrc
mov r5,-(sp)
mov r1,r5
/ is divisor 0?
tst r2
bne div5
/ if so, quit
bis $7,*r4
br div12
div5:
/ is dividend negative?
tst r0
bge div16
/ yes
bis $17,*r4
neg r0
clr r1
sub r5,r1
sbc r0
bpl div16
div12:
/ error exit
bis $2,*r4
mov (sp)+,r5
mov $17,r2
jmp setcc
div16:
/ first step of algorithm
mov r2,r3
neg r3
clc
rol r1
rol r0
tst r2
bmi 1f
add r3,r0
br 2f
1:
add r2,r0
2:
adc r1
bic $1,*r4
/ test for overflow condition
bit $1,r1
beq 1f
tst r0
jne div12
clr r5
tst r2
bge 3f
inc r5
3:
bit $10,*r4
beq 3f
inc r5
3:
ror r5
jcc div12
1:
/ if no overflow, interate algorithm 15 times
mov $17,-(sp)
div19:
clc
rol r1
rol r0
clr r5
tst r2
bpl 1f
inc r5
1:
bit $2,r1
beq 1f
inc r5
1:
ror r5
bcc 1f
add r3,r0
br 2f
1:
add r2,r0
2:
adc r1
dec (sp)
bne div19
/ branch to appropriate cleanup and condition code routines
cmp r2,(sp)+
bgt 1f
bit $1,r1
beq div31
bne div33
1:
bit $1,r1
bne div23
div27:
add r2,r0
div23:
bit $10,*r4
bne div29
div26:
clr *r4
tst r1
beq 2f
bpl 1f
bis $10,*r4
br 1f
2:
bis $4,*r4
1:
jmp div42
div31:
sub r2,r0
div33:
bit $10,*r4
beq div37
neg r0
jmp div26
div29:
neg r0
div37:
mov r1,r3
neg r1
com r3
jmi div26
clr *r4
tst r1
beq 2f
bpl 1f
bis $10,*r4
br div42
2:
bis $4,*r4
1:
bis $2,*r4
div42:
/ exit procedure
mov (sp)+,r5
mov r0,r3
mov r1,r0
mov r3,r1
mov $1,r3
mov $-17,r2
jmp strreg
/
/
/
/
/ this routine performs the arithmetic shift function
/
sash:
jsr pc,getsrc
br 1f
/
/
/
/
/ this routine performs the arithmetic shift combined function
/
sashc:
jsr pc,getsrc
inc r3
1:
/ get shift distance
bic $177700,r2
bit $40,r2
beq 1f
bis $177700,r2
2:
/ right shift
tst r3
beq 3f
/ for ashc
asr r0
ror r1
br 4f
3:
/ for ash
asr r0
4:
bic $1,*r4
bcc 5f
bis $1,*r4
5:
inc r2
bne 2b
br 9f
1:
/ left shift
tst r2
beq 9f
1:
tst r3
beq 3f
/ for ashc
asl r1
rol r0
br 4f
3:
/ for ash
asl r0
4:
bvc 2f
bis $2,*r4
2:
bic $1,*r4
bcc 5f
bis $1,*r4
5:
dec r2
bgt 1b
9:
tst r3
bne 7f
/ for ash
mov r0,r1
br 8f
7:
bit $100,(sp)
beq 8f
/ for ashc
mov r1,r0
8:
/ exit
mov $17,r2
jmp strreg
/
/
/
/
/ this routine performs the exclusive OR function
/ using A xor B = A and NOT B or B and NOT A
/
sxor:
jsr pc,getsrc
mov r0,r1
bic r2,r0 / A AND NOT B
bic r1,r2 / B AND NOT A
bis r0,r2 / A XOR B
mov r2,*DSTN(sp)
bvc 1f
bis $2,*r4
1:
mov r2,r0
clr r1
mov $16,r2
jmp setnz
/
/
/
/
/ this routine performs the subtract one and
/ branch function
/ ( untested )
/
ssob:
mov (sp),r2
bic $177700,r2
/ subtract 1
dec r0
beq 1f
/ modify PC
asl r2
sub r2,UPC(r5)
1:
/exit
clr r3
clr r2
jmp strreg
/
/
/
/
/ this routine performs the decoding and
/ fetching of the source operand and
/ places it in register 2
/
getsrc:
mov INST+2(sp),r4
mov r4,r3
bic $177770,r4 / register
bic $177707,r3 / mode
asr r3
asr r3
clr PCFLG+2(sp)
/ if PC addressing
cmp r4,$7
bne 1f
mov $2,PCFLG+2(sp)
/ then modes 1,4 and 5 are errors
cmp r3,$2
jeq errrtn
cmp r3,$10
jeq errrtn
cmp r3,$12
jeq errrtn
1:
asr r3
bic $1,r3
movb regs(r4),r4
add r5,r4
jmp *mods(r3)
mods:
0f / modes 0,1
1f / 2,3
2f / 4,5
3f / 6,7
0:
/ contents of register
mov r4,r2
br 4f
1:
/ autoincrementing
mov (r4),r2
add $2,(r4)
br 4f
2:
/ autodecrementing
sub $2,(r4)
mov (r4),r2
br 4f
3:
/ indexed
mov (r4),r2
mov UPC(r5),r3
add $2,UPC(r5)
add PCFLG+2(sp),r2
add (r3),r2
4:
/ address of location in r2
/ is mode indirect?
bit $10,INST+2(sp)
beq 5f
/ if so, new address to r2
mov (r2),r2
5:
/ effective address to DSTN
mov r2,DSTN+2(sp)
/ contents to r2
mov (r2),r2
clr r3
mov $MODMAP+2,r4
add sp,r4
clr *r4
rts pc
/
/
/
/
/ this table contains the offset in bytes of the
/ user's registers in the stack based at r5
/
.data
regs:
.byte 14 / r0
.byte 10 / r1
.byte -6 / r2
.byte -4 / r3
.byte -2 / r4
.byte 0 / r5
.byte 6 / r6
.byte 16 / r7
.text
/
/
/
/
/ this routine stores the results of the operation
/ into the proper registers
/
strreg:
/ find register number = n
mov (sp),r4
bic $177077,r4
asl r4
asl r4
swab r4
/ single (r0) or double (r0-r1) register store
tst r3
beq 1f
/store r1 in r(n ORed with 1)
mov r4,r3
bis $1,r3
movb regs(r3),r3
add r5,r3
mov r1,(r3)
1:
/ store r0 in r(n)
movb regs(r4),r3
add r5,r3
mov r0,(r3)
/ branch to next routine by flag
tst r2
bge setnz
neg r2
br setcc
/
/
/
/
/ this routine cause a return to the regular
/ trap handler if an error is found so a normal
/ illegal instruction trap can be signalled
/
errrtn:
mov nfaddr(sp),nofault
sub $6,r5
mov r5,sp
mov (sp)+,r2
mov (sp)+,r3
mov (sp)+,r4
mov (sp)+,r5
add $6,sp
mov (sp)+,r1
tst (sp)+
mov (sp)+,r0
jmp emtrap
/
/
/
/
/ this routine sets the condition codes for
/ the n and z bits
/
setnz:
tst r0
bgt setcc
blt 1f
tst r1
bne setcc
bis $4,MODMAP(sp)
br setcc
1:
bis $10,MODMAP(sp)
/
/
/
/
/ this routine sets the proper condition codes
/ in the user's PS and jumps to cret which
/ cleans up the stack and causes the
/ return to the user
/
setcc:
bic r2,UPS(r5)
com r2
bic r2,MODMAP(sp)
bis MODMAP(sp),UPS(r5)
mov nfaddr(sp),nofault
jmp cret
/
/
/
/