📄 vaxdeciml.s
字号:
# (The comment in the next four lines is preserved for its historical # content.) # # finally, there is no explicit test for the end of the string. the # routine assumes that the low order byte, the one that contains the # sign, is not equal to zero. This can cause rather strange behavior # ( read UNPREDICTABLE ) for poorly formed decimal strings. # # (The following comment describes the revised treatment of certain # froms of illegal packed decimal strings.) # # although an end-of-string test is not required for well formed packed # decimal strings, it turns out that some layered products create packed # decimal data on the fly consisting of so many bytes containing zero. # in other words, the sign nibble contains zero. Previous # implementations of packed decimal zero. # # The bleq 30$ instructions that exist in the following two loops detect # these strings and treat them as strings with a digit count of one. # (The digit itself is zero.) Whether this string is treated as +0 or # -0 is determine by the caller of this routine. That much # unpredictable behavior remains in the treatment of these illegal # strings. # # input and output parameters: # # there are really two identical but separate routines here. one is # used when the input decimal string descriptor is in r0 and r1. the # other is used when r2 and r3 describe the decimal string. note that # we have already performed the reserved operand checks so that r0 (or # r2) is guaranteed lequ 31. # # if the high order digit of an initially even length string is zero, # then the digit count (r0 or r2) is reduced by one. for all other # cases, the digit count is reduced by two as an entire byte of zeros # is skipped. # # input parameters (for entry at decimal$strip_zeros_r0_r1): # # r0<4:0> - len.rw length of input decimal string # r1 - addr.ab address of input packed decimal string # # output parameters (for entry at decimal$strip_zeros_r0_r1): # # r1 advanced to first nonzero byte in string # r0 reduced accordingly (note that if r0 is altered at all, # then r0 is always odd on exit.) # # input parameters (for entry at decimal$strip_zeros_r2_r3): # # r2<4:0> - len.rw length of input decimal string # r3 - addr.ab address of input packed decimal string # # output parameters (for entry at decimal$strip_zeros_r2_r3): # # r3 advanced to first nonzero byte in string # r2 reduced accordingly (note that if r2 is altered at all, # then r2 is always odd on exit.) # note: # # although these routines can generate access violations, there is no # mark_point here because these routines can be called from other # modules (and are not called by the routines in this module). the pc # check is made based on the return pc from this subroutine rather than # on the pc of the instruction that accessed the inaccessible address. #- # this routine is used when the decimal string is described by r0 (digit # count) and r1 (string address). .globl decimal$strip_zeros_r0_r1decimal$strip_zeros_r0_r1: blbs r0,1f # skip first check if r0 starts out odd tstb (r1)+ # is first byte zero? bneq 2f # all done if not decl r0 # skip leading zero digit (r0 nequ 0)1: tstb (r1)+ # is next byte zero? bneq 2f # all done if not subl2 $2,r0 # decrease digit count by 2 bleq 3f # We passed the end of the string brb 1b # ... and charge on2: decl r1 # back up r1 to last nonzero byte rsb3: addl2 $2,r0 # undo last r0 modification brb 2b # ... and take common exit # this routine is used when the decimal string is described by r2 (digit # count) and r3 (string address). .globl decimal$strip_zeros_r2_r3decimal$strip_zeros_r2_r3: blbs r2,1f # skip first check if r2 starts out odd tstb (r3)+ # is first byte zero? bneq 2f # all done if not decl r2 # skip leading zero digit (r2 nequ 0)1: tstb (r3)+ # is next byte zero? bneq 2f # all done if not subl2 $2,r2 # decrease digit count by 2 bleq 3f # We passed the end of the string brb 1b # ... and charge on2: decl r3 # back up r3 to last nonzero byte rsb3: addl2 $2,r2 # undo last r2 modification brb 2b # ... and take common exit # #- # 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. because # all of the routines in this module check for legal digit counts # before saving any registers, this routine simply passes control # to vax$roprand. # # input parameters: # # 0(sp) - return pc from vax$xxxxxx routine # # output parameters: # # 0(sp) - offset in packed register array to delta pc byte # 4(sp) - return pc from vax$xxxxxx routine # # implicit output: # # this routine passes control to vax$roprand where further # exception processing takes place. #-decimal_roprand: pushl $movp_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 cmpp3, cmpp4 or movp. # # 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 #-decimal_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 trivial to back out cmpp3 and cmpp4 because neither of these # routines uses any stack space (other than saved register space). the # only reason that this routine does not use the common # vax$decimal_accvio exit path is that fewer registers are saved by # these two routines than are saved by the typical packed decimal # emulation routine. # # input parameters: # # r0 - address of top of stack when access violation occurred # # 00(r0) - saved r0 on entry to vax$cmppx # 04(r0) - saved r1 # 08(r0) - saved r2 # 12(r0) - saved r3 # 16(r0) - saved r4 # 20(r0) - saved r5 # 24(r0) - saved r10 # 28(r0) - return pc from vax$cmppx routine # # 00(sp) - saved r0 (restored by vax$handler) # 04(sp) - saved r1 # 08(sp) - saved r2 # 12(sp) - saved r3 # # output parameters: # # r0 is advanced over saved register array as the registers are restored. # r0 ends up pointing at the return pc. # # r1 contains the value of delta pc for all of the routines that # use this common code path. the fpd and accvio bits are both set # in r1. # # 00(r0) - return pc from vax$cmppx routine # # 00(sp) - value of r0 on entry to vax$cmppx # 04(sp) - value of r1 on entry to vax$cmppx # 08(sp) - value of r2 on entry to vax$cmppx # 12(sp) - value of r3 on entry to vax$cmppx # # r4, r5, and r10 are restored to their values on entry to vax$cmppx. #- .globl cmppx_accviocmppx_accvio: movq (r0)+,pack_l_saved_r0(sp) # "restore" r0 and r1 movq (r0)+,pack_l_saved_r2(sp) # "restore" r2 and r3 movq (r0)+,r4 # really restore r4 and r5 # the last two instructions can be shared with movp_accvio, provided that # the following assumptions hold. brb 1f # share remainder with movp_accvio #+ # functional description: # # it is almost too trivial to back out vax$movp to its starting point. # if time permits, we will add restart points to this routine. this will # illustrate how one could go about adding restart capability to other # decimal instructions, allowing the routines to pick up where they left # off if an access violation occurs. this will also point out the # magnitude of the task by showing the amount of intermediate state that # must be saved for even so simple a routine as vax$movp. # # the vax$movp routine, like vax$cmppx, uses no stack space. it also # saves only a subset of the registers and so a special exit path must # be taken to vax$reflect_fault. # # input parameters: # # r0 - address of top of stack when access violation occurred # # 00(r0) - saved r0 on entry to vax$movp # 04(r0) - saved r1 # 08(r0) - saved r2 # 12(r0) - saved r3 # 16(r0) - saved r10 # 20(r0) - return pc from vax$movp routine # # 00(sp) - saved r0 (restored by vax$handler) # 04(sp) - saved r1 # 08(sp) - saved r2 # 12(sp) - saved r3 # # output parameters: # # r0 is advanced over saved register array as the registers are restored. # r0 ends up pointing at the return pc. # # r1 contains the value of delta pc for all of the routines that # use this common code path. the fpd and accvio bits are both set # in r1. # # 00(r0) - return pc from vax$movp routine # # 00(sp) - value of r0 on entry to vax$movp # 04(sp) - value of r1 on entry to vax$movp # 08(sp) - value of r2 on entry to vax$movp # 12(sp) - value of r3 on entry to vax$movp # # r10 is restored to its value on entry to vax$movp. #- .globl movp_accviomovp_accvio: movq (r0)+,pack_l_saved_r0(sp) # "restore" r0 and r1 movq (r0)+,pack_l_saved_r2(sp) # "restore" r2 and r3 bisb3 $movp_m_fpd,-8(r0),movp_b_state(sp) # preserved saved c-bit1: movl (r0)+,r10 # really restore r10 # movl $<movp_b_delta_pc!- # indicate offset for delta pc # pack_m_fpd!- # fpd bit should be set # pack_m_accvio>,r1 # this is an access violation movl $(movp_b_delta_pc|pack_m_fpd|pack_m_accvio),r1 jmp vax$reflect_fault # continue exception handling
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -