📄 vaxemulat.s
字号:
.word Lvax$cvttp_restart-fdp_case_table_base # cvttp entry .word Lvax$divp-fdp_case_table_base # divp entry .word 1f-fdp_case_table_base .word Lvax$cmpc3-fdp_case_table_base # cmpc3 entry .word Lvax$scanc-fdp_case_table_base # scanc entry .word Lvax$spanc-fdp_case_table_base # spanc entry .word 1f-fdp_case_table_base .word Lvax$cmpc5-fdp_case_table_base # cmpc5 entry .word Lvax$movtc-fdp_case_table_base # movtc entry .word Lvax$movtuc-fdp_case_table_base # movtuc entry .word 1f-fdp_case_table_base .word 1f-fdp_case_table_base .word 1f-fdp_case_table_base .word 1f-fdp_case_table_base .word Lvax$movp-fdp_case_table_base # movp entry .word Lvax$cmpp3-fdp_case_table_base # cmpp3 entry .word Lvax$cvtpl_restart-fdp_case_table_base # cmtpl entry .word Lvax$cmpp4-fdp_case_table_base # cmpp4 entry .word Lvax$editpc_restart-fdp_case_table_base # editpc entry .word Lvax$matchc-fdp_case_table_base # matchc entry .word Lvax$locc-fdp_case_table_base # locc entry .word Lvax$skpc-fdp_case_table_base # skpc entry # if we drop through the case dispatcher, then the fault was not caused # by executing one of the instructions supported by this emulator. the # exception will be passed to vms with the following stack. # # 00(sp) - signal array size (always 4) # 04(sp) - signal name (vax$_opcdec_fpd) # 08(sp) - opcode that is not supported # 12(sp) - pc of that opcode # 16(sp) - psl of exception # # (in the bootstrap emulator, we simply halt with the stack containing # these data.)1: addl2 $4,sp # discard return pc movl old_pc(sp),new_pc(sp) # use pc of opcode and not new pc moval new_pc(sp),sp # discard rest of stack pushl $vax$_opcdec_fpd # this is the signal name pushl $3 # signal array has four longwords jmp vax$reflect_to_vms # use common exit to vms #+ # functional description: # # the case tables for the two caseb instructions are built with the # macros that are invoked here. macros are used to guarantee that both # tables contain correct entries for a selected opcode at the same # offset. # # assumptions: # # the case_table_entry macro assumes that the names of the respective # case tables are case_table_base and fpd_case_table_base. # # notes: # # in the following lists, those fpd routines that do not have _fpd in # their names use the same jsb entry point for initial entry and after # restarting the instruction. in most of these cases, the register state # is the same for both starting and restarting. for the remaining cases, # there is not enough difference between the two cases to justify an # additional entry point. (see vax$movtc for an example of this latter # situation.) # # the fpd routines that include _restart in their names have to do a # certain amount of work to restore the intermediate state from the # canonical registers before they can resume instruction execution. #- # first generate table entries for the string instructions/* case_table_entry opcode=movtc,- routine=movtc,- fpd_routine=vax$movtc case_table_entry opcode=movtuc,- routine=movtuc,- fpd_routine=vax$movtuc case_table_entry opcode=cmpc3,- routine=cmpc3,- fpd_routine=vax$cmpc3,- boot_flag=boot case_table_entry opcode=cmpc5,- routine=cmpc5,- fpd_routine=vax$cmpc5,- boot_flag=boot case_table_entry opcode=locc,- routine=locc,- fpd_routine=vax$locc,- boot_flag=boot case_table_entry opcode=skpc,- routine=skpc,- fpd_routine=vax$skpc case_table_entry opcode=scanc,- routine=scanc,- fpd_routine=vax$scanc case_table_entry opcode=spanc,- routine=spanc,- fpd_routine=vax$spanc case_table_entry opcode=matchc,- routine=matchc,- fpd_routine=vax$matchc case_table_entry opcode=crc,- routine=crc,- fpd_routine=vax$crc # now generate table entries for the decimal instructions case_table_entry opcode=addp4,- routine=addp4,- fpd_routine=vax$addp4 case_table_entry opcode=addp6,- routine=addp6,- fpd_routine=vax$addp6 case_table_entry opcode=ashp,- routine=ashp,- fpd_routine=vax$ashp case_table_entry opcode=cmpp3,- routine=cmpp3,- fpd_routine=vax$cmpp3 case_table_entry opcode=cmpp4,- routine=cmpp4,- fpd_routine=vax$cmpp4 case_table_entry opcode=cvtlp,- routine=cvtlp,- fpd_routine=vax$cvtlp_restart case_table_entry opcode=cvtpl,- routine=cvtpl,- fpd_routine=vax$cvtpl_restart case_table_entry opcode=cvtps,- routine=cvtps,- fpd_routine=vax$cvtps case_table_entry opcode=cvtpt,- routine=cvtpt,- fpd_routine=vax$cvtpt_restart case_table_entry opcode=cvtsp,- routine=cvtsp,- fpd_routine=vax$cvtsp case_table_entry opcode=cvttp,- routine=cvttp,- fpd_routine=vax$cvttp_restart case_table_entry opcode=divp,- routine=divp,- fpd_routine=vax$divp case_table_entry opcode=movp,- routine=movp,- fpd_routine=vax$movp case_table_entry opcode=mulp,- routine=mulp,- fpd_routine=vax$mulp case_table_entry opcode=subp4,- routine=subp4,- fpd_routine=vax$subp4 case_table_entry opcode=subp6,- routine=subp6,- fpd_routine=vax$subp6_unpack # editpc always seems to find itself in last place case_table_entry opcode=editpc,- routine=editpc,- fpd_routine=vax$editpc_restart .restore # reset current location counter */ #++ # the instruction-specific routines do similar things. rather than clutter up # each routine with the same comments, we will describe the steps that each # routine takes in this section. # # the input parameters to each routine are identical. # # contents of exception stack # --------------------------- # # opcode(sp) - opcode of reserved instruction # old_pc(sp) - pc of reserved instruction # operand_1(sp) - first operand specifier # operand_2(sp) - second operand specifier # operand_3(sp) - third operand specifier # operand_4(sp) - fourth operand specifier # operand_5(sp) - fifth operand specifier # operand_6(sp) - sixth operand specifier # operand_7(sp) - seventh operand specifier (currently unused) # operand_8(sp) - eight operand specifier (currently unused) # new_pc(sp) - pc of instruction following reserved instruction # exception_psl(sp) - psl at time of exception # # the routine headers for the instruction-specific routines in this # module will list the input and output parameters in symbolic form # only. the vax$xxxxxx routines in other modules in the emulator contain # the exact meanings of the various operands (parameters) to the # routines. # # outline of execution: # # the operands are loaded into registers as required by the instruction # specific routines. routine headers for each routine contain detailed # descriptions. # # a routine of the form vax$xxxxxx (where xxxxxx is the instruction # name) is called to perform the actual work indicated by each # instruction. # # common exit code executes to allow the condition codes returned by the # vax$xxxxxx routines to be passed back to the code that generated the # original exception. # # notes: # # the following routines are constructed to be reasonably fast. in # particular, each instruction has its own separate routine, even though # several instructions differ only in the instruction-specific routine # to which final control is passed. rather than share this common code # at the expense of another dispatch on opcode, we shoose to duplicate # the common code. #-- #+ # input parameters: # # opcode(sp) # old_pc(sp) # operand_1(sp) - srclen.rw # operand_2(sp) - srcaddr.ab # operand_3(sp) - fill.rb # operand_4(sp) - tbladdr.ab # operand_5(sp) - dstlen.rw # operand_6(sp) - dstaddr.ab # operand_7(sp) # operand_8(sp) # new_pc(sp) # exception_psl(sp) # # output parameters: # # r0<15:0> - srclen.rw # r1 - srcaddr.ab # r2<7:0> - fill.rb # r3 - tbladdr.ab # r4<15:0> - dstlen.rw # r5 - dstaddr.ab # # implicit output: # # r0<31:16> - 0 # r2<31:8> - 0 # r4<31:16> - 0 #-Lmovtc: movzwl operand_1(sp),r0 # r0<15:0> <- srclen.rw movl operand_2(sp),r1 # r1 <- srcaddr.ab movzbl operand_3(sp),r2 # r2<7:0> <- fill.rb movl operand_4(sp),r3 # r3 <- tbladdr.ab movzwl operand_5(sp),r4 # r4<15:0> <- dstlen.rw movl operand_6(sp),r5 # r5 <- dstaddr.ab # now that the operands have been loaded, the only exception parameter # other than the pc/psl pair that needs to be saved is the old pc. however, # there is no reason why the state of the stack needs to be altered and we # save two instructions if we leave the stack alone. pushab vax$exit_emulator # store the return pc jmp vax$movtc # do the actual work #+ # input parameters: # # opcode(sp) # old_pc(sp) # operand_1(sp) - srclen.rw # operand_2(sp) - srcaddr.ab # operand_3(sp) - esc.rb # operand_4(sp) - tbladdr.ab # operand_5(sp) - dstlen.rw # operand_6(sp) - dstaddr.ab # operand_7(sp) # operand_8(sp) # new_pc(sp) # exception_psl(sp) # # output parameters: # # r0<15:0> - srclen.rw # r1 - srcaddr.ab # r2<7:0> - esc.rb # r3 - tbladdr.ab # r4<15:0> - dstlen.rw # r5 - dstaddr.ab # # implicit output: # # r0<31:16> - 0 # r2<31:8> - 0 # r4<31:16> - 0 #-Lmovtuc: movzwl operand_1(sp),r0 # r0<15:0> <- srclen.rw movl operand_2(sp),r1 # r1 <- srcaddr.ab movzbl operand_3(sp),r2 # r2<7:0> <- esc.rb movl operand_4(sp),r3 # r3 <- tbladdr.ab movzwl operand_5(sp),r4 # r4<15:0> <- dstlen.rw movl operand_6(sp),r5 # r5 <- dstaddr.ab # now that the operands have been loaded, the only exception parameter # other than the pc/psl pair that needs to be saved is the old pc. however, # there is no reason why the state of the stack needs to be altered and we # save two instructions if we leave the stack alone. pushab vax$exit_emulator # store the return pc jmp vax$movtuc # do the actual work #+ # input parameters: # # opcode(sp) # old_pc(sp) # operand_1(sp) - len.rw # operand_2(sp) - src1addr.ab # operand_3(sp) - src2addr.ab # operand_4(sp) # operand_5(sp) # operand_6(sp) # operand_7(sp) # operand_8(sp) # new_pc(sp) # exception_psl(sp) # # output parameters: # # r0<15:0> - len.rw # r1 - src1addr.ab # r3 - src2addr.ab # # implicit output: # # r0<31:16> - 0 # r2 - unpredictable #-Lcmpc3: movzwl operand_1(sp),r0 # r0<15:0> <- srclen.rw movl operand_2(sp),r1 # r1 <- src1addr.ab movl operand_3(sp),r3 # r3 <- src2addr.ab # now that the operands have been loaded, the only exception parameter # other than the pc/psl pair that needs to be saved is the old pc. however, # there is no reason why the state of the stack needs to be altered and we # save two instructions if we leave the stack alone. pushab vax$exit_emulator # store the return pc jmp vax$cmpc3 # do the actual work #+ # input parameters: # # opcode(sp) # old_pc(sp) # operand_1(sp) - src1len.rw # operand_2(sp) - src1addr.ab # operand_3(sp) - fill.rb # operand_4(sp) - src2len.rw # operand_5(sp) - src2addr.ab # operand_6(sp) # operand_7(sp) # operand_8(sp) # new_pc(sp) # exception_psl(sp) # # output parameters: # # r0<15:0> - srclen.rw # r0<23:16> - fill.rb # r1 - srcaddr.ab # r2<15:0> - src2len.rw # r3 - src2addr.ab # # implicit output: # # r0<31:24> - unpredictable # r2<31:16> - 0 #-Lcmpc5: rotl $16,operand_3(sp),r0 # r0<23:16> <- fill.rb movw operand_1(sp),r0 # r0<15:0> <- src1len.rw movl operand_2(sp),r1 # r1 <- src1addr.ab movzwl operand_4(sp),r2 # r2<15:0> <- src2len.rw movl operand_5(sp),r3 # r3 <sca- src2addr.ab # now that the operands have been loaded, the only exception parameter # other than the pc/psl pair that needs to be saved is the old pc. however, # there is no reason why the state of the stack needs to be altered and we # save two instructions if we leave the stack alone. pushab vax$exit_emulator # store the return pc jmp vax$cmpc5 # do the actual work #+ # input parameters: # # opcode(sp) # old_pc(sp) # operand_1(sp) - len.rw # operand_2(sp) - addr.ab # operand_3(sp) - tbladdr.ab # operand_4(sp) - mask.ab # operand_5(sp) # operand_6(sp) # operand_7(sp) # operand_8(sp) # new_pc(sp) # exception_psl(sp) # # output parameters: # # r0<15:0> - len.rw # r1 - addr.ab # r2<7:0> - mask.rb # r3 - tbladdr.ab # # implicit output: # # r0<31:16> - 0 # r2<31:8> - 0 #-Lscanc: movzwl operand_1(sp),r0 # r0<15:0> <- len.rw movl operand_2(sp),r1 # r1 <- addr.ab movl operand_3(sp),r3 # r3 <- tbladdr.ab movzbl operand_4(sp),r2 # r2<7:0> <- mask.ab # now that the operands have been loaded, the only exception parameter # other than the pc/psl pair that needs to be saved is the old pc. however, # there is no reason why the state of the stack needs to be altered and we # save two instructions if we leave the stack alone. pushab vax$exit_emulator # store the return pc jmp vax$scanc # do the actual work #+ # input parameters: # # opcode(sp) # old_pc(sp) # operand_1(sp) - len.rw # operand_2(sp) - addr.ab # operand_3(sp) - tbladdr.ab # operand_4(sp) - mask.ab # operand_5(sp) # operand_6(sp) # operand_7(sp) # operand_8(sp) # new_pc(sp) # exception_psl(sp) # # output parameters: # # r0<15:0> - len.rw # r1 - addr.ab # r2<7:0> - mask.rb # r3 - tbladdr.ab # # implicit output: # # r0<31:16> - 0 # r2<31:8> - 0 #-Lspanc: movzwl operand_1(sp),r0 # r0<15:0> <- len.rw movl operand_2(sp),r1 # r1 <- addr.ab movl operand_3(sp),r3 # r3 <- tbladdr.ab movzbl operand_4(sp),r2 # r2<7:0> <- mask.ab # now that the operands have been loaded, the only exception parameter # other than the pc/psl pair that needs to be saved is the old pc. however, # there is no reason why the state of the stack needs to be altered and we # save two instructions if we leave the stack alone. pushab vax$exit_emulator # store the return pc jmp vax$spanc # do the actual work
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -