📄 vaxdeciml.s
字号:
extzv $1,$4,r0,r0 # same for input string addl3 r0,r1,r6 # get address of sign digit incl r0 # include byte containing sign bicb3 $0xf0,(r6),r6 # extract sign digit/* * the following can be done with a six-byte table. is the case really * necessary here? what else am i forgetting? */ movzbl $12,r9 # assume that input sign is plus caseb r6,$10,$15-10L3: # dispatch on sign .word 4f-L3 # 10 => + .word 3f-L3 # 11 => - .word 4f-L3 # 12 => + .word 3f-L3 # 13 => - .word 4f-L3 # 14 => + .word 4f-L3 # 15 => +3: incl r9 # change preferred plus to minus bisb2 $psl$m_n,r11 # set n-bit in saved psw # we now retrieve the shift count from the saved r0 and perform the next set # of steps based on the parity and sign of the shift count. note that the # round operand is ignored unless the shift count is strictly less than zero.4: cvtbl ashp_b_cnt(r8),r4 # extract sign-extended shift count blss 5f # branch if shift count negative clrl r5 # ignore "round" for positive shift bsbw ashp_copy_source # move source string to work area jlbs r4,6f # do shift by one for odd shift count bicb2 $0x0f,-(r8) # drop sign in saved source string jbr ashp_shift_positive # go do the actual shift # the "round" operand is important for negative shifts. if the shift count # is even, the source can be shifted directly into the destination. for odd # shift counts, the source must be moved into the work area on the stack and # shifted by one before the rest of the shift operation takes place.5: extzv $ashp_v_round,$ashp_s_round,ashp_b_round(r8),r5 # store "round" in a safe place jlbc r4,ashp_shift_negative # get right to it for even shift count bsbw ashp_copy_source # move source string to work area # for odd shift counts, the saved source string is shifted by one in place. # this is equivalent to a shift of -1 so the shift count (r4) is adjusted # accordingly. the least significant digit is moved to the place occupied by # the sign, the tens digit becomes the units digit, and so on. because the # work area was padded with zeros, this shift moves a zero into the high # order digit of a source string of even length. 6: pushl r0 # we need a scratch register to count decl r0 # want to map {1..16} onto {0..3} ashl $-2,r0,r0 # convert a byte count to longwords # the following loop executes from one to four times such that the entire # source, taken as a collection of longwords, is shifted by one. note that # the two pieces of the source are shifted (rotated) in opposite directions. # note also that the shift mask is applied to one string before the shift and # to the other string after the shift. (this points up the arbitrary choice # of shift mask. we just as well could have chosen the one's complement of # the shift mask and reversed the order of the shift and mask operations for # the two pieces of the source string.)7: rotl $-4,-(r8),r6 # shift left one digit bicl2 $ashp_shift_mask,r6 # clear out old low order digits bicl3 $ashp_shift_mask,-1(r8),r7 # clear out high order digits rotl $4,r7,r7 # shift these digits right one digit bisl3 r6,r7,(r8) # combine the two sets of digits sobgeq r0,7b # keep going if more movl (sp)+,r0 # restore source string byte count incl r4 # count the shift we did blss ashp_shift_negative # join common code at the right place # drop through to ashp_shift_positive #+ # functional description: # # this routine completes the work of the ashp instruction in the case of # an even shift count. (if the original shift count was odd, the source # string has already been shifted by one and the shift count adjusted by # one.) a portion (from none to all) of the source string is moved to # the destination string. pieces of the destination string at either end # may be filled with zeros. if excess digits of the source are not # moved, they must be tested for nonzero to determine the correct # setting of the v-bit. # # input parameters: # # r0<3:0> - number of bytes in source string # r1 - address of source string # r2<3:0> - number of bytes in destination string # r3 - address of destination string # r4<7:0> - count operand (signed longword of digit count) # r5<3:0> - round operand in case of negative shift # r9<3:0> - sign of source string in preferred form # # implicit input: # # r4 is presumed (guaranteed) even on input to this routine # # the top of the stack is assumed to contain a 20-byte work area (that # may or may not have been used). the space must be allocated for this # work area in all cases so that the exit code works correctly for all # cases without the need for lots of extra conditional code. # # output parameters: # # this routine completes the operation of vax$ashp. see the routine # header for vax$ashp for details on output registers and conditon codes. # # details: # # put some of the stuff from ashp.txt here. #-ashp_shift_positive: divl2 $2,r4 # convert digit count to byte count subl3 r4,r2,r7 # modify the destination count blss 3f # branch if simply moving zeros movl r4,r6 # number of zeros at low order end1: subl3 r0,r7,r8 # are there any excess high order digits? blss L260 # no, excess is in source. # we only move "srclen" source bytes. the rest of the destination string is # filled with zeros. movl r0,r7 # get number of bytes to actually move jbr L200 # ... and go move them # the count argument is larger than the destination length. all of the source # is checked for nonzero (overflow check). all of the destination is filled # with zeros.3: movl r2,r6 # number of low order zeros clrl r7 # the source string is untouched movl r0,r8 # number of source bytes to check jbr L280 # go do the actual work # if the count is negative, then there is no need to fill in low order zeros # (r6 is zero). the following code is similar to the above cases, differing # in the roles played by source length (r0) and destination length (r2) and # also in the first loop (zero fill or overflow check) that executes.ashp_shift_negative: clrl r6 # no zero fill at low end of destination mnegl r4,r4 # get absolute value of count divl2 $2,r4 # convert digit count to byte count subl3 r4,r0,r7 # get modified source length blss L270 # branch if count is larger subl3 r7,r2,r8 # are there zeros at high end? bgeq L200 # exit to zero fill loop if yes # the modified source length is larger than the destination length. part # of the source is moved. the rest is checked for nonzero. movl r2,r7 # only move "dstlen" bytes # in these cases, some digits in the source string will not be moved. if any # of these digits is nonzero, then the v-bit must be set.L260: mnegl r8,r8 # number of bytes in source to check jbr L280 # exit to overflow check loop # the count argument is larger than the source length. all of the destination # is filled with zeros. the source is ignored.L270: clrl r7 # no source bytes get moved movl r2,r8 # all of the destination is filled jbr L200 # join the zero fill loop #+ # at this point, the three separate counts have all been calculated. each # loop is executed in turn, stepping through the source and destination # strings, either alone or in step as appropriate. # # r6 - number of low order digits to fill with zero # r7 - number of bytes to move intact from source to destination # r8 - number of excess digits in one or the other string. # # if excess source digits, they must be tested for nonzero to # correctly set the v-bit. # # if excess destination bytes, they must be filled with zero. #- # test excess source digits for nonzeroL285: tstb (r1)+ # is next byte nonzero bneq L290 # handle overflow out of lineL280: sobgeq r8,L285 # otherwise, keep on looking jbr L320 # join top of second loopL290: bisb2 $psl$m_v,r11 # set saved v-bit addl2 r8,r1 # skip past rest of excess jbr L320 # join top of second loop # in this case, the excess digits are found in the destination string. they # must be filled with zero.L200: tstl r8 # is there really something to do? beql L320 # skip first loop if nothingL310: clrb (r3)+ # store another zero sobgtr r8,L310 # ... and keep on looping # the next loop is where something interesting happens, namely that parts of # the source string are moved to the destination string. note that the use of # bytes rather than digits in this operation makes the detection of nonzero # digits difficult because the presence of a nonzero digit in the place # occupied by the sign or in the high order nibble of an even output string # and nowhere else would cause the z-bit to be incorrectly cleared. for this # reason, we ignore the z-bit here and make a special pass over the output # string after all of the special cases have been dealt with. the extra # overhead of a second trip to memory is offset by the simplicity in other # places in this routine.L320: tstl r7 # something to do here? beql L340 # skip this loop if nothingL330: movb (r1)+,(r3)+ # move the next byte sobgtr r7,L330 # ... and keep on looping # the final loop occurs in some cases of positive shift count where the low # order digits of the destination must be filled with zeros.L340: tstl r6 # something to do here? beql L360 # skip if loop count is zeroL350: clrb (r3)+ # store another zero sobgtr r6,L350 # ... until we're done #+ # at this point, the destination string is complete except for the sign. # if there is a round operand, that must be added to the destination string. # # r3 - address one byte beyond destination string # r5 - round operand #-L360: addl2 $20,sp # deallocate work area extzv $1,$4,ashp_w_dstlen(sp),r2 # get original destination byte count movq r2,-(sp) # save address and count for z-bit loop movzbl r5,r8 # load round into carry register beql L380 # skip next mess unless "round" exists movl r3,r5 # r5 tracks the addition output clrl r6 # we only need one term and carry in sumL370: movzbl -(r3),r7 # get next digit bsbw add_packed_byte_r6_r7 # perform the addition tstl r8 # see if this add produced a carry beql L380 # all done if no more carry sobgeq r2,L370 # back for the next byte # if we drop through the end of the loop, then the final add produced a carry. # this must be reflected by setting the v-bit in the saved psw. bisb2 $psl$m_v,r11 # set the saved v-bit # all of the digits are now loaded into the destination string. the condition # codes, except for the z-bit, have their correct settings. the sign must be # set, a check must be made for even digit count in the output string, and # the various special cases (negative zero, decimal overflow trap, ans so on) # must be checked before completing the routine. # this entire routine worked with entire bytes, ignoring whether digit counts # were odd or even. an illegal digit in the upper nibble of an even input string # is ignored. a nonzero digit in the upper nibble of an even output string is # not allowed but must be checked for. if one exists, it indicates overflow.L380: jlbs 16(sp),L385 # skip next if output digit count is odd bitb $0xf0,*20(sp) # is most significant digit nonzero? beql L385 # nothing to worry about if zero bicb2 $0xf0,*20(sp) # make the digit zero bisb2 $psl$m_v,r11 # ... and set the overflow bit # we have not tested for nonzero digits in the output string. this test is # made by making another pass over the ouptut string. note that the low # order digit is unconditionally checked.L385: movq (sp),r2 # get address and count bitb $0xf0,-(r3) # do not test sign in low order byte bneq L387 # skip loop if nonzero jbr L386 # start at bottom of loopL383: tstb -(r3) # is next higher byte nonzero? bneq L387 # exit loop if yesL386: sobgeq r2,L383 # keep looking for nonzero if more bytes # the entire output string has been scanned and contains no nonzero # digits. the z-bit retains its original setting, which is set. if the # n-bit is also set, then the negative zero must be changed to positive # zero (unless the v-bit is also set). note that in the case of overflow, # the n-bit is cleared but the output string retrins the minus sign. bbc $psl$v_n,r11,L390 # n-bit is off already bicb2 $psl$m_n,r11 # turn off saved n-bit unconditionally bbs $psl$v_v,r11,L390 # no fixup if v-bit is also set movb $12,r9 # use preferred plus as sign of output jbr L390 # ... and rejoin the exit code # the following instruction is the exit point for all of the nonzero byte # checks. its direct effect is to clear the saved z-bit. it also bypasses # whatever other zero checks have not yet been performed.L387: bicb2 $psl$m_z,r11 # clear saved z-bit # the following code executes in all cases. it is the common exit path for # all of the ashp routines when the count is even.L390: movq (sp)+,r2 # get address of end of output string insv r9,$0,$4,-1(r3) # store sign that we have been saving #+ # this is the common exit path for many of the routines in this module. this # exit path can only be used for instructions that conform to the following # restrictions. # # 1. registers r0 through r11 were saved on entry. # # 2. the architecture requires that r0 and r2 are zero on exit. # # 3. all other registers that have instruction-specific values on exit are # correctly stored in the appropriate locations on the stack. # # 4. the saved psw is contained in r11 # # 5. this instruction/routine should generate a decimal overflow trap if # both the v-bit and the dv-bit are set on exit. #-decimal_exit:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -