#include <machine/asm.h>
#define return rsb
#define savepsl movpsl 4(%sp)
#define setpsl(reg) movl reg,4(%sp)
#define overflowpsl movl $2,4(%sp)
#define arg1 12(%sp)
#define arg2 16(%sp)
#define arg3 20(%sp)
#define arg4 24(%sp)
#define arg5 28(%sp)
#define arg6 32(%sp)
#define argub(num,reg) movzbl 8+4*num(%sp),reg
#define arguw(num,reg) movzwl 8+4*num(%sp),reg
#define argul(num,reg) movl 8+4*num(%sp),reg
#define argb(num,reg) cvtbl 8+4*num(%sp),reg
#define argw(num,reg) cvtwl 8+4*num(%sp),reg
#define argl(num,reg) movl 8+4*num(%sp),reg
#define toarg(reg,num) movl reg,8+4*num(%sp)
.text
.align 1
ALTENTRY(EMcrc)
argl(1,%r11) # (1) table address == %r11
argl(2,%r0) # (2) initial crc == %r0
argl(4,%r3) # (4) source address == %r3
arguw(3,%r2) # (3) source length == %r2
jeql Lcrc_out
Lcrc_loop:
xorb2 (%r3)+,%r0
extzv $0,$4,%r0,%r10
extzv $4,$28,%r0,%r1
xorl3 %r1,(%r11)[%r10],%r0
extzv $0,$4,%r0,%r10
extzv $4,$28,%r0,%r1
xorl3 %r1,(%r11)[%r10],%r0
sobgtr %r2,Lcrc_loop
tstl %r0
Lcrc_out:
savepsl
clrl %r1
return
.align 1
ALTENTRY(EMmovtc)
arguw(1,%r0) # (1) source length == %r0
argl(2,%r1) # (2) source address == %r1
argub(3,%r11) # (3) fill character == %r11
argl(4,%r3) # (4) table address == %r3
argl(6,%r5) # (6) destination address == %r5
arguw(5,%r4) # (5) destination length == %r4
jeql Lmovtc_out
Lmovtc_loop:
tstl %r0
jeql Lmovtc_2loop
movzbl (%r1)+,%r2
movb (%r3)[%r2],(%r5)+
decl %r0
sobgtr %r4,Lmovtc_loop
jbr Lmovtc_out
Lmovtc_2loop:
movb %r11,(%r5)+
sobgtr %r4,Lmovtc_2loop
Lmovtc_out:
cmpw arg1,arg5
savepsl
clrl %r2
return
.align 1
ALTENTRY(EMmovtuc)
arguw(1,%r0) # (1) source length == %r0
argl(2,%r1) # (2) source address == %r1
argub(3,%r11) # (3) escape character == %r11
argl(4,%r3) # (4) table address == %r3
argl(6,%r5) # (6) destination address == %r5
arguw(5,%r4) # (5) destination length == %r4
jeql Lmovtuc_out1
Lmovtuc_loop:
tstl %r0
jeql Lmovtuc_out1
movzbl (%r1),%r2
movzbl (%r3)[%r2],%r2
cmpl %r2,%r11
jeql Lmovtuc_out2
movzbl (%r1)+,%r2
movb (%r3)[%r2],(%r5)+
decl %r0
sobgtr %r4,Lmovtuc_loop
Lmovtuc_out1:
clrl %r2 # clear V-bit
brb Lmovtuc_out
Lmovtuc_out2:
movl $2,%r2 # set V-bit
Lmovtuc_out:
cmpw arg1,arg5
savepsl
bisl2 %r2,4(%sp) # merge V-bit into psl
clrl %r2
return
.align 1
ALTENTRY(EMmatchc)
argl(2,%r10) # (2) substring address == %r10
arguw(3,%r2) # (3) source length == %r2
argl(4,%r3) # (4) source address == %r3
arguw(1,%r11) # (1) substring length == %r11
jeql Lmatchc_out # temp source address == %r1
addl2 %r10,%r11 # temp substring address == %r0
tstl %r2
jeql Lmatchc_out
Lmatchc_loop:
cmpb (%r10),(%r3)
jneq Lmatchc_fail
movl %r3,%r1
movl %r10,%r0
Lmatchc_2loop:
cmpl %r0,%r11
jeql Lmatchc_succ
cmpb (%r0)+,(%r1)+
jeql Lmatchc_2loop
Lmatchc_fail:
incl %r3
sobgtr %r2,Lmatchc_loop
movl %r10,%r1
subl3 %r10,%r11,%r0
jbr Lmatchc_out
Lmatchc_succ:
movl %r1,%r3
movl %r11,%r1
clrl %r0
Lmatchc_out:
savepsl
return
.align 1
ALTENTRY(EMspanc)
argl(2,%r1) # (2) string address == %r1
argub(4,%r2) # (4) character-mask == %r2
argl(3,%r3) # (3) table address == %r3
arguw(1,%r0) # (1) string length == %r0
jeql Lspanc_out
Lspanc_loop:
movzbl (%r1),%r11
mcomb (%r3)[%r11],%r11
bicb3 %r11,%r2,%r11
jeql Lspanc_out
incl %r1
sobgtr %r0,Lspanc_loop
Lspanc_out:
savepsl
clrl %r2
return
.align 1
ALTENTRY(EMscanc)
argl(2,%r1) # (2) string address == %r1
argub(4,%r2) # (4) character-mask == %r2
argl(3,%r3) # (3) table address == %r3
arguw(1,%r0) # (1) string length == %r0
jeql Lscanc_out
Lscanc_loop:
movzbl (%r1),%r11
mcomb (%r3)[%r11],%r11
bicb3 %r11,%r2,%r11
jneq Lscanc_out
incl %r1
sobgtr %r0,Lscanc_loop
Lscanc_out:
savepsl
clrl %r2
return
.align 1
ALTENTRY(EMskpc)
argub(1,%r11) # (1) character == %r11
argl(3,%r1) # (3) string address == %r1
arguw(2,%r0) # (2) string length == %r0
jeql Lskpc_out # forget zero length strings
Lskpc_loop:
cmpb (%r1),%r11
jneq Lskpc_out
incl %r1
sobgtr %r0,Lskpc_loop
Lskpc_out:
tstl %r0 # be sure of condition codes
savepsl
return
.align 1
ALTENTRY(EMlocc)
argub(1,%r11) # (1) character == %r11
argl(3,%r1) # (3) string address == %r1
arguw(2,%r0) # (2) string length == %r0
jeql Lskpc_out # forget zero length strings
Llocc_loop:
cmpb (%r1),%r11
jeql Llocc_out
incl %r1
sobgtr %r0,Llocc_loop
Llocc_out:
tstl %r0 # be sure of condition codes
savepsl
return
.align 1
ALTENTRY(EMcmpc3)
argl(2,%r1) # (2) string1 address == %r1
argl(3,%r3) # (3) string2 address == %r3
arguw(1,%r0) # (1) strings length == %r0
jeql Lcmpc3_out
Lcmpc3_loop:
cmpb (%r1),(%r3)
jneq Lcmpc3_out
incl %r1
incl %r3
sobgtr %r0,Lcmpc3_loop
Lcmpc3_out:
savepsl
movl %r0,%r2
return
.align 1
ALTENTRY(EMcmpc5)
argl(2,%r1) # (2) string1 address == %r1
argub(3,%r11) # (1) fill character == %r11
arguw(4,%r2) # (1) string2 length == %r2
argl(5,%r3) # (3) string2 address == %r3
arguw(1,%r0) # (1) string1 length == %r0
jeql Lcmpc5_str2
Lcmpc5_loop:
tstl %r2
jeql Lcmpc5_str1loop
cmpb (%r1),(%r3)
jneq Lcmpc5_out
incl %r1
incl %r3
decl %r2
sobgtr %r0,Lcmpc5_loop
Lcmpc5_str2:
tstl %r2
jeql Lcmpc5_out
Lcmpc5_str2loop:
cmpb %r11,(%r3)
jneq Lcmpc5_out
incl %r3
sobgtr %r2,Lcmpc5_str2loop
jbr Lcmpc5_out
Lcmpc5_str1loop:
cmpb (%r1),%r11
jneq Lcmpc5_out
incl %r1
sobgtr %r0,Lcmpc5_str1loop
Lcmpc5_out:
savepsl
return
#define POSITIVE $12
#define NEGATIVE $13
#define NEGATIVEalt $11
.align 1
ALTENTRY(EMaddp4)
toarg(%r9,6) # save register %r9 in arg6 spot
arguw(1,%r11) # (1) source length == %r11
argl(2,%r10) # (2) source address == %r10
arguw(3,%r9) # (3) destination length == %r9
argl(4,%r3) # (4) destination address == %r3
ashl $-1,%r11,%r11
addl2 %r11,%r10 # source address of LSNibble
incl %r11 # source length is in bytes
ashl $-1,%r9,%r9
addl2 %r9,%r3 # %r3 = destination address of LSNibble
incl %r9 # destination length is in bytes
toarg(%r3,5)
extzv $0,$4,(%r3),%r2 # set standard +/- indicators in destination
cmpl %r2,NEGATIVE
jeql L112
cmpl %r2,NEGATIVEalt
jeql L111
insv POSITIVE,$0,$4,(%r3)
jbr L112
L111:
insv NEGATIVE,$0,$4,(%r3)
L112:
extzv $0,$4,(%r10),%r2 # %r2 = standard +/- of source
cmpl %r2,NEGATIVE
jeql L114
cmpl %r2,NEGATIVEalt
jeql L113
movl POSITIVE,%r2
jbr L114
L113:
movl NEGATIVE,%r2
L114:
cmpl %r11,%r9 # if source is longer than destination
jleq L115
movl %r9,%r11 # set source length == destination length
L115:
extzv $4,$4,(%r3),%r9 # %r9 = LSDigit of destination
extzv $4,$4,(%r10),%r1 # %r1 = LSDigit of source
extzv $0,$4,(%r3),%r0
cmpl %r0,%r2 # if signs of operands are not equal
jeql Laddp4_same # do a subtraction
clrl %r2 # %r2 is non-zero if result is non-zero
subl2 %r1,%r9 # %r9 = "addition" of operands high nibble
jbr L119 # jump into addition loop
Laddp4_diff_loop:
decl %r3
extzv $0,$4,(%r3),%r0
addl2 %r0,%r1 # %r1 = carry + next (low) nibble of source
decl %r10
extzv $0,$4,(%r10),%r0
subl2 %r0,%r1 # %r1 -= next (low) nibble of destination
jgeq L121 # if negative result
mnegl $1,%r9 # %r9 == carry = -1
addl2 $10,%r1 # %r1 == result += 10
jbr L122 # else
L121:
clrl %r9 # %r9 == carry = 0
L122:
insv %r1,$0,$4,(%r3) # store result low nibble
bisl2 %r1,%r2
extzv $4,$4,(%r3),%r0
addl2 %r0,%r9 # %r9 = carry + next (high) nibble of source
extzv $4,$4,(%r10),%r0
subl2 %r0,%r9 # %r9 -= next (high) nibble of destination
L119:
jgeq L117 # if negative result
mnegl $1,%r1 # %r1 == carry = -1
addl2 $10,%r9 # %r9 == result += 10
jbr L118 # else
L117:
clrl %r1 # %r1 == carry = 0
L118:
insv %r9,$4,$4,(%r3) # store result high nibble
bisl2 %r9,%r2 # %r2 is non-zero if result is non-zero
decl %r11 # while (--source length)
jneq Laddp4_diff_loop
argl(4,%r10) # %r10 = address of destination MSNibble
jbr Laddp4_diff_carry
Laddp4_diff_carlop:
decl %r3
extzv $0,$4,(%r3),%r0
addl2 %r0,%r1 # %r1 == carry += next (low) nibble
jgeq L127 # if less than zero
movl %r1,%r9 # %r9 == carry (must be -1)
movl $9,%r1 # %r1 == result = 9
jbr L128
L127: # else
clrl %r9 # %r9 == carry = 0
L128:
insv %r1,$0,$4,(%r3) # store result
bisl2 %r1,%r2
extzv $4,$4,(%r3),%r0
addl2 %r0,%r9 # %r9 == carry += next (high) nibble
jgeq L129 # if less than zero
movl %r9,%r1 # %r1 == carry (must be -1)
movl $9,%r9 # %r9 == result = 9
jbr L130
L129:
clrl %r1
L130:
insv %r9,$4,$4,(%r3) # store result
bisl2 %r9,%r2
Laddp4_diff_carry:
cmpl %r3,%r10
jneq Laddp4_diff_carlop
tstl %r1 # if carry out of MSN then fix up result
jeql Laddp4_add_done
argl(5,%r3) # %r3 == address of LSN of destination
extzv $0,$4,(%r3),%r0
cmpl %r0,NEGATIVE # switch sign of result
jneq L132
insv POSITIVE,$0,$4,(%r3)
jbr L133
L132:
insv NEGATIVE,$0,$4,(%r3)
L133:
extzv $4,$4,(%r3),%r0 # normalize result (carry out of MSN into LSN)
subl3 %r0,$10,%r9 # %r9 = 10 - destination LSNibble
jbr L134
L137:
movl $9,%r1
Laddp4_diff_norm:
insv %r9,$4,$4,(%r3)
cmpl %r3,%r10 # while (not at MSNibble)
jeql Laddp4_add_done
decl %r3
extzv $0,$4,(%r3),%r0 # low nibble = (9 + carry) - low nibble
subl2 %r0,%r1
cmpl %r1,$9
jleq L135
clrl %r1
movl $10,%r9
jbr L136
L135:
movl $9,%r9
L136:
insv %r1,$0,$4,(%r3)
extzv $4,$4,(%r3),%r0 # high nibble = (9 + carry) - high nibble
subl2 %r0,%r9
L134:
cmpl %r9,$9
jleq L137
clrl %r9
movl $10,%r1
jbr Laddp4_diff_norm
Laddp4_same: # operands are of the same sign
clrl %r2
addl2 %r1,%r9
jbr L139
Laddp4_same_loop:
decl %r3
extzv $0,$4,(%r3),%r0
addl2 %r0,%r1 # %r1 == carry += next (low) nibble of dest
decl %r10
extzv $0,$4,(%r10),%r0
addl2 %r0,%r1 # %r1 += next (low) nibble of source
cmpl %r1,$9 # if result > 9
jleq L141
movl $1,%r9 # %r9 == carry = 1
subl2 $10,%r1 # %r1 == result -= 10
jbr L142
L141: # else
clrl %r9 # %r9 == carry = 0
L142:
insv %r1,$0,$4,(%r3) # store result
bisl2 %r1,%r2
extzv $4,$4,(%r10),%r0
addl2 %r0,%r9 # ditto for high nibble
extzv $4,$4,(%r3),%r0
addl2 %r0,%r9
L139:
cmpl %r9,$9
jleq L143
movl $1,%r1
subl2 $10,%r9
jbr L144
L143:
clrl %r1
L144:
insv %r9,$4,$4,(%r3)
bisl2 %r9,%r2
sobgtr %r11,Laddp4_same_loop # while (--source length)
argl(4,%r10) # %r10 = destination address of MSNibble
jbr Laddp4_same_carry
Laddp4_same_cloop:
decl %r3
extzv $0,$4,(%r3),%r0 # propagate carry up to MSNibble of destination
addl2 %r0,%r1
cmpl %r1,$10
jneq L147
movl $1,%r9
clrl %r1
jbr L148
L147:
clrl %r9
L148:
insv %r1,$0,$4,(%r3)
bisl2 %r1,%r2
extzv $4,$4,(%r3),%r0
addl2 %r0,%r9
cmpl %r9,$10
jneq L149
movl $1,%r1
clrl %r9
jbr L150
L149:
clrl %r1
L150:
insv %r9,$4,$4,(%r3)
bisl2 %r9,%r2
Laddp4_same_carry:
cmpl %r3,%r10
jneq Laddp4_same_cloop
Laddp4_add_done:
argl(5,%r3) # %r3 = destination address of LSNibble
tstl %r2 # if zero result
jneq L151
savepsl # remember that for condition codes
insv POSITIVE,$0,$4,(%r3) # make sure sign of result is positive
jbr Laddp4_out
L151: # else
extzv $0,$4,(%r3),%r0
cmpl %r0,NEGATIVE # if result is negative
jneq Laddp4_out
mnegl %r2,%r2 # remember THAT in Cond Codes
savepsl
Laddp4_out:
argl(4,%r3)
argl(2,%r1)
clrl %r0
clrl %r2
argl(6,%r9) # restore %r9 from stack
return
.align 1
ALTENTRY(EMmovp)
arguw(1,%r11) # (1) string length == %r11
argl(2,%r10) # (1) source address == %r10
argl(3,%r3) # (1) destination address == %r3
clrl %r2 # %r2 == non-zero if source is non-zero
ashl $-1,%r11,%r11 # length is number of bytes, not nibbles
jeql Lmovp_zlen
Lmovp_copy:
bisb2 (%r10),%r2 # keep track of non-zero source
movb (%r10)+,(%r3)+ # move two nibbles
sobgtr %r11,Lmovp_copy # loop for length of source
Lmovp_zlen:
extzv $4,$4,(%r10),%r0 # look at least significant nibble
bisl2 %r0,%r2
extzv $0,$4,(%r10),%r0 # check sign nibble
cmpl %r0,NEGATIVEalt
jeql Lmovp_neg
cmpl %r0,NEGATIVE
jneq Lmovp_pos
Lmovp_neg: # source was negative
mnegl %r2,%r2
Lmovp_pos:
tstl %r2 # set condition codes
savepsl
jeql Lmovp_zero
movb (%r10),(%r3) # move last byte if non-zero result
jbr Lmovp_out
Lmovp_zero:
movb POSITIVE,(%r3) # otherwise, make result zero and positive
Lmovp_out:
clrl %r0
argl(2,%r1)
clrl %r2
argl(3,%r3)
return
#define SIGNIFBIT $0
#define setsignif bisl2 $1,%r4
#define clsignif bicl2 $1,%r4
#define OVERFLOWBIT $1
#define setoverflow bisl2 $2,%r4
#define cloverflow bicl2 $2,%r4
#define ZEROBIT $2
#define setzero bisl2 $4,%r4
#define clzero bicl2 $4,%r4
#define NEGATIVEBIT $3
#define setnegative bisl2 $8,%r4
#define clnegative bicl2 $8,%r4
#define putfill movb arg5,(%r5)+
#define setfill(reg) movb reg,arg5
#define putsign movb arg6,(%r5)+
#define setsign(reg) movb reg,arg6
.align 1
ALTENTRY(EMeditpc)
arguw(1,%r11) # (1) source length == %r11
argl(2,%r10) # (2) source address == %r10
argl(3,%r3) # (3) pattern address == %r3
argl(4,%r5) # (4) destination address == %r5
setfill($32) # fill character is ' '
setsign($32) # sign character is ' '
clrl %r4 # clear flags
ashl $-1,%r11,%r11 # source length / 2
addl3 %r11,%r10,%r2
extzv $4,$4,(%r2),%r1 # %r1 == least significant nibble of source
L169:
cmpl %r2,%r10
jeql L170
tstb -(%r2) # loop over source packed decimal number
jeql L169
incl %r1 # %r1 is non-zero if source is non-zero
L170:
addl3 %r11,%r10,%r2
tstl %r1
jeql L172 # source is zero - set flags
extzv $0,$4,(%r2),%r11
cmpl %r11,NEGATIVEalt
jeql L9998 # source is negative - set sign and flags
cmpl %r11,NEGATIVE
jneq L175
L9998:
setnegative
setsign($45) # sign character is '-'
jbr L175
L172:
setzero
L175:
arguw(1,%r2) # (1) source length == %r2
Ledit_case:
movzbl (%r3)+,%r11 # get next edit command (pattern)
cmpl %r11,$128
jlss L180
extzv $0,$4,%r11,%r1 # command has a "count" arg - into %r1
ashl $-4,%r11,%r11 # and shift over
L180:
jbc $6,%r11,L181 # "shift" those commands > 64 to 16 and up
subl2 $48,%r11
L181:
caseb %r11,$0,$0x18 # "do" the command
# %r11 is available for use, %r1 has "count" in it
Lcaseb_label:
.word Le_end - Lcaseb_label # 00
.word Le_end_float - Lcaseb_label # 01
.word Le_clear_signif - Lcaseb_label # 02
.word Le_set_signif - Lcaseb_label # 03
.word Le_store_sign - Lcaseb_label # 04
.word Le_end - Lcaseb_label # 05
.word Le_end - Lcaseb_label # 06
.word Le_end - Lcaseb_label # 07
.word Le_fill - Lcaseb_label # 80
.word Le_move - Lcaseb_label # 90
.word Le_float - Lcaseb_label # a0
.word Le_end - Lcaseb_label # b0
.word Le_end - Lcaseb_label # c0
.word Le_end - Lcaseb_label # d0
.word Le_end - Lcaseb_label # e0
.word Le_end - Lcaseb_label # f0
.word Le_load_fill - Lcaseb_label # 40
.word Le_load_sign - Lcaseb_label # 41
.word Le_load_plus - Lcaseb_label # 42
.word Le_load_minus - Lcaseb_label # 43
.word Le_insert - Lcaseb_label # 44
.word Le_blank_zero - Lcaseb_label # 45
.word Le_replace_sign - Lcaseb_label # 46
.word Le_adjust_input - Lcaseb_label # 47
Le_end:
arguw(1,%r0)
argl(2,%r1)
clrl %r2
decl %r3
setpsl(%r4)
clrl %r4
return
Le_end_float:
jbs SIGNIFBIT,%r4,Ledit_case # if significance not set
putsign # drop in the sign
Le_set_signif:
setsignif
jbr Ledit_case
Le_clear_signif:
clsignif
jbr Ledit_case
Le_store_sign:
putsign
jbr Ledit_case
Le_load_fill:
setfill((%r3)+)
jbr Ledit_case
Le_load_plus:
jbs NEGATIVEBIT,%r4,Lpattern_inc # if non-negative
Le_load_sign:
setsign((%r3)+)
jbr Ledit_case
Le_load_minus:
jbs NEGATIVEBIT,%r4,Le_load_sign # if negative load the sign
incl %r3 # else increment pattern
jbr Ledit_case
Le_insert:
jbc SIGNIFBIT,%r4,L196 # if significance set, put next byte
movb (%r3)+,(%r5)+
jbr Ledit_case
L196: # else put in fill character
putfill
Le_replace_sign: # we dont do anything with
Lpattern_inc: # replace sign cause we dont
incl %r3 # get negative zero
jbr Ledit_case
Le_blank_zero:
jbc ZEROBIT,%r4,Lpattern_inc # if zero
movzbl (%r3)+,%r11 # next byte is a count
jeql Ledit_case
subl2 %r11,%r5 # to back up over output and replace
L200:
putfill # with fill character
sobgtr %r11,L200
jbr Ledit_case
Le_adjust_input:
movzbl (%r3)+,%r0 # get count of nibbles from pattern
subl3 %r2,%r0,%r11
jgeq Ledit_case # if length of source is > this number
L204: # discard digits in source
jlbc %r2,L206 # use low bit of length to choose nibble
bitb $0xf0,(%r10) # high nibble
jeql L208
setsignif # set significance and overflow if
setoverflow # wasted digit is non-zero
jbr L208
L206:
bitb $0xf,(%r10) # low nibble
jeql L209
setsignif
setoverflow
L209:
incl %r10 # increment to next byte
L208:
decl %r2 # decrement source length
incl %r11 # continue till were out of excess
jlss L204
jbr Ledit_case
Le_fill:
tstl %r1 # put (count in %r1) fill characters
jeql Ledit_case
Le_fill_loop:
putfill
sobgtr %r1,Le_fill_loop
jbr Ledit_case
Le_move:
tstl %r1 # move (count in %r1) characters
jeql Ledit_case # from source to destination
L214:
jlbc %r2,L215 # read a nibble
extzv $4,$4,(%r10),%r11
jbr L216
L215:
extzv $0,$4,(%r10),%r11
incl %r10
L216:
decl %r2 # source length CAN go negative here...
tstl %r11
jeql L218 # if non-zero
setsignif # set significance
L218:
jbc SIGNIFBIT,%r4,L219 # if significance set
addb3 $48,%r11,(%r5)+ # put 0 + digit into destination
jbr L220
L219: # else put fill character
putfill
L220:
sobgtr %r1,L214
jbr Ledit_case
Le_float: # move with floating sign character
tstl %r1
jeql Ledit_case
L221:
jlbc %r2,L222
extzv $4,$4,(%r10),%r11
jbr L223
L222:
extzv $0,$4,(%r10),%r11
incl %r10
L223:
decl %r2 # source length CAN go negative here...
tstl %r11
jeql L225
jbs SIGNIFBIT,%r4,L226
putsign
L226:
setsignif
L225:
jbc SIGNIFBIT,%r4,L227
addb3 $48,%r11,(%r5)+
jbr L228
L227:
putfill
L228:
sobgtr %r1,L221
jbr Ledit_case
.align 1
ALTENTRY(EMashp)
argb(1,%r11) # (1) scale (number to shift) == %r11
arguw(2,%r10) # (2) source length == %r10
argl(3,%r1) # (3) source address == %r1
argub(4,%r2) # (4) rounding factor == %r2
arguw(5,%r3) # (5) destination length == %r3
toarg(%r6,3)
argl(6,%r6) # (6) destination address == %r6
ashl $-1,%r3,%r0 # destination length is number of bytes
addl2 %r0,%r6 # destination address == least sig nibble
toarg(%r6,1) # save in arg1 spot for later
ashl $-1,%r10,%r0
addl2 %r0,%r1 # source address == least sig nibble
extzv $0,$4,(%r1),%r0 # determine sign of source
cmpl %r0,NEGATIVEalt
jeql Lashp_neg
cmpl %r0,NEGATIVE
jeql Lashp_neg
movb POSITIVE,(%r6)
jbr L245
Lashp_neg:
movb NEGATIVE,(%r6)
L245:
clrl arg2 # arg2 is 1 if dstlen is even, 0 if odd
blbs %r3,L246
incl arg2
bisl2 $1,%r3 # %r3<0> counts digits going into destination
L246: # and is flip-flop for which nibble to
tstl %r11 # write in destination (1 = high, 0 = low)
jgeq Lashp_left # (it must start out odd)
addl2 %r11,%r10 # scale is negative (right shift)
jgeq Lashp_right
clrl %r10 # test for shifting whole number out
jbr Lashp_setround
Lashp_right:
divl3 $2,%r11,%r0
addl2 %r0,%r1 # source address == MSNibble to be shifted off
jlbc %r11,L249
extzv $4,$4,(%r1),%r0
addl2 %r0,%r2 # round = last nibble to be shifted off + round
jbr Lashp_setround
L249:
extzv $0,$4,(%r1),%r0
addl2 %r0,%r2 # round = last nibble to be shifted off + round
Lashp_setround: # %r11<0> now is flip-flop for which nibble to
incl %r11 # read from source (1 == high, 0 == low)
cmpl %r2,$9 # set rounding factor to one if nibble shifted
jleq Lashp_noround # off + round argument was 10 or greater
movl $1,%r2
jbr Lashp_shift
Lashp_zloop:
jlbs %r3,L257 # dont need to clear high nibble twice
clrb -(%r6) # clear low (and high) nib of next byte in dest
L257:
sobgtr %r3,L258 # move to next nibble in destination, but
incl %r3 # dont go beyond the end.
L258:
decl %r11
Lashp_left: # while scale is positive
jneq Lashp_zloop
incl %r11 # %r11<0> is flip-plop ... (incl sets it to one)
Lashp_noround:
clrl %r2 # no more rounding
Lashp_shift:
clrl arg4 # arg4 will be used for result condition codes
tstl %r10
jeql Lashp_round
Lashp_shloop:
jlbc %r11,L260
extzv $4,$4,(%r1),%r0
jbr L261
L260:
decl %r1
extzv $0,$4,(%r1),%r0
L261:
incl %r11 # flip the source nibble flip/flop
addl2 %r0,%r2 # round += next nibble
cmpl %r2,$10 # if round == 10
jneq L262
clrl arg5 # then result = 0 and round = 1
movl $1,%r2
jbr L263
L262: # else
movl %r2,arg5 # store result and round = 0
clrl %r2
L263:
bisl2 arg5,arg4 # remember if result was nonzero in arg4
decl %r3 # move to next nibble early to check
cmpl %r3,arg2 # if weve moved passed destination limits
jgeq Lashp_noovfl # test the result for possible overflow
movl arg2,%r3 # ignore zero nibbles
tstl arg5 # if the nibble was non-zero, overflow
jeql L265
jbr Lashp_overfl
Lashp_noovfl: # else
jlbs %r3,L264
insv arg5,$4,$4,(%r6) # put the result into destination (high or low)
jbr L265
L264:
movb arg5,-(%r6)
L265:
sobgtr %r10,Lashp_shloop # loop for length of source
Lashp_round:
tstl %r2 # take care of round out of high nibble
jeql Lashp_zeroround
decl %r3
cmpl %r3,arg2 # if weve moved passed destination limits
jlss Lashp_overfl # then overflow
jlbs %r3,L266
insv arg5,$4,$4,(%r6) # put the round into destination (high or low)
jbr Lashp_zeroround
L266:
movb arg5,-(%r6)
Lashp_zeroround:
argl(1,%r10) # %r10 = address of destination LSNibble
argl(6,%r3) # %r3 = address of destination MSNibble
movl arg4,%r11 # %r11 = non-zero if destination == non-zero
savepsl
jbr L267
Lashp_zerofill:
clrb -(%r6) # fill up MSNs of destination with zeros
L267:
cmpl %r3,%r6
jneq Lashp_zerofill
extzv $0,$4,(%r10),%r0 # test for negative result
cmpl %r0,NEGATIVE
jneq Lashp_out
mnegl %r11,%r11
savepsl
jneq Lashp_out # turn -0 into 0
insv POSITIVE,$0,$4,(%r10)
Lashp_out:
clrl %r0
argl(3,%r6) # restore %r6 from stack
return
Lashp_overfl: # do overflow
clrl %r2
overflowpsl
jbr Lashp_out
.align 1
ALTENTRY(EMcvtlp)
arguw(2,%r10) # (2) destination length == %r10
argl(3,%r3) # (3) destination address == %r3
ashl $-1,%r10,%r10
addl2 %r10,%r3 # destination address points to Least Sig byte
incl %r10 # length is # of bytes, not nibbles
argl(1,%r11) # (1) source == %r11
savepsl
jgeq Lcvtlp_pos
movb NEGATIVE,(%r3) # source is negative
divl3 $10,%r11,%r0
mull3 $10,%r0,%r1
subl3 %r11,%r1,%r2 # %r2 = source mod 10
mnegl %r0,%r11 # source = -(source / 10)
jbr Lcvtlp_cvt
Lcvtlp_pos:
movb POSITIVE,(%r3) # source is non-negative
divl3 $10,%r11,%r0
mull3 $10,%r0,%r1
subl3 %r1,%r11,%r2 # %r2 = source mod 10
movl %r0,%r11 # source = source / 10
Lcvtlp_cvt:
insv %r2,$4,$4,(%r3) # store least significant digit
tstl %r11
jeql Lcvtlp_zloop
Lcvtlp_loop: # while source is non-zero
decl %r10 # and for length of destination ...
jeql Lcvtlp_over
divl3 $10,%r11,%r1 # %r1 = source / 10
mull3 $10,%r1,%r0
subl2 %r0,%r11 # source = source mod 10
movb %r11,-(%r3) # store low "nibble" in next significant byte
divl3 $10,%r1,%r11 # source = %r1 / 10
mull3 $10,%r11,%r0
subl2 %r0,%r1 # %r1 = source mod 10
insv %r1,$4,$4,(%r3) # store high nibble
tstl %r11
jneq Lcvtlp_loop # quit if source becomes zero
Lcvtlp_zloop: # fill any remaining bytes with zeros
decl %r10
jeql Lcvtlp_out
clrb -(%r3)
jbr Lcvtlp_zloop
Lcvtlp_over:
overflowpsl
Lcvtlp_out:
clrl %r1 # %r0 is already zero
clrl %r2
return
.align 1
ALTENTRY(EMcvtpl)
arguw(1,%r11) # (1) source length == %r11
argl(2,%r10) # (2) source address == %r10
clrl %r3 # %r3 == destination
movl %r10,%r1 # %r1 set up now for return
ashl $-1,%r11,%r11 # source length is number of bytes
jeql Lcvtpl_zero
Lcvtpl_loop: # for source length
mull2 $10,%r3 # destination *= 10
extzv $4,$4,(%r10),%r0
addl2 %r0,%r3 # destination += high nibble
mull2 $10,%r3 # destination *= 10
extzv $0,$4,(%r10),%r0
addl2 %r0,%r3 # destination += low nibble
incl %r10
sobgtr %r11,Lcvtpl_loop
Lcvtpl_zero: # least significant byte
mull2 $10,%r3
extzv $4,$4,(%r10),%r0
addl2 %r0,%r3 # dest = 10 * dest + high nibble
savepsl
extzv $0,$4,(%r10),%r2 # test sign nibble
cmpl %r2,NEGATIVE
jeql Lcvtpl_neg
cmpl %r2,NEGATIVEalt
jneq Lcvtpl_out
Lcvtpl_neg: # source was negative - negate destination
mnegl %r3,%r3
savepsl
Lcvtpl_out:
toarg(%r3,3)
clrl %r0
clrl %r2
clrl %r3
return
.align 1
ALTENTRY(EMcvtps)
return
.align 1
ALTENTRY(EMcvtsp)
return
.align 1
ALTENTRY(EMaddp6)
return
.align 1
ALTENTRY(EMsubp4)
return
.align 1
ALTENTRY(EMsubp6)
return
.align 1
ALTENTRY(EMcvtpt)
return
.align 1
ALTENTRY(EMmulp)
return
.align 1
ALTENTRY(EMcvttp)
return
.align 1
ALTENTRY(EMdivp)
return
.align 1
ALTENTRY(EMcmpp3)
return
.align 1
ALTENTRY(EMcmpp4)
return
#ifdef notdef
#define EMUTABLE 0x43
#define NOEMULATE .long noemulate
#define EMULATE(a) .long _EMa
.globl _C_LABEL(emJUMPtable)
_C_LABEL(emJUMPtable)
EMULATE(ashp); EMULATE(cvtlp); NOEMULATE; NOEMULATE
NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
EMULATE(cvtps); EMULATE(cvtsp); NOEMULATE; EMULATE(crc)
NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
EMULATE(addp4); EMULATE(addp6); EMULATE(subp4); EMULATE(subp6)
EMULATE(cvtpt); EMULATE(mulp); EMULATE(cvttp); EMULATE(divp)
NOEMULATE; EMULATE(cmpc3); EMULATE(scanc); EMULATE(spanc)
NOEMULATE; EMULATE(cmpc5); EMULATE(movtc); EMULATE(movtuc)
NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE
EMULATE(movp); EMULATE(cmpp3); EMULATE(cvtpl); EMULATE(cmpp4)
EMULATE(editpc); EMULATE(matchc); EMULATE(locc); EMULATE(skpc)
SCBVEC(emulate):
movl %r11,32(%sp) # save register %r11 in unused operand
movl %r10,36(%sp) # save register %r10 in unused operand
cvtbl (%sp),%r10 # get opcode
addl2 $8,%r10 # shift negative opcodes
subl3 %r10,$EMUTABLE,%r11 # forget it if opcode is out of range
bcs noemulate
movl _C_LABEL(emJUMPtable)[%r10],%r10
jsb (%r10) # routines put return values into regs 0-5
movl 32(%sp),%r11 # restore register %r11
movl 36(%sp),%r10 # restore register %r10
insv (%sp),$0,$4,44(%sp) # and condition codes in Opcode spot
addl2 $40,%sp # adjust stack for return
rei
noemulate:
addl2 $48,%sp # adjust stack for
.word 0xffff # "reserved instruction fault"
SCBVEC(emulateFPD):
.word 0xffff # "reserved instruction fault"
#endif