📄 vaxconvrt.s
字号:
# in addition, the cvtsp instruction insures that the sign character is # one of "+", " ", or "-". # # the cvttp instruction uses the highest addressed byte as an offset # into a 256-byte table. the byte that is retrieved from this table is # checked to determine that its high nibble contains a legal decimal # digit and its low nibble contains a legal sign. #- #+ # the following tables contains the decimal equivalents of the ten decimal # digits. one table is used if the low nibble of a byte is being loaded # (an even numbered digit). the other table is used when the high nibble # of a byte is being loaded (odd numbered digit). #- # table for entry into low order nibblecvtxp_table_low: .byte 0x00 , 0x01 , 0x02 , 0x03 , 0x04 .byte 0x05 , 0x06 , 0x07 , 0x08 , 0x09 # table for entry into high order nibblecvtxp_table_high: .byte 0x00 , 0x10 , 0x20 , 0x30 , 0x40 .byte 0x50 , 0x60 , 0x70 , 0x80 , 0x90 #+ # functional description: # # the source numeric string specified by the source length and source # address operands is converted to a packed decimal string and the # destination string specified by the destination address and destination # length operands is replaced by the result. # # input parameters: # # r0 = srclen.rw number of digits in source character string # r1 = srcaddr.ab address of input character string # r2 = dstlen.rw length in digits of output decimal string # r3 = dstaddr.ab address of destination packed decimal string # # output parameters: # # r0 = 0 # r1 = address of the sign byte 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 # # Notes: #- # note that the two entry points vax$cvtsp and vax$cvttp must save the # exact same set of registers because the two routines use a common exit # path that includes a popr instruction that restores registers. in fact, by # saving all registers, even if one or two of them are not needed, we can use # the common exit path from this module. .globl vax$cvtspvax$cvtsp: # pushr $^m<r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11> # save the lot pushr $0x0fff incl r1 # skip byte containing sign for now bsbw cvtxp_common # execute bulk as common code #+ # the common code routine returns here with the following relevant input. # # r0 number of digits remaining in source and destination strings # r1 address of last (highest addressed) byte in source string # r3 address of least significant digit and sign of output string # r4 r4<31:8> must be zero on input to this routine # r11 saved psw with condition codes to date (n=0,z,v,c=0) # # cvtsp_a_srcaddr(sp) saved r1 at input, address of sign character # # r4 is a scratch register # # the last input digit is moved to the output stream, after a check that it # represents a legal decimal digit. a check is also required to insure that # the z-bit has its correct setting if this digit is the first nonzero digit # encountered in the input string. the sign of the input string is checked # for a legal value and transformed into one of two legal output signs, 12 # for "+" and 13 for "-". #- # mark_point cvtsp_accvio .text 2 .set table_size,table_size + 1 .word Lcvtsp_accvio - module_base .text 3 .word cvtsp_accvio - module_base .textLcvtsp_accvio: movb $12,(r3) # assume that sign is plus tstl r0 # check for zero length input string beql 2f # skip storing digit if nothing there # mark_point cvtsp_accvio_a .text 2 .set table_size,table_size + 1 .word Lcvtsp_accvio_a - module_base .text 3 .word cvtsp_accvio - module_base .textLcvtsp_accvio_a: subb3 $0x030,(r1),r4 # get least significant digit "0" blssu 3f # reserved operand if not a digit beql 1f # skip clearing z-bit if zero bicb2 $psl$m_z,r11 # clear saved z-bit1: cmpb r4,$9 # check digit against top of range bgtru 3f # reserved operand if over the top # mark_point cvtsp_accvio_b .text 2 .set table_size,table_size + 1 .word Lcvtsp_accvio_b - module_base .text 3 .word cvtsp_accvio - module_base .textLcvtsp_accvio_b: addb2 cvtxp_table_high[r4],(r3) # store final output digit # mark_point cvtsp_accvio_c .text 2 .set table_size,table_size + 1 .word Lcvtsp_accvio_c - module_base .text 3 .word cvtsp_accvio - module_base .textLcvtsp_accvio_c:2: movzbl *cvtsp_a_srcaddr(sp),r4 # get sign character from input string caseb r4,$0x2b,$0x2d - 0x2b # 001 dispatch on sign characterL3: .word 5f-L3 # character is "+" .word 3f-L3 # sign character is "#" (illegal input) .word 4f-L3 # character is "-" cmpb r4,$0x20 # blank is also legal "plus sign" beql 5f # error path for all code paths that detect an illegal character in # the input stream3: brw decimal_roprand_no_pc # reserved operand abort on illegal input # the sign of the input stream was "-". if something other than negative # zero, set the n-bit and adjust the sign.4: bisb2 $psl$m_n,r11 # set n-bit because sign is "-" # mark_point cvtsp_accvio_d .text 2 .set table_size,table_size + 1 .word Lcvtsp_accvio_d - module_base .text 3 .word cvtsp_accvio - module_base .textLcvtsp_accvio_d: incb (r3) # change sign from "+" (12) to "-" (13) bbc $psl$v_z,r11,5f # all done unless negative zero bicb2 $psl$m_n,r11 # clear the saved n-bit bbs $psl$v_v,r11,5f # the output sign is ignored if overflow # mark_point cvtsp_accvio_e .text 2 .set table_size,table_size + 1 .word Lcvtsp_accvio_e - module_base .text 3 .word cvtsp_accvio - module_base .textLcvtsp_accvio_e: decb (r3) # change sign back so -0 becomes +05: jmp vax$decimal_exit # exit through common code #+ # functional description: # # the source trailing numeric string specified by the source length and # source address operands is converted to a packed decimal string and the # destination packed decimal string specified by the destination address # and destination length operands is replaced by the result. # # conversion is effected by using the highest addressed (trailing) byte of # the source string as an unsigned index into a 256 byte table whose # zeroth entry is specified by the table address operand. the byte read # out of the table replaces the highest addressed byte of the destination # string (i.e. the byte containing the sign and the least significant # digit). the remaining packed digits of the destination string are # replaced by the low order 4 bits of the corresponding bytes in the # source string. # # input parameters: # # r0 <15:0> = srclen.rw number of digits in source character string # r0 <31:16> = dstlen.rw length in digits of output decimal string # r1 = srcaddr.ab address of input character string # r2 = tbladdr.ab address of 256-byte table used for sign conversion # r3 = dstaddr.ab address of destination packed decimal string # # output parameters: # # r0 = 0 # r1 = address of 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 #- # note that the two entry points vax$cvtsp and vax$cvttp must save the # exact same set of registers because the two routines use a common exit # path that includes a popr instruction that restores registers. in fact, by # saving all registers, even if one or two of them are not needed, we can use # the common exit path from this module. # # See the rotine header for CVTPT for an explanation of the _JSB and _RESTART # entry points. # there is a single case where the common subroutine cannot be used. if the # output length is zero, then the final character in the input string would # be subjected to the rather stringent legality test that it lie between # ascii 0 and ascii 9. in fact, it is the translated character that must be # tested. there are three cases. # # the input length is also zero. in this case, the common code path can # be used because the input and output length are equal. (in fact, the # subroutine does little more than set the condition codes and load # registers. # # the input consists of a single character. in this case, this single # character is translated and tested for legality. note that the # subroutine is also called here to set condition codes and the like. # # the input size is larger than one. in this case, the common subroutine # is called with the input size reduced by one. the leading characters # are tested by the subroutine which returns here to allow the final # character to be tested. # # note that this is not a commonly travelled code path so that the seemingly # excessive amount of code necessary to achieve accuracy is not a performance # problem. 8: # roprand_check r0 # insure that r0 lequ 31 cmpw r0,$31 blequ 1f brw decimal_roprand1: movzwl r0,r0 beql 0f # back in line if source length zero decl r0 # reduce input length by one bsbw cvtxp_common # check leading digits for legality # mark_point cvttp_accvio .text 2 .set table_size,table_size + 1 .word Lcvttp_accvio - module_base .text 3 .word cvttp_accvio - module_base .textLcvttp_accvio:9: movzbl (r1),r4 # get last input byte # mark_point cvttp_accvio_a .text 2 .set table_size,table_size + 1 .word Lcvttp_accvio_a - module_base .text 3 .word cvttp_accvio - module_base .textLcvttp_accvio_a: movzbl (r9)[r4],r4 # get associated output byte from table bicb3 $0x0f0,r4,(r3) # only store sign in output string extzv $4,$4,r4,r0 # get low-order digit beql 1f # join exit code if zero bisb2 $psl$m_v,r11 # set v-bit in saved psw cmpl r0,$9 # is the digit within range? blequ 1f # yes, join the exit code brw decimal_roprand_no_pc # otherwise, report exception .globl vax$cvttp_jsbvax$cvttp_jsb: # bbcc $cvttp_v_fpd,r0,vax$cvttp # Have we been here before? bbcc $cvttp_v_fpd,r0,L600 .globl vax$cvttp_restartvax$cvttp_restart: bicl2 $0x0ff000000,r0 # Make sure that we clear the right byte .globl vax$cvttpvax$cvttp:L600: # pushr $^m<r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11> # save the lot pushr $0x0fff movl r2,r9 # store table address away extzv $16,$16,r0,r2 # store "dstlen" in r2 beql 8b # perform extraordinary check if zero0: bsbw cvtxp_common # execute bulk as common code #+ # the common code routine returns here with the following relevant input. # # r0 number of digits remaining in source and destination strings # r1 address of last (highest addressed) byte in source string # r3 address of least significant digit and sign of output string # r9 address of 256-byte table (preserved across call) # r11 saved psw with condition codes to date (n=0,z,v,c=0) # # r4 is a scratch register # # the last byte of the input string is used as an index into the 256-byte # table that contains the last output byte. the contents of this byte are # tested for a legal decimal digit in its upper nibble and a legal sign # representation (10 through 15) in its low nibble. the z-bit is cleared # if the digit is 1 through 9 to cover the case that this is the first # nonzero digit in the input string. #- tstl r0 # check for no remaining input beql 7f # special case if zero length input # mark_point cvttp_accvio_b .text 2 .set table_size,table_size + 1 .word Lcvttp_accvio_b - module_base .text 3 .word cvttp_accvio - module_base .textLcvttp_accvio_b: movzbl (r1),r4 # get last input byte # mark_point cvttp_accvio_c .text 2 .set table_size,table_size + 1 .word Lcvttp_accvio_c - module_base .text 3 .word cvttp_accvio - module_base .textLcvttp_accvio_c: movzbl (r9)[r4],r4 # get associated output byte from table # mark_point cvttp_accvio_d .text 2 .set table_size,table_size + 1 .word Lcvttp_accvio_d - module_base .text 3 .word cvttp_accvio - module_base .textLcvttp_accvio_d: movb r4,(r3) # store in destination string extzv $4,$4,r4,r0 # get least significant digit beql 1f # skip clearing z-bit if zero cmpb r0,$9 # check for legal range bgtr 2f # reserved operand if 10 through 15 bicb2 $psl$m_z,r11 # clear saved z-bit1: bicb3 $0x0f0,r4,r0 # sign "digit" to r0 caseb r0,$10,$15-10 # dispatch on sign L4: .word 5f-L4 # 10 => + .word 3f-L4 # 11 => - .word 6f-L4 # 12 => + .word 4f-L4 # 13 => - .word 5f-L4 # 14 => + .word 5f-L4 # 15 => +2: brw decimal_roprand_no_pc # reserved operand if sign is 0 to 9 # a minus sign of 11 must be changed to 13, the preferred minus representation # mark_point cvttp_accvio_e .text 2 .set table_size,table_size + 1 .word Lcvttp_accvio_e - module_base .text 3 .word cvttp_accvio - module_base .textLcvttp_accvio_e:3: addb2 $2,(r3) # change 11 to 13, preferred minus sign4: bisb2 $psl$m_n,r11 # set n-bit because sign is "-" bbc $psl$v_z,r11,6f # all done unless negative zero bicb2 $psl$m_n,r11 # clear the saved n-bit bbs $psl$v_v,r11,6f # the output sign is ignored if overflow # if the sign character is a 10, 14, or 15, it must be changed to a 12, the # preferred plus sign before joining the exit code. # mark_point cvttp_accvio_f .text 2 .set table_size,table_size + 1 .word Lcvttp_accvio_f - module_base .text 3 .word cvttp_accvio - module_base .textLcvttp_accvio_f:5: insv $12,$0,$4,(r3) # store a 12 as the output sign6: jmp vax$decimal_exit # exit through common code # if the source string has zero length, the destination is set identically # to zero. the following instruction sequence assumes that the z-bit was # set in the initialization code for this routine. # mark_point cvttp_accvio_g .text 2 .set table_size,table_size + 1 .word Lcvttp_accvio_g - module_base .text 3 .word cvttp_accvio - module_base .textLcvttp_accvio_g:7: movb $12,(r3) # store "+" in output string jmp vax$decimal_exit # exit through common code #+ # functional description: #
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -