📄 vaxarith.s
字号:
# by this routine # # assumptions: # # this routine makes two important assumptions. # # 1. if both of the input bytes contain only legal decimal digits, then # it is only necessary to add 100 at most once to put all # possible differences in the range 0..99. that is, # # 0 - 99 - 1 = -100 # # 2. the result will be checked in some way to determine whether the # result is nonzero so that the z-bit can have its correct setting. #-sub_packed_byte_string: # mark_point add_sub_bsbw_24_b .text 2 .set table_size,table_size + 1 .word Ladd_sub_bsbw_24_b - module_base .text 3 .word add_sub_bsbw_24 - module_base .textLadd_sub_bsbw_24_b: movzbl -(r1),r6 # get byte from first string # mark_point add_sub_bsbw_24_c .text 2 .set table_size,table_size + 1 .word Ladd_sub_bsbw_24_c - module_base .text 3 .word add_sub_bsbw_24 - module_base .textLadd_sub_bsbw_24_c: movzbl -(r3),r7 # get byte from second stringsub_packed_byte_r6_r7: movb decimal$packed_to_binary_table[r6],r6 # convert digits to binary movb decimal$packed_to_binary_table[r7],r7 # convert digits to binary subb2 r6,r7 # form their difference subb2 r8,r7 # include borrow from last step blss 1f # branch if need to borrow clrb r8 # no borrow next time brb 2f # join common exit code1: addb2 $100,r7 # put r7 into interval 0..99 movb $1,r8 # propogate borrow to next step2: movb decimal$binary_to_packed_table[r7],-(r5) # store converted sum byte rsb # #+ # functional description: # # this routine takes a packed decimal string that typically contains # the result of an arithmetic operation and stores it in another # decimal string whose descriptor is specified as an input parameter # to the original arithmetic operation. # # the string is stored from the high address end (least significant # digits) to the low address end (most significant digits). this order # allows all of the special cases to be handled in the simplest fashion. # # input parameters: # # r1 - address one byte beyond high address end of input string # (note that this string must be at least 17 bytes long.) # # r4<4:0> - number of digits in ultimate destination # r5 - address one byte beyond destination string # # r11 - contains saved condition codes # # implicit input: # # the input string must be at least 17 bytes long to contain a potential # carry out of the highest digit when doing an add of two large numbers. # this carry out of the last byte will be detected and reported as a # decimal overflow, either as an exception or simply by setting the v-bit. # # the least significant digit (highest addressed byte) cannot contain a # sign digit because that would cause the z-bit to be incorrectly cleared. # # output parameters: # # r11<psl$v_z> - cleared if a nonzero digit is stored in output string # r11<psl$v_v> - set if a nonzero digit is detected after the output # string is exhausted # # a portion of the result (dictated by the size of r4 on input) is # moved to the destination string. #-store_result: incl r4 # want number of "complete" bytes in ashl $-1,r4,r0 # output string beql 3f # skip first loop if none # mark_point add_sub_bsbw_24_d .text 2 .set table_size,table_size + 1 .word Ladd_sub_bsbw_24_d - module_base .text 3 .word add_sub_bsbw_24 - module_base .textLadd_sub_bsbw_24_d:1: movb -(r1),-(r5) # move the next complete byte beql 2f # check whether to clear z-bit bicb2 $psl$m_z,r11 # clear z-bit if nonzero2: sobgtr r0,1b # keep going?3: blbc r4,5f # was original r4 odd? branch if yes # mark_point add_sub_bsbw_24_f .text 2 .set table_size,table_size + 1 .word Ladd_sub_bsbw_24_f - module_base .text 3 .word add_sub_bsbw_24 - module_base .textLadd_sub_bsbw_24_f: bicb3 $0x0f0,-(r1),-(r5) # if r4 was even, store half a byte beql 4f # need to check for zero here, too bicb2 $psl$m_z,r11 # clear z-bit if nonzero # mark_point add_sub_bsbw_24_g .text 2 .set table_size,table_size + 1 .word Ladd_sub_bsbw_24_g - module_base .text 3 .word add_sub_bsbw_24 - module_base .textLadd_sub_bsbw_24_g:4: bitb $0x0f0,(r1) # if high order nibble is nonzero, bneq 7f # ... then overflow has occurred # the entire destination has been stored. we must now check whether any of # the remaining input string is nonzero and set the v-bit if nonzero is # detected. note that at least one byte of the output string has been examined # in all cases already. this makes the next byte count calculation correct.5: decl r4 # restore r4 to its original self extzv $1,$4,r4,r0 # extract a byte count subb3 r0,$16,r0 # loop count is 16 minus byte count # note that the loop count can never be zero because we are testing a 17-byte # string and the largest output string can be 16 bytes long. # mark_point add_sub_bsbw_24_h .text 2 .set table_size,table_size + 1 .word Ladd_sub_bsbw_24_h - module_base .text 3 .word add_sub_bsbw_24 - module_base .textLadd_sub_bsbw_24_h:6: tstb -(r1) # check next byte for nonzero bneq 7f # nonzero means overflow has occurred sobgtr r0,6b # check for end of this loop rsb # this is return path for no overflow7: bisb2 $psl$m_v,r11 # indicate that overflow has occurred rsb # ... and return to the caller # #+ # functional description: # # the multiplicand string specified by the multiplicand length and # multiplicand address operands is multiplied by the multiplier string # specified by the multiplier length and multiplier address operands. the # product string specified by the product length and product address # operands is replaced by the result. # # input parameters: # # r0 - mulrlen.rw number of digits in multiplier string # r1 - mulraddr.ab address of multiplier string # r2 - muldlen.rw number of digits in multiplicand string # r3 - muldaddr.ab address of multiplicand string # r4 - prodlen.rw number of digits in product string # r5 - prodaddr.ab address of product string # # output parameters: # # r0 = 0 # r1 = address of the byte containing the most significant digit of # the multiplier string # r2 = 0 # r3 = address of the byte containing the most significant digit of # the multiplicand string # r4 = 0 # r5 = address of the byte containing the most significant digit of # the string containing the product # # condition codes: # # n <- product string lss 0 # z <- product 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 product string. r11 is used to record the condition # codes. # # notes: # # 1. this routine uses a large amount of stack space to allow storage of # intermediate results in a convenient form. specifically, each digit # pair of the longer input string is stored in binary in a longword on # the stack. in addition, 32 longwords are set aside to hold the product # intermediate result. each longword contains a binary number between 0 # and 99. # # after the multiplication is complete. each longword is removed from # the stack, converted to a packed decimal pair, and stored in the # output string. any nonzero cells remaining on the stack after the # output string has been completely filled are the indication of decimal # overflow. # # the purpose of this method of storage is to avoid decimal/binary or # even byte/longword conversions during the calculation of intermediate # results. # # 2. trailing zeros are removed from the larger string. all zeros in # the shorter string are eliminated in the sense that no arithmetic # is performed. the output array pointer is simply advanced to point # to the next higher array element. #- .globl vax$mulpvax$mulp: # pushr $^m<r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11> # save the lot pushr $0x0fff # establish_handler - # store address of access # arith_accvio # violation handler movab arith_accvio,r10 # roprand_check r4 # insure that r4 is lequ 31 cmpw r4,$31 blequ 1f brw decimal_roprand1: movzwl r4,r4 # roprand_check r2 # insure that r2 is lequ 31 cmpw r2,$31 blequ 1f brw decimal_roprand1: movzwl r2,r2 # mark_point mulp_bsbw_0 .text 2 .set table_size,table_size + 1 .word Lmulp_bsbw_0 - module_base .text 3 .word mulp_bsbw_0 - module_base .textLmulp_bsbw_0: jsb decimal$strip_zeros_r2_r3 # strip high order zeros from r2/r3 string # roprand_check r0 # insure that r0 is lequ 31 cmpw r0,$31 blequ 1f brw decimal_roprand1: movzwl r0,r0 # mark_point mulp_bsbw_0_a .text 2 .set table_size,table_size + 1 .word Lmulp_bsbw_0_a - module_base .text 3 .word mulp_bsbw_0 - module_base .textLmulp_bsbw_0_a: jsb decimal$strip_zeros_r0_r1 # strip high order zeros from r0/r1 string extzv $1,$4,r0,r0 # convert digit count to byte count incl r0 # include least significant digit extzv $1,$4,r2,r2 # convert digit count to byte count incl r2 # include least significant digit cmpl r0,r2 # see which string is larger bgtru 3f # r2/r3 describes the longer string movq r2,r8 # r8 and r9 describe the longer string movq r0,-(sp) # shorter string descriptor also saved brb 6f3: movq r0,r8 # r8 and r9 describe the longer string movq r2,-(sp) # shorter string descriptor also saved # create space for the output array on the stack (32 longwords of zeros)6: movl $8,r0 # eight pairs of quadwords0: clrq -(sp) # clear one pair clrq -(sp) # ... and another sobgtr r0,0b # do all eight pairs movl sp,r7 # store beginning of output array in r7 # the longer input array will be stored on the stack as an array of # longwords. each array element contains a number between 0 and 99, # representing a pair of digits in the original packed decimal string. # because the units digit is stored with the sign in packed decimal format, # it is necessary to shift the number as we store it. this is accomplished by # multiplying the number by ten. # # the longer array is described by r8 (byte count) and r9 (address of most # significant digit pair). addl3 r9,r8,r5 # point r5 beyond sign digit movl r8,r4 # r4 contains the loop count # an array of longwords is allocated on the stack. r3 starts out pointing # at the longword beyond the top of the stack. the first remainder, guaranteed # to be zero, is "stored" here. the rest of the digit pairs are stored safely # below the top of the stack. mnegl r8,r3 # stack grows toward lower addresses moval (sp)[r3],sp # allocate the space subl3 $4,sp,r3 # point r3 at next lower longword # mark_point mulp_r8 .text 2 .set table_size,table_size + 1 .word Lmulp_r8 - module_base .text 3 .word mulp_r8 - module_base .textLmulp_r8:2: movzbl -(r5),r1 # get next digit pair movzbl decimal$packed_to_binary_table[r1],r1 # convert digits to binary emul $10,r1,r2,r0 # multiply by 10 ediv $100,r0,r2,(r3)+ # divide by 100 sobgtr r4,2b movl r2,(r3) # store final quotient movl sp,r9 # remember array address in r9 pushal (sp)[r8] # store start of fixed size area # check for trailing zeros in the input array stored on the stack. if any are # present, they are removed and the product array is adjusted accordingly.3: tstl (r9)+ # is next number zero? bneq 4f # leave loop if nonzero addl2 $4,r7 # advance output pointer to next element sobgtr r8,3b # keep going # if we drop through the loop, then the entire input array is zero. there is # no need to perform any arithmetic because the product will be zero (and the # output array on the stack starts out as zero). the only remaining work is # to store the result in the output string and set the condition codes. brb 7f # exit to end processing # now multiply the input array by each successive digit pair. in order to # allow r10 to continue to locate arith_accvio while we execute this loop, it # is necessary to perform a small amount of register juggling. in essence, # r8 and r9 switch the identity of the string that they describe.4: subl2 $4,r9 # readjust input array pointer movq r8,-(sp) # save r8/r9 descriptor on stack movl 8(sp),r8 # point r8 at start of 32-longword array movq (32*4)(r8),r8 # get descriptor that follows that array addl2 r8,r9 # point r9 beyond sign byte5: moval (r7)+,r3 # output array address to r3 # mark_point mulp_at_sp .text 2 .set table_size,table_size + 1 .word Lmulp_at_sp - module_base .text 3 .word mulp_at_sp - module_base .text
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -