📄 vaxdeciml.s
字号:
* invariance arises from the fact that a packed decimal byte containing two * zero digits converts to a byte containing zero. */ clrl r6 # otherwise, carry must propogate movzbl -(r3),r7 # so add carry to single string bsbw add_packed_byte_r6_r7 # use the special entry point sobgtr r2,5b # check for this string exhausted jbr 7f # join common completion code6: movb -(r3),-(r5) # simply move src to dst if no carry sobgtr r2,6b # ... until we're all done7: movb r8,-(r5) # store the final carry #+ # at this point, the result has been computed. that result must be moved to # its ultimate destination, noting whether any nonzero digits are stored # so that the z-bit will have its correct setting. # # input parameters: # # r9<7:0> - sign of result in preferred form # r11 - saved condition codes # # (sp) - saved r5, high address end of destination string #-add_subtract_exit: addl3 $1,(sp),r5 # point r5 beyond real destination movab 24(sp),r1 # r1 locates the saved result bsbw store_result # store the result and record the z-bit bbs $psl$v_z,r11,9f # step out of line for minus zero check8: insv r9,$0,$4,*(sp)+ # the sign can finally be stored addl2 $20,sp # get rid of intermediate buffer jbr decimal_exit # exit through common code path # if the result is negative zero, then the n-bit is cleared and the sign # is changed to a plus sign.9: bicb2 $psl$m_n,r11 # clear the n-bit unconditionally bbs $psl$v_v,r11,8b # do not change the sign on overflow movb $12,r9 # make sure that the sign is plus jbr 8b # ... and rejoin the exit code #+ # functional description: # # this routine adds together two bytes containing decimal digits and # produces a byte containing the sum that is stored in the output # string. each of the input bytes is converted to a binary number # (with a table-driven conversion), the two numbers are added, and # the sum is converted back to two decimal digits stored in a byte. # # this routine makes no provisions for bytes that contain illegal # decimal digits. we are using the unpredictable statement in the # architectural description of the decimal instructions to its fullest. # # the bytes that contain a pair of packed decimal digits can either # exist in packed decimal strings located by r1 and r3 or they can # be stored directly in registers. in the former case, the digits must # be extracted from registers before they can be used in later operations # because the sum will be used as an index register. # # for entry at add_packed_byte_string: # # input parameters: # # r1 - address one byte beyond first byte that is to be added # r3 - address one byte beyond second byte that is to be added # r5 - address one byte beyond location to store sum # # r8 - carry from previous byte (r8 is either 0 or 1) # # implicit input: # # r6 - scratch # r7 - scratch # # output parameters: # # r1 - decreased by one to point to current byte in first input string # r3 - decreased by one to point to current byte in second input string # r5 - decreased by one to point to current byte in output string # # r8 - either 0 or 1, reflecting whether this most recent add resulted # in a carry to the next byte. # # for entry at add_packed_byte_r6_r7: # # input parameters: # # r6 - first byte containing decimal digit pair # r7 - second byte containing decimal digit pair # # r5 - address one byte beyond location to store sum # # r8 - carry from previous byte (r8 is either 0 or 1) # # output parameters: # # r5 - decreased by one to point to current byte in output string # # r8 - either 0 or 1, reflecting whether this most recent add # resulted # in a carry to the next byte. # # side effects: # # r6 and r7 are modified by this routine # # r0, r2, r4, and r9 (and, of course, r10 and r11) are preserved # 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 subtract 100 at most once to put all # possible sums in the range 0..99. that is, # # 99 + 99 + 1 = 199 lss 200 # # 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. #-add_packed_byte_string: movzbl -(r1),r6 # get byte from first string movzbl -(r3),r7 # get byte from second stringadd_packed_byte_r6_r7: movb packed_to_binary_table[r6],r6 # convert digits to binary movb packed_to_binary_table[r7],r7 # convert digits to binary addb2 r6,r7 # form their sum addb2 r8,r7 # add carry from last step clrb r8 # assume no carry this time cmpb r7,$99 # check for carry blequ 1f # branch if within bounds movb $1,r8 # propogate carry to next step subb2 $100,r7 # put r7 into interval 0..991: movb 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/* at the cost of one more instruction * bbc $psl$v_z,r11,20$ * we can make this loop go faster in the usual case of nonzero result */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: jlbc r4,5f # was original r4 odd? branch if yes bicb3 0xf0,-(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 4: bitb $0xf0,(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.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 source string specified by the source length and source address # operands is scaled by a power of 10 specified by the count operand. the # destination string specified by the destination length and destination # address operands is replaced by the result. # # a positive count operand effectively multiplies# a negative count # effectively divides# and a zero count just moves and affects condition # codes. when a negative count is specified, the result is rounded using # the round operand. # # input parameters: # # r0<15:0> = srclen.rw number of digits in source character string # r0<23:16> = cnt.rb shift count # r1 = srcaddr.ab address of input character string # r2<15:0> = dstlen.rw length in digits of output decimal string # r2<23:16> = round.rb round operand used with negative shift count # r3 = dstaddr.ab address of destination packed decimal string # # output parameters: # # r0 = 0 # r1 = address of byte containing most significant digit of # the source string # r2 = 0 # r3 = address of byte containing most significant digit of # the destination string # # condition codes: # # n <- destination string lss 0 # z <- destination string eql 0 # v <- decimal overflow # c <- 0 # # algorithm: # # the routine tries as much as possible to work with entire bytes. this # makes the case of an odd shift count more difficult that of an even # shift count. the first part of the routine reduces the case of an odd # shift count to an equivalent operation with an even shift count. # # the instruction proceeds in several stages. in the first stage, after # the input parameters have been verified and stored, the operation is # broken up into four cases, based on the sign and parity (odd or even) # of the shift count. these four cases are treated as follows, in order # of increasing complexity. # # case 1. shift count is negative and even # # the actual shift operation can work with the source string in # place. there is no need to move the source string to an # intermediate work area. # # case 2. shift count is positive and even # # the source string is moved to an intermediate work area and the # sign "digit" is cleared before the actual shift operation takes # place. if the source is worked on in place, then a spurious sign # digit is moved to the middle of the output string instead of a # zero. the alternative is to keep track of where, in the several # special cases of shifting, the sign digit is looked at. we # believe that the overhead of the work area is worth the relative # simplicity of the later stages of this instruction. # # cases 3 and 4. shift count is odd # # the case of an odd shift count is considerably more difficult # than an even shift count, which is only slightly more complicated # than movp. in the case of an even shift count, various digits # remain in the same place (high nibble or low nibble) in a byte. # for odd shift counts, high nibbles become low nibbles and vice # versa. in addition, digits that were adjacent when viewing the # decimal string as a string of bits proceeding from low address to # high are now separated by a full byte. # # we proceed in two steps. the source string is first moved to a # work area. the string is then shifted by one. this shift reduces # the operation to one of the two even shift counts already # mentioned, where the source to the shift operation is the # modified source string residing in the work area. the details of # the shift-by-one are described below near the code that performs # the actual shift. #-# define ashp_shift_mask 0xf0f0f0f0 # mask used to shift string by onevax$ashp: pushr $0xfff # save registers 0-11 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 movl sp,r8 # remember current top of stack subl2 $20,sp # allocate work area on stack/* * No need to check bound because we will before calling these * routines * roprand_check r2 # insure that r2 lequ 31 * roprand_check r0 # insure that r0 lequ 31 */ bsbw strip_zeros_r0_r1 # eliminate any high order zeros extzv $1,$4,r2,r2 # convert output digit count to bytes incl r2 # make room for sign as well
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -