📄 vaxarith.s
字号:
Lmulp_at_sp: movzbl -(r9),r1 # next digit pair to r1 movzbl decimal$packed_to_binary_table[r1],r6 # convert digits to binary beql 6f # skip the work if zero movq (sp),r4 # input array descriptor to r4/r5 bsbw extend_string_multiply # do the work6: sobgtr r8,5b # any more multiplier digits? addl2 $8,sp # discard saved long string descriptor7: movl (sp),sp # remove input array from stack # at this point, the product string is located in a 32-longword array on # the top of the stack. each longword corresponds to a pair of digits in # the output string. as digits are removed from the stack, they are checked # for nonzero to obtain the correct setting of the z-bit. after the output # string has been filled, the remainder of the product string is removed from # the stack. if a nonzero result is detected at this stage, the v-bit is set. movl $32,r9 # set up array counter # movq < <32*4> + - # skip over 32-longword array # <2*4> + - # and saved string descriptor # <4*4> >(sp),r4 # to retrieve original r4 and r5 movq ( (32*4) + (2*4) + (4*4) )(sp),r4 # #+ # the code for vax$mulp and vax$divp merges at this point. the result is stored # in an array of longwords at the top of the stack. the size of this array is # stored in r9. the original r4 and r5 heve been retrieved from the stack. # # input parameters: # # r4 - contains byte count of destination string in r4 <1:4> # r5 - address of most significant digit of destination string # r9 - count of longwords in result array on stack # # contents of result array # # implicit input: # # signs of two input factors (multiplier and multiplicand or # divisor and dividend) #-multiply_divide_exit: movpsl r11 # get current psl insv $psl$m_z,$0,$4,r11 # clear all codes except z-bit # establish_handler - # store address of access # arith_accvio # violation handler again movab arith_accvio,r10 extzv $1,$4,r4,r3 # excess byte count to r3 beql L125 # skip to single digit code addl3 r3,r5,r7 # remember address of sign byte addl3 $1,r7,r5 # point r5 beyond end of product string8: movl (sp)+,r1 # remove next value from stack beql 9f # do not clear z-bit if zero bicb2 $psl$m_z,r11 # clear z-bit # mark_point mulp_divp_r9 .text 2 .set table_size,table_size + 1 .word Lmulp_divp_r9 - module_base .text 3 .word mulp_divp_r9 - module_base .textLmulp_divp_r9:9: movb decimal$binary_to_packed_table[r1],-(r5) # store converted sum byte decl r9 # one less element on the stack bleq L116 # exit loop if result array exhausted sobgtr r3,8b # keep going?L200: blbc r4,L220 # different for even digit count # the output string consists of an odd number of digits. a complete digit # pair can be stored in the most significant (lowest addressed) byte of # the product string. movl (sp)+,r1 # remove next value from stack beql L210 # do not clear z-bit if zero bicb2 $psl$m_z,r11 # clear z-bit # mark_point mulp_divp_r9_a .text 2 .set table_size,table_size + 1 .word Lmulp_divp_r9_a - module_base .text 3 .word mulp_divp_r9 - module_base .textLmulp_divp_r9_a:L210: movb decimal$binary_to_packed_table[r1],-(r5) # store converted sum byte decl r9 # one less element on the stack bleq L116 # exit loop if result array exhausted brb L140 # perform overflow check # this loop executes if the result array has fewer elements than the output # string. the remaining bytes in the output string are filled with zeros. # there is no need for an overflow check. # mark_point mulp_divp_8 .text 2 .set table_size,table_size + 1 .word Lmulp_divp_8 - module_base .text 3 .word mulp_divp_8 - module_base .textLmulp_divp_8:L114: clrb -(r5) # store another zero byteL116: sobgeq r3,L114 # any more room in output string brb L150 # determine sign of result # this code path is used in the case where the output digit count is 0 or 1. # r5 must be advanced L125: movl r5,r7 # remember address of output sign byte incl r5 # advance r5 so common code can be used brb L200 # join common code path # the output string consists of an even number of digits. only the low order # nibble is stored in the most significant (lowest addresses) byte. a zero is # stored in the high order nibble. if the high order digit would have been # nonzero, the v-bit is set and the overflow check is bypassed because there # are faster ways to clean the stack if we do not have to check for nonzero # at the same time.L220: movl (sp)+,r1 # remove next value from stack movb decimal$binary_to_packed_table[r1],r1 # obtain converted sum byte # mark_point mulp_divp_r9_c .text 2 .set table_size,table_size + 1 .word Lmulp_divp_r9_c - module_base .text 3 .word mulp_divp_r9 - module_base .textLmulp_divp_r9_c: bicb3 $0x0f0,r1,-(r5) # store byte, clearing high order nibble beql L130 # do not clear z-bit if zero bicb2 $psl$m_z,r11 # clear z-bitL130: bitb $0x0f0,r1 # is high order nibble nonzero? bneq L133 # yes, go set overflow bit decl r9 # one less element on the stack bleq L116 # exit loop if result array exhausted brb L140 # check rest of result array for nonzero # if we detect overflow, we need to adjust r9 to reflect the nonzero longword # removed from the stack before we enter the next code block that sets the # v-bit and cleans off the stack based on the contents of r9. L133: decl r9 # one more longword removed from stack # a nonzero digit has been discovered in a position that cannot be stored in # the output string. set the v-bit, remove the rest of the product array from # the stack, and join the exit processing in the code that determines the sign # of the product.L135: bisb2 $psl$m_v,r11 # set the overflow bit moval (sp)[r9],sp # clean off remaining product string brb L150 # go to code that determines the sign # the remainder of the product array must be removed from the stack. a nonzero # result causes the v-bit to be set and the rest of the loop to be skipped. # note that there is always a nonzero loop count remaining at this point.L140: tstl (sp)+ # is next longword zero? bneq L133 # no, leave loop sobgtr r9,L140 # the final product string has been stored and the v- and z-bits have their # correct settings. the sign of the product must be determined from the # signs of the two input strings. opposite signs produce a negative product. # same signs (in any representation) produce a plus sign in the output string.L150: addl2 $8,sp # discard saved string descriptor movl $12,r6 # assume final result is positive movq (sp),r0 # retrieve original r0/r1 pair extzv $1,$4,r0,r0 # get byte count for first input string addl2 r0,r1 # point r1 to byte containing sign # mark_point mulp_divp_0 .text 2 .set table_size,table_size + 1 .word Lmulp_divp_0 - module_base .text 3 .word mulp_divp_0 - module_base .textLmulp_divp_0: bicb3 $0x0f0,(r1),r0 # r0 contains the sign "digit" caseb r0,$10,$15-10 # dispatch on sign digitL5: .word 2f-L5 # 10 => sign is "+" .word 1f-L5 # 11 => sign is "-" .word 2f-L5 # 12 => sign is "+" .word 1f-L5 # 13 => sign is "-" .word 2f-L5 # 14 => sign is "+" .word 2f-L5 # 15 => sign is "+"1: movl $1,r4 # count a minus sign brb L230 # now check second input sign2: clrl r4 # no real minus signs so farL230: movq 8(sp),r2 # retrieve original r2/r3 pair extzv $1,$4,r2,r2 # get byte count for second input string addl2 r2,r3 # point r3 to byte containing sign # mark_point mulp_divp_0_a .text 2 .set table_size,table_size + 1 .word Lmulp_divp_0_a - module_base .text 3 .word mulp_divp_0 - module_base .textLmulp_divp_0_a: bicb3 $0x0f0,(r3),r2 # r2 contains the sign "digit" caseb r2,$10,$15-10 # dispatch on sign digitL6: .word 5f-L6 # 10 => sign is "+" .word 4f-L6 # 11 => sign is "-" .word 5f-L6 # 12 => sign is "+" .word 4f-L6 # 13 => sign is "-" .word 5f-L6 # 14 => sign is "+" .word 5f-L6 # 15 => sign is "+"4: incl r4 # remember that sign was minus5: blbc r4,L260 # even parity indicates positive result bbs $psl$v_z,r11,L270 # step out of line for minus zero check bisb2 $psl$m_n,r11 # set n-bit in saved pswL255: incl r6 # change sign to minus # mark_point mulp_divp_0_b .text 2 .set table_size,table_size + 1 .word Lmulp_divp_0_b - module_base .text 3 .word mulp_divp_0 - module_base .textLmulp_divp_0_b:L260: insv r6,$0,$4,(r7) # store sign in result string clrl 16(sp) # set saved r4 to zero jmp vax$decimal_exit # join common exit code # if the result is negative zero, then it must be changed to positive zero # unless overflow has occurred, in which case, the sign is left as negative # but the n-bit is clear.L270: bbs $psl$v_v,r11,L255 # make sign negative if overflow brb L260 # sign will be positive # #+ # functional description: # # this routine multiplies an array of numbers (each array element lequ # 99) by a number (also lequ 99). the resulting product array is added # to another array, each of whose elements is also lequ 99. # # input parameters: # # r3 - pointer to output array # r4 - input array size # r5 - input array address # r6 - multiplier # # output parameters: # # none # # implicit output: # # the output array is altered. # # an intermediate product array is produced by multiplying each input # array element by the multiplier. each product array element is then # added to the corresponding output array element. # # side effects: # # r3, r4, and r5 are modified by this routine. # # r6 is preserved. # # r0, r1, and r2 are used as scratch registers. r0 and r1 contain the # quadword result of emul that is then passed into ediv. # # assumptions: # # this routine assumes that all array elements lie in the range from 0 # to 99 inclusive. (this is true if all input strings contain only legal # decimal digits.) the arithmetic performed by this routine will # maintain this assumption. that is, # # input array element lequ 99 # times multiplier lequ 99 # ------------------------ # product lequ 99*99 # plus carry lequ 99 # ------------------------ # modified product lequ 99*100 # plus old output array element lequ 99 # ------------------------ # new output array element lequ 99*101 = 9999 # # a number lequ 9999, when divided by 100, is guaranteed to produce both # a quotient and a remainder lequ 99. #-extend_string_multiply: clrl r2 # initial carry is zero1: emul r6,(r5)+,r2,r0 # form modified product (r0 lequ 9900) addl2 (r3),r0 # add old output array element ediv $100,r0,r2,(r3)+ # remainder to output array # quotient becomes carry sobgtr r4,1b # keep going? # this remaining code looks more complicated than it actually is. in the # usual case, the routine exits immediately. in the event that a carry # occurs, one additional entry in the output array will be modified. only in # the rare case of an output array consisting of a string of 99s will any # significant looping occur. addl2 r2,(r3) # add final carry2: cmpl (r3),$100 # do we overflow into next digit pair? bgequ 3f # branch if carry rsb # otherwise, all done3: subl2 $100,(r3)+ # readjust entry and advance pointer incl (r3) # propogate carry brb 2b # ... and test this entry for overflow # #+ # functional description: # # the dividend string specified by the dividend length and dividend # address operands is divided by the divisor string specified by the # divisor length and divisor address operands. the quotient string # specified by the quotient length and quotient address operands is # replaced by the result. # # input parameters: # # r0 - divrlen.rw number of digits in divisor string # r1 - divraddr.ab address of divisor string # r2 - divdlen.rw number of digits in dividend string # r3 - divdaddr.ab address of dividend string # r4 - quolen.rw number of digits in quotient string # r5 - quoaddr.ab address of quotient string # # output parameters: # # r0 = 0 # r1 = address of the byte containing the most significant digit of # the divisor string # r2 = 0 # r3 = address of the byte containing the most significant digit of # the dividend string # r4 = 0 # r5 = address of the byte containing the most significant digit of # the string containing the quotient # # condition codes: # # n <- quotient string lss 0 # z <- quotient string eql 0 # v <- decimal overflow # c <- 0 # # register usage: # # this routine uses all of the general registers. the condition codes # are computed at the end of the instruction as the final result is # stored in the quotient string. r11 is used to record the condit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -