#include <machine/asm.h>
#include "assym.h"
#undef EMULATE_INKERNEL
#define S_R0 (%fp)
#define S_R1 4(%fp)
#define S_R2 8(%fp)
#define S_R3 12(%fp)
#define S_R4 16(%fp)
#define S_R5 20(%fp)
#define S_R6 24(%fp)
#define S_R7 28(%fp)
#define S_R8 32(%fp)
#define S_R9 36(%fp)
#define S_R10 40(%fp)
#define S_R11 44(%fp)
#define S_AP 48(%fp)
#define S_FP 52(%fp)
#define S_SP 56(%fp)
#define S_PC 60(%fp)
#define S_PSL 64(%fp)
#define PSL_C 1
#define PSL_V 2
#define PSL_Z 4
#define PSL_N 8
#define PSL_Q 15 # all four
#
#
ALTENTRY(unimemu)
pushl %r0
movl 8(%sp),%r0 # get trap address
movzbl (%r0),%r0 # fetch insn generating trap
caseb %r0,$0x74,$1 # case to jump to address
0: .word emodd-0b
.word polyd-0b
1: movl (%sp)+,%r0 # restore reg
rsb # continue fault
#
#
#ifdef EMULATE_INKERNEL
touser: movl (%sp),-52(%sp) # save rsb address on top of new stack
movl 4(%sp),%r0 # restore saved reg
addl2 $12,%sp # pop junk from stack
pushr $0x7fff # save all regs
movl %sp,%fp # new frame pointer
tstl -(%sp) # remember old rsb address
incl S_PC # skip matching insn
rsb
#else
touser: mfpr $PR_USP,%r0 # get user stack pointer
movl 4(%sp),-68(%r0) # move already saved %r0
movl (%sp),-72(%r0) # move return address
movq 12(%sp),-8(%r0) # move pc + psl
addl2 $12,%sp # remove moved fields from stack
movl $1f,(%sp) # change return address
rei
1: subl2 $8,%sp # trapaddr + psl already on stack
pushr $0x7ffe # %r0 already saved
subl2 $8,%sp # do not trash %r0 + retaddr
movab 4(%sp),%fp
incl S_PC # skip matching insn
rsb
#endif
#
#
goback: movl %fp,%sp # be sure
popr $0x7fff # restore all regs
rei
getval:
clrq %r0
pushr $(R2+R3+R4+R5+R6)
movl S_PC,%r3 # argument address
extzv $4,$4,(%r3),%r2 # get mode
caseb %r2,$0,$0xf
0: .word getval_literal-0b # 0-3 literal
.word getval_literal-0b
.word getval_literal-0b
.word getval_literal-0b
.word 2f-0b # 4 indexed
.word getval_reg-0b # 5 register
.word getval_regdefer-0b # 6 register deferred
.word 2f-0b # 7 register deferred
.word getval_ai-0b # 8 autoincrement
.word 2f-0b # 9 autoincrement deferred
.word getval_bytedis-0b # A byte displacement
.word 2f-0b # B byte displacement deferred
.word 2f-0b # C word displacement
.word 2f-0b # D word displacement deferred
.word getval_longdis-0b # E longword displacement
.word 2f-0b # F longword displacement deferred
#ifdef EMULATE_INKERNEL
2: movab 0f,%r0
movl %r2,%r1
brw die
0: .asciz "getval: missing address mode %d\n"
#else
2: .word 0xffff # reserved operand
#endif
getval_literal:
movzbl (%r3)+,%r0 # correct operand
brw 4f
getval_reg:
extzv $0,$4,(%r3),%r2 # Get reg number
incl %r3
ashl $2,%r2,%r2
addl3 %fp,%r2,%r5
bsbw emul_extract
brw 4f
getval_regdefer:
extzv $0,$4,(%r3),%r2 # Get reg number
incl %r3
ashl $2,%r2,%r2
addl2 %fp,%r2
movl (%r2),%r5
bsbw emul_extract
brw 4f
getval_ai:
extzv $0,$4,(%r3),%r2 # Get reg number
incl %r3
movl %r3,S_PC
ashl $2,%r2,%r2
addl2 %fp,%r2
movl (%r2),%r5
bsbw emul_extract
addl2 %r6,(%r2)
movl S_PC,%r3
brw 4f
getval_bytedis:
extzv $0, $4, (%r3), %r2 # get register
incl %r3
ashl $2,%r2,%r2
addl2 %fp,%r2
movl (%r2),%r5
movzbl (%r3),%r4
incl %r3
addl2 %r4, %r5
bsbw emul_extract
brw 4f
getval_longdis:
extzv $0, $4, (%r3), %r2 # get register
incl %r3
ashl $2,%r2,%r2
addl2 %fp,%r2
movl (%r2),%r5
movl (%r3)+,%r4
addl2 %r4, %r5
bsbw emul_extract
4: movl %r3,S_PC
popr $(R2+R3+R4+R5+R6)
rsb
emul_extract:
cmpl $0x8, %r6
bgeq 1f
.word 0xffff # reserved operand
1:
caseb %r6, $0x1, $0x7
0: .word 1f-0b # 1: byte
.word 2f-0b # 2: word
.word 9f-0b # unknown
.word 4f-0b # 4: longword
.word 9f-0b # unknown
.word 9f-0b # unknown
.word 9f-0b # unknown
.word 8f-0b # 8: quadword
1: movzbl (%r5), %r0
rsb
2: movzwl (%r5), %r0
rsb
4: movl (%r5), %r0
rsb
8: movq (%r5), %r0
rsb
9:
.word 0xffff # reserved operand
rsb
getval_dfloat:
clrq %r0
pushr $(R2+R3+R6) # use %r2+%r3 as scratch reg
movl S_PC,%r3 # argument address
extzv $4,$4,(%r3),%r2 # get mode
caseb %r2,$0,$0x3
0: .word 1f-0b # 0-3 literal
.word 1f-0b
.word 1f-0b
.word 1f-0b
movl $0x8, %r6
bsbw getval
brw 4f
1: insv (%r3),$0,$3,%r0 # insert fraction
extzv $3,$3,(%r3),%r2 # get exponent
addl2 $128,%r2 # bias the exponent
insv %r2,$7,$8,%r0 # insert exponent
tstb (%r3)+
movl %r3,S_PC
4:
popr $(R2+R3+R6)
rsb
getval_long:
clrl %r0
pushr $(R6+R1)
movl $0x4, %r6
bsbw getval
popr $(R6+R1)
rsb
getval_word:
clrl %r0
pushr $(R6+R1)
movl $0x2, %r6
bsbw getval
popr $(R6+R1)
rsb
getval_byte:
clrl %r0
pushr $(R6+R1) # use %r2+%r3 as scratch reg
movl $0x1, %r6
bsbw getval
popr $(R6+R1)
rsb
#
#
getaddr_byte:
clrl %r0
pushr $(R2+R3) # use %r2+%r3 as scratch reg
movl S_PC,%r3 # argument address
extzv $4,$4,(%r3),%r2 # get mode
caseb %r2,$0,$0xf
0: .word 2f-0b # 0-3 literal
.word 2f-0b
.word 2f-0b
.word 2f-0b
.word 2f-0b # 4
.word 6f-0b # 5 register
.word 5f-0b # 6 deferred
.word 2f-0b # 7 autodecr (missing)
.word 2f-0b # 8 autoincr (missing)
.word 2f-0b # 9 autoincr deferred (missing)
.word 7f-0b # 10 byte disp
.word 2f-0b # 11 byte disp deferred (missing)
.word 8f-0b # 12 word disp
.word 2f-0b # 13 word disp deferred (missing)
.word 1f-0b # 14 long disp
.word 2f-0b # 15 long disp deferred (missing)
#ifdef EMULATE_INKERNEL
2: movab 3f,%r0
movl %r2,%r1
brw die # reserved operand
3: .asciz "getaddr_byte: missing address mode %d\n"
#else
2: .word 0xffff # reserved operand
#endif
1: extzv $0,$4,(%r3),%r2 # Get reg number
incl %r3
movl (%fp)[%r2],%r0 # Register contents
addl2 (%r3),%r0 # add displacement
cmpl %r2,$15 # pc?
bneq 0f # no, skip
addl2 $5,%r0 # compensate for displacement size
0: addl2 $4,%r3 # increase pc
brw 4f
5: extzv $0,$4,(%r3),%r2 # Get reg number
incl %r3
movl (%fp)[%r2],%r0
brw 4f
7:
extzv $0, $4, (%r3), %r2 # get register
incl %r3
movl (%fp)[%r2],%r0 # Register contents
pushl %r4
cvtbl (%r3),%r4
addl2 %r4,%r0 # add displacement
movl (%sp)+,%r4
cmpl %r2,$15 # pc?
bneq 0f # no, skip
addl2 $2,%r0 # compensate for displacement size
0: incl %r3 # increase pc
brw 4f
8:
extzv $0, $4, (%r3), %r2 # get register
incl %r3
movl (%fp)[%r2],%r0 # Register contents
pushl %r4
cvtwl (%r3),%r4
addl2 %r4,%r0 # add displacement
movl (%sp)+,%r4
cmpl %r2,$15 # pc?
bneq 0f # no, skip
addl2 $3,%r0 # compensate for displacement size
0: addl2 $2,%r3 # increase pc
brw 4f
6: extzv $0,$4,(%r3),%r2 # Get reg number
incl %r3
moval (%fp)[%r2],%r0
4: movl %r3,S_PC
popr $(R2+R3)
rsb
#
#
# - check for bad arguments
# - set PSL flags
# - do not use d-float instructions (may be emulated)
#
polyd: bsbw touser # go back to user mode
bsbw getval_dfloat # fetches argument to %r0/%r1
movq %r0,%r6
bsbw getval_word
movl %r0,%r4
bsbw getaddr_byte
movl %r0,%r3
clrq %r0
0: addd2 (%r3)+,%r0 # add constant
tstl %r4 # more?
beql 1f # no, exit
muld2 %r6,%r0 # multiply with arg
decl %r4 # lower degree
brb 0b
1: movq %r0,(%fp)
clrl S_R2
movl %r3,S_R3
clrq S_R4
brw goback
#ifdef EMULATE_INKERNEL
die: pushl %r1
pushl %r0
calls $2,_printf
movl %fp,sp
brw goback # anything may happen
#endif
#define TMPSIZE 0x20
#define PRECIS 0x7
#define TMPFRAC1 (%ap)
#define TMPFRAC2 32(%ap)
#define TMPFRACTGT 64(%ap)
#
emodd: bsbw touser
bicl2 $(PSL_C|PSL_V|PSL_Z|PSL_N), S_PSL
pushl %ap
subl2 $(3*TMPSIZE), %sp
movl %sp, %ap
movc5 $0x0, TMPFRAC1, $0x0, $TMPSIZE, TMPFRAC1
movc5 $0x0, TMPFRAC2, $0x0, $TMPSIZE, TMPFRAC2
movc5 $0x0, TMPFRACTGT, $0x0, $TMPSIZE, TMPFRACTGT
clrl -(%sp)
movl %sp, %r3
clrl -(%sp)
movl %sp, %r5
subl2 $0x10, %sp
movl %sp, %r6
bsbw getval_dfloat # get operand into %r0 and %r1
bicl3 $0x7f, %r0, %r4
cmpl %r4, $0x0
bneq 1f
bsbw getval_byte # get multiplier extension operand
bsbw getval_dfloat # get target operand
jmp zeroexit
1:
cmpw %r0, $0x8000
bneq 1f
bsbw getval_byte # get multiplier extension operand
bsbw getval_dfloat # get operand into %r0 and %r1
extzv $0, $0xff, %r0, %r0 # generate a resopflt -- XXX is this ok?
1:
movd %r0, TMPFRACTGT
bicl3 $0xffff7fff, %r0, %r6 # Extract the sign while we're here.
bsbw getval_byte # get multiplier extension operand
movzbl %r0, -(%sp)
movd %r9, %r0
pushl %r3
pushab TMPFRAC1
movab TMPFRACTGT, -(%sp)
calls $0x4, fltext_De
bsbw getval_dfloat # get operand into %r0 and %r1
bicl3 $0x7f, %r0, %r4
cmpl %r4, $0x0
bneq 1f
bsbw getval_byte # get multiplier extension operand
bsbw getval_dfloat # get target operand
jmp zeroexit
1:
cmpw %r0, $0x8000
bneq 1f
bsbw getval_byte # get multiplier extension operand
bsbw getval_dfloat # get operand into %r0 and %r1
extzv $0, $0xff, %r0, %r0 # generate a resopflt -- XXX is this ok?
1:
movd %r0, TMPFRACTGT
bicl3 $0xffff7fff, %r0, %r7 # Extract the sign while we're here.
movzbl $0x0, -(%sp) # no multiplier extension here
pushl %r5
pushab TMPFRAC2
movab TMPFRACTGT, -(%sp)
calls $0x4, fltext_De
addl3 (%r5), (%r3), %r9
subl2 $0x80, %r9
xorl2 %r7, %r6
pushab TMPFRAC1
calls $0x1, bitcnt
movl %r0, %r1
pushab TMPFRAC2
calls $0x1, bitcnt
movl %r0, %r2
clrd TMPFRACTGT
pushr $0x7fc
subl2 $0x8, %sp
movl %sp, %r1
subl2 $0x8, %sp
movl %sp, %r2
movl $PRECIS, %r5
movl $PRECIS, %r6
clrl %r7
1:
movab TMPFRAC1, %r7
addl3 %r5, %r7, %r3
movab TMPFRAC2, %r7
addl3 %r6, %r7, %r4
movzbl (%r3), %r10
movzbl (%r4), %r11
mull3 %r10, %r11, %r7
movl %r7, %r3
cvtld %r7, (%r2)
subl3 %r5, $0x8, %r8
subl3 %r6, $0x8, %r9
addl2 %r8, %r9
mull2 $0x8, %r9
subl2 $0x40, %r9
blss 9f
5: cmpl %r9, $0x1e
bleq 6f
subl2 $0x1e, %r9
ashl $0x1e, $0x1, %r8
cvtld %r8, (%r1)
muld2 (%r1), (%r2)
jmp 5b
6:
ashl %r9, $0x1, %r8
cvtld %r8, (%r1)
muld2 (%r1), (%r2)
addd2 (%r2), TMPFRACTGT
9:
cmpl %r5, $0x0
beql 2f
decl %r5
jmp 1b
2: cmpl %r6, $0x0
beql 3f
decl %r6
movl $PRECIS, %r5
jmp 1b
3:
addl2 $0x10, %sp
movl %r7, 0x14(%sp)
popr $0x7fc
clrl %r3
movl %r7, %r8
1:
bicl3 $0xffff7fff, %r8, %r5
bneq 2f
incl %r3
ashl $0x1, %r8, %r5
movl %r5, %r8
jmp 1b
2:
subl2 %r3, %r9
insv %r9, $0x7, $0x8, TMPFRACTGT
bisl2 %r6, TMPFRACTGT # set the sign
cmpl $0x80, %r9
blss 7f
brw 8f
7:
subl3 $0x80, %r9, %r8
movq TMPFRACTGT, TMPFRAC1
cmpl %r8, $0x20
blss 3f
bisl2 $PSL_V, S_PSL
3:
cmpl %r8, $0x38
blss 1f
movq $0d0.0, TMPFRAC2
jmp 9f
1:
movab TMPFRACTGT, %r0
movab TMPFRAC1, %r1
movb (%r0), 7(%r1)
bisb2 $0x80, 7(%r1)
movw 2(%r0), 5(%r1)
movw 4(%r0), 3(%r1)
movb 7(%r0), 2(%r1)
movb 6(%r0), 1(%r1)
subl3 %r8, $0x40, %r7
mnegl %r7, %r6
ashq %r6, TMPFRAC1, %r0 # shift right
ashq %r7, %r0, TMPFRAC2 # shift left
movab TMPFRAC2, %r0
movab TMPFRAC1, %r1
extv $0x18, $0x7, 4(%r0), (%r1)
extzv $0x7, $0x9, TMPFRACTGT, %r2
insv %r2, $0x7, $0x9, (%r1)
movw 5(%r0), 2(%r1)
movw 3(%r0), 4(%r1)
movw 1(%r0), 6(%r1)
subd3 TMPFRAC1, TMPFRACTGT, TMPFRAC2
jmp 9f
8:
movd $0d0.0, TMPFRAC1
movd TMPFRACTGT, TMPFRAC2
9:
cvtdl TMPFRAC1, %r4
bsbw getaddr_byte
movl %r4, (%r0)
bsbw getaddr_byte
movq TMPFRAC2, (%r0)
movd TMPFRAC2, %r0
addl2 $0x74, %sp
movl (%sp)+, %ap
tstd %r0
bgeq 1f
bisl2 $PSL_N, S_PSL
1:
brw goback
zeroexit:
bisl2 $PSL_Z, S_PSL
bsbw getaddr_byte
movl $0x0, (%r0)
bsbw getaddr_byte
movd $0d0, (%r0)
brw goback
bitcnt:
.word 0xffe
movl 4(%ap), %r0
movl $0x8, %r1
1: decl %r1
addl3 %r1, %r0, %r4
movzbl (%r4), %r2
ffs $0, $0x20, %r2, %r3
bneq 2f
cmpl %r1, $0x0
jeql 3f
jmp 1b
2:
subl3 %r3, $0x8, %r0
ashl $0x5, %r1, %r2
addl2 %r2, %r0
ret
3:
movl $0xffffffff, %r0
ret
fltext_De:
.word 0x831 # %r0 %r1 %r2 %r3 %r4 ap (no return)
movl 0x4(%ap), %r0 # %r0 - addr of source
movl 0x8(%ap), %r1 # %r1 - addr of fraction destination
movb (%r0), (%r1)
bisb2 $0x80, (%r1)+ # This is the hidden bit.
movb 3(%r0), (%r1)+
movb 2(%r0), (%r1)+
movb 5(%r0), (%r1)+
movb 4(%r0), (%r1)+
movb 7(%r0), (%r1)+
movb 6(%r0), (%r1)+
movb 0x10(%ap), (%r1)
movl 0x4(%ap), %r0 # %r0 - addr of source
movl 0xc(%ap), %r2 # %r2 - addr of exponent destination
extzv $0x7, $0x8, (%r0), (%r2) # get exponent out
ret