📄 vaxdeciml.s
字号:
.byte 40 , 40 , 40 , 40 , 40 , 40 # illegal decimal digits .byte 50 , 51 , 52 , 53 , 54 # index ^x50 .byte 55 , 56 , 57 , 58 , 59 # to ^x59 .byte 50 , 50 , 50 , 50 , 50 , 50 # illegal decimal digits .byte 60 , 61 , 62 , 63 , 64 # index ^x60 .byte 65 , 66 , 67 , 68 , 69 # to ^x69 .byte 60 , 60 , 60 , 60 , 60 , 60 # illegal decimal digits .byte 70 , 71 , 72 , 73 , 74 # index ^x70 .byte 75 , 76 , 77 , 78 , 79 # to ^x79 .byte 70 , 70 , 70 , 70 , 70 , 70 # illegal decimal digits .byte 80 , 81 , 82 , 83 , 84 # index ^x80 .byte 85 , 86 , 87 , 88 , 89 # to ^x89 .byte 80 , 80 , 80 , 80 , 80 , 80 # illegal decimal digits .byte 90 , 91 , 92 , 93 , 94 # index ^x90 .byte 95 , 96 , 97 , 98 , 99 # to ^x99 .byte 90 , 90 , 90 , 90 , 90 , 90 # illegal decimal digits #+ # binary number to decimal equivalent # # the following table is used to do a fast conversion from a binary number # stored in a byte to its decimal representation. the table structure assumes # that the number lies in the range 0 to 99. numbers that lie outside this # range produce unpredictable resutls. #- # decimal equivalents binary # ------------------- ------binary_to_packed_table: .byte 0x00 , 0x01 , 0x02 , 0x03 , 0x04 # 0 through 9 .byte 0x05 , 0x06 , 0x07 , 0x08 , 0x09 # .byte 0x10 , 0x11 , 0x12 , 0x13 , 0x14 # 10 through 19 .byte 0x15 , 0x16 , 0x17 , 0x18 , 0x19 # .byte 0x20 , 0x21 , 0x22 , 0x23 , 0x24 # 20 through 29 .byte 0x25 , 0x26 , 0x27 , 0x28 , 0x29 # .byte 0x30 , 0x31 , 0x32 , 0x33 , 0x34 # 30 through 39 .byte 0x35 , 0x36 , 0x37 , 0x38 , 0x39 # .byte 0x40 , 0x41 , 0x42 , 0x43 , 0x44 # 40 through 49 .byte 0x45 , 0x46 , 0x47 , 0x48 , 0x49 # .byte 0x50 , 0x51 , 0x52 , 0x53 , 0x54 # 50 through 59 .byte 0x55 , 0x56 , 0x57 , 0x58 , 0x59 # .byte 0x60 , 0x61 , 0x62 , 0x63 , 0x64 # 60 through 69 .byte 0x65 , 0x66 , 0x67 , 0x68 , 0x69 # .byte 0x70 , 0x71 , 0x72 , 0x73 , 0x74 # 70 through 79 .byte 0x75 , 0x76 , 0x77 , 0x78 , 0x79 # .byte 0x80 , 0x81 , 0x82 , 0x83 , 0x84 # 80 through 89 .byte 0x85 , 0x86 , 0x87 , 0x88 , 0x89 # .byte 0x90 , 0x91 , 0x92 , 0x93 , 0x94 # 90 through 99 .byte 0x95 , 0x96 , 0x97 , 0x98 , 0x99 # #+ # functional description: # # in 4 operand format, the addend string specified by the addend length # and addend address operands is added to the sum string specified by the # sum length and sum address operands and the sum string is replaced by # the result. # # input parameters: # # r0 - addlen.rw number of digits in addend string # r1 - addaddr.ab address of addend decimal string # r2 - sumlen.rw number of digits in sum string # r3 - sumaddr.ab address of sum decimal string # # output parameters: # # r0 = 0 # r1 = address of the byte containing the most significant digit of # the addend string # r2 = 0 # r3 = address of the byte containing the most significant digit of # the string containing the sum # # condition codes: # # n <- sum string lss 0 # z <- sum string eql 0 # v <- decimal overflow # c <- 0 # # register usage: # # this routine uses all of the general registers. the condition codes # are recorded in r11 as the routine executes. #-vax$addp4: pushr $0xfff # save registers 0,1,2,3,4,5,6,7,8,9,10,11 clrl r9 # this is addition2: movq r2,r4 # let r4 and r5 describe output string #+ # all four routines converge at this point and execute common initialization # code until a later decision is made to do addition or subtraction. # # r4 - number of digits in destination string # r5 - address of destination string # # r9 - indicates whether operation is addition or subtraction # 0 => addition # 1 => subtraction #-3: movpsl r11 # get initial psl insv $psl$m_z,$0,$4,r11 # set z-bit, clear the rest movab decimal_pack,r10 # store address of handler/* No need to check operand size because the routines that call us * all have defined operand sizes. * * roprand_check r2 # insure that r2 is lequ 31 */ bsbw strip_zeros_r2_r3 # strip high order zeros from r2/r3 string/* roprand_check r0 # insure that r0 is lequ 31 */ bsbw strip_zeros_r0_r1 # strip high order zeros from r0/r1 string # rather than totally confuse the already complicated logic dealing with # different length strings in the add or subtract loop, we will put the # result into an intermediate buffer on the stack. this buffer will be long # enough to handle the worst case so that the addition loop need only concern # itself with the lengths of the two input loops. the required length is 17 # bytes, to handle an addition with a carry out of the most significant byte. # we will allocate 20 bytes to maintain whatever alignment the stack has. clrq -(sp) # set aside space for output string clrq -(sp) # worst case string needs 16 bytes clrl -(sp) # add slack for a carry extzv $1,$4,r4,r8 # get byte count of destination string addl3 r8,r5,-(sp) # save high address end of destination movab 24(sp),r5 # point r5 one byte beyond buffer # the number of minus signs will determine whether the real operation that we # perform is addition or subtraction. that is, two plus signs or two minus # signs will both result in addition, while a plus sign and a minus sign will # result in subtraction. the addition and subtraction routines have their own # methods for determining the correct sign of the result. # # for the purpose of counting minus signs, we treat subtraction as the # addition of the negative of the input operand. that is, subtraction of a # positive quantity causes the sign to be remembered as minus and counted as # a minus sign while subtraction of a minus quantity stores a plus sign and # counts nothing. # # on input to this code sequence, r9 distinguished addition from subtraction. # on output, it contains either 0, 1, or 2, indicating the total number of # minus signs, real or implied, that we counted. extzv $1,$4,r0,r6 # get byte count for first input string addl2 r6,r1 # point r1 to byte containing sign bicb3 $0xf0,(r1),r6 # r6 contains the sign "digit"/* * No need to check this because we only need addition * * jlbs r9,35$ # use second case if subtraction */ # this case statement is used for addition caseb r6,$10,$15-10L1: # dispatch on sign digit .word 5f-L1 # 10 => sign is "+" .word 4f-L1 # 11 => sign is "-" .word 5f-L1 # 12 => sign is "+" .word 4f-L1 # 13 => sign is "-" .word 5f-L1 # 14 => sign is "+" .word 5f-L1 # 15 => sign is "+"4: movl $1,r9 # count a minus sign movzbl $13,r6 # the preferred minus sign is 13 jbr L60 # now check second input sign5: clrl r9 # no real minus signs so far movzbl $12,r6 # the preferred minus sign is 12L60: extzv $1,$4,r2,r7 # get byte count for second input string addl2 r7,r3 # point r3 to byte containing sign bicb3 $0xf0,(r3),r7 # r7 contains the sign "digit" caseb r7,$10,$15-10L2: # dispatch .word 8f-L2 # 10 => sign is "+" .word 7f-L2 # 11 => sign is "-" .word 8f-L2 # 12 => sign is "+" .word 7f-L2 # 13 => sign is "-" .word 8f-L2 # 14 => sign is "+" .word 8f-L2 # 15 => sign is "+"7: incl r9 # remember that sign was minus movzbl $13,r7 # the preferred minus sign is 13 jbr L90 # now check second input sign8: movzbl $12,r7 # the preferred minus sign is 12L90: jlbc r9,add_packed # even parity indicates addition/* * Don't need this because we don't do subtraction * * jbr subtract_packed # odd parity calls for subtraction */ #+ # functional description: # # this routine adds two packed decimal strings whose descriptors # are passed as input parameters and places their sum into another # (perhaps identical) packed decimal string. # # at the present time, the result is placed into a 16-byte storage # area while the sum is being evaluated. this drastically reduces # the number of different cases that must be dealt with as each # pair of bytes in the two input strings is added. # # the signs of the two input strings have already been dealt with # so this routine performs addition in all cases, even if the original # entry was at subp4 or subp6. the cases that arrive in this routine # are as follows. # # r2/r3 r0/r1 result # +---------------+---------------+---------------+ # | | | | # r2/r3 + r0/r1 | plus | plus | plus | # | | | | # +---------------+---------------+---------------+ # | | | | # r2/r3 + r0/r1 | minus | minus | minus | # | | | | # +---------------+---------------+---------------+ # | | | | # r2/r3 - r0/r1 | minus | plus | minus | # | | | | # +---------------+---------------+---------------+ # | | | | # r2/r3 - r0/r1 | plus | minus | plus | # | | | | # +---------------+---------------+---------------+ # # note that the correct choice of sign in all four cases is the sign # of the second input string, the one described by r2 and r3. # # input parameters: # # r0<4:0> - number of digits in first input decimal string # r1 - address of least significant digit of first input # decimal string (the byte containing the sign) # # r2<4:0> - number of digits in second input decimal string # r3 - address of least significant digit of second input # decimal string (the byte containing the sign) # # r4<4:0> - number of digits in output decimal string # r5 - address of one byte beyond least significant digit of # intermediate string stored on the stack # # r6<3:0> - sign of first input string in preferred form # r7<3:0> - sign of second input string in preferred form # # r11 - saved psl (z-bit is set, other condition codes are clear) # # (sp) - saved r5, address of least significant digit of ultimate # destination string. # 4(sp) - beginning of 20-byte buffer to hold intermediate result # # output parameters: # # the particular input operation (addpx or subpx) is completed in # this routine. see the routine headers for the four routines that # request addition or subtraction for a list of output parameters # from this routine. #-add_packed: movb r7,r9 # use sign of second string for output jlbc r9,1f # check if sign is negative bisb2 $psl$m_n,r11 # ... so the saved n-bit can be set1: bicb3 $0x0f,(r1),r6 # get least significant digit to r6 bicb3 $0x0f,(r3),r7 # get least significant digit to r7 clrl r8 # start the add with carry off bsbw add_packed_byte_r6_r7 # add the two low order digits # the following set of instructions computes the number of bytes in the two # strings and, if necessary, performs a switch so that r0 and r1 always # describe the shorter of the two strings. extzv $1,$4,r0,r0 # convert digit count to byte count extzv $1,$4,r2,r2 # do it for both strings cmpl r0,r2 # we want to compare the byte counts blequ 2f # skip the swap if we're already correct movq r0,r6 # save the longer movq r2,r0 # store the shorter on r0 and r1 movq r6,r2 # ... and store the longer in r2 and r32: subl2 r0,r2 # make r2 a difference (r2 gequ 0) # r0 now contains the number of bytes remaining in the shorter string. # r2 contains the difference in bytes between the two input strings. tstl r0 # does shorter string have any room? beql 4f # skip loop if no room at all3: bsbw add_packed_byte_string # add the next two bytes together sobgtr r0,3b # check for end of loop4: tstl r2 # does longer string have any room? beql 7f # skip next loops if all done5: jlbc r8,6f # life is simple if carry clear/* note that r6 is a loop invariant here and can be removed from the loop if * we carefully document this assumption in the per-byte addition routine. the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -