📄 vaxconvrt.s
字号:
# This routine is shared by both CVTPS and CVTPT to translate an ASCII # string that contains only the characters "0" to "9" into an equivalent # packed decimal string. A check is made for legal input digits and a # reserved operand generated if an illegal digit is encountered. # # input parameters: # # r0 = srclen.rw number of digits in source character string # r1 = srcaddr.ab address of first digiyt in input character # string # r2 = dstlen.rw length in digits of output decimal string # r3 = dstaddr.ab address of destination packed decimal string # # (sp) address of instruction-specific completion code in cvtsp # or cvtpt routine # # output parameters: # # r0 = Size in digits of shorter of source and dest. strings # r1 = address of lowest addressed byte of source string # (see instruction-specific header for details) # r2 = Number of digits in dest. packed decimal string # r3 = address of byte containing most significant digit of # the destination string # # R11 contains the partial condition codes accumlated by converting # all but the least significant input digit # # condition codes: # # implicit output: # # r4<31:8> is zero to insure that cvtsp works correctly # # r10 is loaded with the address of an access violation handler in the # event that any strings touched by this routine are not accessible. # # side effects: # # r4 and r5 are used as scratch registers by this routine. # # r6 through r9 are not used. #-cvtxp_common: # roprand_check r0 # insure that r0 lequ 31 cmpw r0,$31 blequ 1f brw decimal_roprand1: movzwl r0,r0 # roprand_check r2 # insure that r2 lequ 31 cmpw r2,$31 blequ 1f brw decimal_roprand1: movzwl r2,r2 movpsl r11 # get initial psl insv $psl$m_z,$0,$4,r11 # set z-bit, clear the rest # establish_handler convrt_accvio # Store address of access # violation handler movab convrt_accvio,r10 subl3 r2,r0,r5 # r5 is length difference beql cvtxp_equal # life is easy if they're the same blss cvtxp_zero_fill # fill output with zeros if its too large #+ # ********** srclen gtru dstlen ********** # # the following code executes if the source string is larger than the # destination string. excess high order input digits must be discarded. if # any of the input digits is not zero, then the v-bit is set in the saved psw # (stored in r11). in addition, digits must be checked for legal values # (ascii 0 through ascii 9) before they are discarded in order to determine # whether to generate a reserved operand abort. the low order digits will be # moved as in the normal case. a test for whether decimal overflow exceptions # are to be generated is made as part of final instruction processing. # # r5 = r0 - r2 (r5 gtru 0) #-cvtxp_overflow_check: # mark_point cvtxp_bsbw .text 2 .set table_size,table_size + 1 .word Lcvtxp_bsbw - module_base .text 3 .word cvtxp_bsbw - module_base .textLcvtxp_bsbw:1: cmpb (r1)+,$0x30 # is digit ascii zero? bneq 3f # exit loop if other than zero2: sobgtr r5,1b # test for more excess digits movl r2,r0 # update input length for skipped digits brb cvtxp_equal # join common code # the following code executes if any of the discarded digits is nonzero. # if the digit is the ascii representation of a decimal digit, then the # v-bit is set in the saved psw and the saved z-bit is cleared. the loop # is reentered where we left it to continue the search for legal input # digits. (note that this is different from the cvtpx case where, once an # overflow was detected, the remaining excess input digits could be skipped.)3: blssu 4f # reserved operand if outside range bisb2 $psl$m_v,r11 # set saved v-bit # mark_point cvtxp_bsbw_a .text 2 .set table_size,table_size + 1 .word Lcvtxp_bsbw_a - module_base .text 3 .word cvtxp_bsbw - module_base .textLcvtxp_bsbw_a: cmpb -1(r1),$0x039 # compare digit to ascii "9" blequ 2b # back in loop if inside range4: brw decimal_roprand # signal illegal digit abort #+ # ********** srclen lssu dstlen ********** # # the following code executes if the destination string is longer than the # source string. all excess digits in the destination string are filled # with zero. #-cvtxp_zero_fill: mnegl r5,r5 # make digit count positive blbc r0,5f # different code paths for even and odd # input string sizes (the shorter one) # shorter string has odd number of digits. note that the divide by two can # never produce zero because r5 is always nonzero before the incl so that r5 # is always at least two before the divide takes place. the comment at the # beginning of the module explains the two different code paths based on the # parity of the input (shorter) string. incl r5 # adjust before divide by two extzv $1,$4,r5,r5 # convert digit count to byte count brb 6f # join common loop # shorter string has an even number of digits.5: extzv $1,$4,r5,r5 # convert digit count to byte count beql cvtxp_equal # no loop if byte count is zero # mark_point cvtxp_bsbw_b .text 2 .set table_size,table_size + 1 .word Lcvtxp_bsbw_b - module_base .text 3 .word cvtxp_bsbw - module_base .textLcvtxp_bsbw_b:6: clrb (r3)+ # store a pair of zeros in output string sobgtr r5,6b # test for more bytes to clear #+ #********** updated srclen eql updated dstlen ********** # # the following code is a common meeting point for the three different input # cases relating source length and destination length. excess source or # destination digits have already been dealt with. we are effectively # dealing with input and output strings of equal length (as measured by # number of digits). #-cvtxp_equal: clrl r4 # insure that r4<31:8> is zero extzv $1,$4,r0,r5 # convert digit count to byte count beql L110 # down to last digit if zero # if the count of remaining digits is even, we need to jump into the middle # of the loop. but the store operation in the second half of the loop uses a # bisb2, assuming that the high order nibble is already cleared (which it is if # we also execute the first half of the loop). in order to insure that the high # order nibble has a zero stored in it, we jump to the last instruction of the # first half of the loop. because we just cleared r4, the movb instruction at # 90$ stores a zero in the appropriate byte of the output string. blbc r0,9f # to middle of loop if digit count even # mark_point cvtxp_bsbw_c .text 2 .set table_size,table_size + 1 .word Lcvtxp_bsbw_c - module_base .text 3 .word cvtxp_bsbw - module_base .textLcvtxp_bsbw_c:7: subb3 $0x30,(r1)+,r4 # convert ascii to digit blssu 4b # abort instruction if out of range beql 8f # do not clear z-bit if digit is zero bicb2 $psl$m_z,r11 # clear z-bit when digit is 1 to 98: cmpb r4,$9 # check for other end of range bgtru 4b # abort if outside the other end, too # mark_point cvtxp_bsbw_d .text 2 .set table_size,table_size + 1 .word Lcvtxp_bsbw_d - module_base .text 3 .word cvtxp_bsbw - module_base .textLcvtxp_bsbw_d:9: movb cvtxp_table_high[r4],(r3) # store digit in high nibble # note that the above instruction also clears out the low order four bits in # the currently addressed byte in the output packed decimal string. # mark_point cvtxp_bsbw_e .text 2 .set table_size,table_size + 1 .word Lcvtxp_bsbw_e - module_base .text 3 .word cvtxp_bsbw - module_base .textLcvtxp_bsbw_e: subb3 $0x030,(r1)+,r4 # convert ascii to digit "0" blssu 4b # abort instruction if out of range beql 0f # do not clear z-bit if digit is zero bicb2 $psl$m_z,r11 # clear z-bit when digit is 1 to 90: cmpb r4,$9 # check for other end of range bgtru 4b # abort if outside the other end, too # mark_point cvtxp_bsbw_f .text 2 .set table_size,table_size + 1 .word Lcvtxp_bsbw_f - module_base .text 3 .word cvtxp_bsbw - module_base .textLcvtxp_bsbw_f: bisb2 cvtxp_table_low[r4],(r3)+ # store digit in low nibble sobgtr r5,7b # test for end of loopL110: rsb # perform instruction-specific # end processing #- # functional description: # # this routine receives control when a digit count larger than 31 # is detected. the exception is architecturally defined as an # abort so there is no need to store intermediate state. all of the # routines in this module save all registers r0 through r11 before # performing the digit check. these registers must be restored # before control is passed to vax$roprand. # # input parameters: # # entry at decimal_roprand # # 00(sp) - return pc from common subroutine (discarded) # 04(sp) - saved r0 \ # . \ # . > restored # . / # 48(sp) - saved r11 / # 52(sp) - return pc from vax$xxxxxx routine # # entry at decimal_roprand_no_pc # # 00(sp) - saved r0 \ # . \ # . > restored # . / # 44(sp) - saved r11 / # 48(sp) - return pc from vax$xxxxxx routine # # output parameters: # # 00(sp) - offset in packed register array to delta pc byte # 04(sp) - return pc from vax$xxxxxx routine # # The two flags in this longword ( pack_m_fpd and pack_m_accvio ) # are both clear in the case of a reserved operand abort # # implicit output: # # this routine passes control to vax$roprand where further # exception processing takes place. # # note: # # this routine can be entered either from internal subroutines or from # the callers of these subroutines. the decimal_roprand entry point is # used when the return pc is on the stack because that is the name of # the routine that is qutomatically invoked by the roprand_check macro # when an illegal digit count is detected. the other name is arbitrary. #-decimal_roprand: addl2 $4,sp # discard return pc from common routinedecimal_roprand_no_pc: # popr $^m<r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11> popr $0x0fff pushl $cvtps_b_delta_pc # store offset to delta pc byte jmp vax$roprand # pass control along #+ # functional description: # # this routine receives control when an access violation occurs while # executing within the emulator routines for cvtps, cvtpt, cvtsp, or # cvttp. # # the routine header for ashp_accvio in module vax$ashp contains a # detailed description of access violation handling for the decimal # string instructions. # # input parameters: # # see routine ashp_accvio in module vax$ashp # # output parameters: # # see routine ashp_accvio in module vax$ashp #-convrt_accvio: clrl r2 # initialize the counter pushab module_base # store base address of this module subl2 (sp)+,r1 # get pc relative to this base1: cmpw r1,pc_table_base[r2] # is this the right pc? beql 3f # exit loop if true aoblss $table_size,r2,1b # do the entire table # if we drop through the dispatching based on pc, then the exception is not # one that we want to back up. we simply reflect the exception to the user.2: # popr #^m<r0,r1,r2,r3> # restore saved registers popr $0x0f rsb # return to exception dispatcher # the exception pc matched one of the entries in our pc table. r2 contains # the index into both the pc table and the handler table. r1 has served # its purpose and can be used as a scratch register.3: movzwl handler_table_base[r2],r1 # get the offset to the handler jmp module_base[r1] # pass control to the handler # in all of the instruction-specific routines, the state of the stack # will be shown as it was when the exception occurred. all offsets will # be pictured relative to r0. #+ # functional description: # # it is relatively simple to back out any of these four instructions # because their use of stack space is so simple. each of the four # routines contains a certain amount of initialization or completion # code that uses no stack space (over and above the saved register # array). additional processing occurs one level deep in a subroutine # where there is a return pc on the stack that must be discarded. # # input parameters: # # r0 - address of top of stack when access violation occurred # # see specific entry points for details # # output parameters: # # see input parameter list for vax$decimal_accvio in module vax$ashp #- #+ # cvtpx_saved_r1 # # an access violation occurred in routine cvtpx_common along the code path # where the intermediate value of r1 is stored on the stack along with the # return pc. this must be disacrded. # # 00(r0) - saved intermediate value of r1 # 04(r0) - return pc in mainline of vax$cvtps or vax$cvtpt # 08(r0) - saved r0 # 12(r0) - saved r1 # etc. #-cvtpx_saved_r1: addl2 $4,r0 # skip over saved r1 and drop into ... #+ # convert_bsbw # # an access violation occurred somewhere in cvtpx_common or cvtxp_common. # the return pc must be discarded. # # 00(r0) - return pc in vax$cvtps, vax$cvtpt, vax$cvtsp, or vax$cvttp # 04(r0) - saved r0 # 08(r0) - saved r1 # etc. #-cvtpx_bsbw:cvtxp_bsbw: addl2 4,r0 # skip over return pc and drop into ... #+ # convert_accvio # # the access violation occurred in one of the four outer routines where # nothing other than the saved registers has been pushed onto the stack. # nothing more needs to be done to the registers or the stack before # transferring control to vax$decimal_accvio. these entry points are merely # a convenience. # # 00(sp) - saved r0 # 04(sp) - saved r1 # 08(sp) - saved r2 # 12(sp) - saved r3 # etc. #-cvtps_accvio:cvtpt_accvio:cvtsp_accvio:cvttp_accvio: jmp vax$decimal_accvio # join common code to restore registers
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -