📄 vaxemulat.s
字号:
/* @(#)vaxemulat.s 4.1 7/2/90 */#include "../machine/emul/vaxemul.h"#include "../machine/psl.h"#include "../machine/emul/vaxregdef.h"/************************************************************************ * * * Copyright (c) 1985 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * * Modification History * * jaw 14-jun-89 * bug in fpd reserve opcode. pushed one too many parameters. * * Stephen Reilly, 23-Dec-85 * 001- Correctly a case statement intialization problem that caused the * subp6 and cvtpt instructions not to work. * * Stephen Reilly, 20-Mar-84 * 000- This code is the modification of the VMS emulation codethat * was written by Larry Kenah. It has been modified to run * on Ultrix. * ***********************************************************************/ #++ # facility: # # vax-11 instruction emulator # # abstract: # # this is the main body of the instruction emulator that supports # the instructions that are not a part of the microvax architecture. # the current design calls for support of the string instructions # (including crc), the decimal instructions, and editpc. # # this routine performs the following steps. # # o moves operands from the exception stack to registers in an # instruction-specific manner # # o calls an instruction-specific subroutine to do the actual work # # if errors occur along the way, those errors are reflected to the # user as exceptions. # # environment: # # these routines run at any access mode, at any ipl, and are ast # reentrant. the routine starts execution in the access mode and # at the ipl at which the instruction executed. # # author: # # lawrence j. kenah # # creation date # # 17 august 1982 # # modified by: # # v01-011 ljk0041 Lawrence j. Kehah 16-jul-1984 # Clear FPD in saved psl at vax$emulate_fpd entry so that # next instruction can execute correctly # # v01-010 ljk0031 Lawrence j. Kenah 5-jul-1984 # Set r2 and r4 unconditionally to zero in editpc routine # to allow the storage of fpd flags and simliar date. # # v01-009 ljk0026 Lawrence j. kenah 19-mar-1984 # Perform final cleanup pass. eliminate xxx_unpack routine # references. add c-bit optimization to movp. # # v01-008 ljk0010 lawrence j. kenah 8-nov-1983 # eliminate code in exit_emulator path that unconditionally # clears the t-bit and conditionally sets the tp-bit. the # tp-bit is handled by the base hardware. # # v01-007 kdm0088 kathleen d. morse 20-oct-1983 # make branches to vax$reflect_to_vms into jumps, so that # the bootstrap emulator will link without truncation errors # until that routine is finished. # # v01-006 kdm0003 kathleen d. morse 18-apr-1983 # generate abbreviated vax$emulate_fpd for the bootstrap # emulator. # # v01-005 ljk0006 lawrence j. kenah 16-mar-1983 # generate case tables with macros. allow subset emulator # for bootstrap instruction emulation. # # v01-004 kdm0002 kathleen d. morse 16-mar-1983 # fix fourth and fifth operand fetches for subp6, addp6, # mulp and divp. # # v01-003 kdm0001 kathleen d. morse 04-mar-1983 # longword align the exception handler entry points. # # v01-002 ljk0005 lawrence j. kenah 15-nov-1982 # use hardware aids provided by microvax architecture revision. # exception is now reported in caller's mode. operands are parsed # and placed on the exception stack as exception parameters. # # v01-001 ljk0002 lawrence j. kenah 17-aug-1982 # original version using kernel mode exception through opcdec # exception vector. #-- # include files:/* $opdef # values for instruction opcodes * $psldef # define bit fields in psl * pack_def # stack usage when restarting instructions * stack_def # stack usage for original exception */ # macro definitions/* .macro init_case_table size,base,error_exit *base: * .rept size * .word error_exit-base * .endr * .endm init_case_table * .macro case_table_entry opcode,- * routine,- * fpd_routine,- * boot_flag * sign_extend op$_'opcode , ...opcode * ...offset = ...opcode - opcode_base * .if not_defined boot_switch * include_'opcode = 0 * .external vax$'opcode * .external fpd_routine * . = case_table_base + <2 * ...offset> * .word routine - case_table_base * . = fpd_case_table_base + <2 * ...offset> * .word fpd_routine - fpd_case_table_base * .if_false * .if identical <boot_flag>,boot * include_'opcode = 0 * .external vax$'opcode * . = case_table_base + <2 * ...offset> * .word routine - case_table_base * .endc * .endc * .endm case_table_entry */ # global and external declarations # external declarations for exception handling/* .if not_defined boot_switch * .external vax$al_delta_pc_table * .external vax$reflect_to_vms * .endc * .external vax$_opcdec, - * vax$_opcdec_fpd # psect declarations: #+ # functional description: # # there are two different entries into this module. when a reserved # instruction is first encountered, its operands are parsed by the # hardware (or microcode, if you will) and placed on the stack as # exception parameters. the code at address vax$emulate is then entered # through the ^xc8(scb) exception vector. that routine dispatches to an # instruction-specific routine called vax$xxxxxx (xxxxxx represents the # name of the reserved instruction) after placing the operands into # registers as required by vax$xxxxxx. # # if an exception occurred during instruction emulation such that a # reserved instruction executed again, this time with fpd set, then a # different exception path is taken. the stack has a different (smaller) # set of parameters for the fpd exception. a different # instruction-specific routine executes to unpack saved intermediate # state before resuming instruction emulation. # # the access mode and ipl are preserved across either exception. # # input parameters: # # 00(sp) - opcode of reserved instruction # 04(sp) - pc of reserved instruction (old pc) # 08(sp) - first operand specifier # 12(sp) - second operand specifier # 16(sp) - third operand specifier # 20(sp) - fourth operand specifier # 24(sp) - fifth operand specifier # 28(sp) - sixth operand specifier # 32(sp) - seventh operand specifier (currently unused) # 36(sp) - eight operand specifier (currently unused) # 40(sp) - pc of instruction following reserved instruction (new pc) # 44(sp) - psl at time of exception # # notes on input parameters: # # 1. the information that appears on the stack for each operand depends # on the nature of the operand. # # .rx - operand value # .ax - operand address # .wx - operand address (register destination is stored in one's # complement form. see vax$cvtpl for details.) # # 2. the old pc value is not used unless an exception such as an access # violation occurs and the instruction has to be backed up. # # 3. the seventh and eighth operands are not used for any existing vax-11 # instructions. those slots in the exception stach frame are reserved # for future expansion. # # 4. the two pc parameters and the psl are the only data that needs to # be preserved once the instruction-specific routine is entered. # # output parameters: # # the operands are moved from the stack to general registers in a way # that varies from instruction to instruction. control is transferred # to a specific routine for each opcode. # # notes: # # there are several tables in the emulator that use the opcode as an # index. we choose to interpret the opcode as a signed quantity because # this reduces the amount of wasted space in the tables. in either case, # there are 27 useful entries. # # unsigned opcode # # opcode_base = cvtps (value of 8) # opcode_max = cvtlp (value of f9) # # table_size = 241 decimal bytes # # signed opcode # # opcode_base = ashp (value of f8 or -8) # opcode_max = skpc (value of 3b) # # table_size = 67 decimal bytes # # the savings of more than 170 entries in each table justifies all # of the machinations that we go through to treat opcodes as signed # quantities. #- # because the assembler does not understand sign extension of byte and # word quantities, we must accomplish this sign extension with macros. the # assignment statements that appear as comments illustrate the sense of the # macro invocations that immediately follow. # opcode_max = op$_skpc # largest opcode in this emulator # sign_extend op$_skpc , opcode_max # we further restrict the table size and supported operations when we are # building the bootstrap subset of the emulator. we only allow certain string # instructions to contribute to the emulator./* .if defined boot_switch * # opcode_base = op$_cmpc3 # smallest (in signed sense) opcode * sign_extend op$_cmpc3 , opcode_base * .if_false *# opcode_base = op$_ashp # smallest (in signed sense) opcode * sign_extend op$_ashp , opcode_base * .endc */ # case_table_size = <opcode_max - opcode_base> + 1 # define table size# define case_table_size 0x44# define opcode_base 0x0f8 # define opcode_max-opcode_base 0x43 .globl vax$emulatevax$emulate: caseb opcode(sp),$opcode_base,$(0x43) # init_case_table case_table_size,case_table_base,10$case_table_base: .word Lashp-case_table_base # ashp entry .word Lcvtlp-case_table_base # cvtlp entry .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word Lcvtps-case_table_base # cvtps entry .word Lcvtsp-case_table_base # cvtps entry .word 1f-case_table_base .word Lcrc-case_table_base # crc entry .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word Laddp4-case_table_base # addp4 entry .word Laddp6-case_table_base # addp4 entry .word Lsubp4-case_table_base # subp4 entry .word Lsubp6-case_table_base # 001 subp6 entry .word Lcvtpt-case_table_base # 001 cvtpt entry .word Lmulp-case_table_base # mulp entry .word Lcvttp-case_table_base # cvttp entry .word Ldivp-case_table_base # divp entry .word 1f-case_table_base .word Lcmpc3-case_table_base # cmpc3 entry .word Lscanc-case_table_base # scanc entry .word Lspanc-case_table_base # spanc entry .word 1f-case_table_base .word Lcmpc5-case_table_base # cmpc5 entry .word Lmovtc-case_table_base # movtc entry .word Lmovtuc-case_table_base # movtuc entry .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word 1f-case_table_base .word Lmovp-case_table_base # movp entry .word Lcmpp3-case_table_base # cmpp3 entry .word Lcvtpl-case_table_base # cvtpl entry .word Lcmpp4-case_table_base # cmpp4 entry .word Leditpc-case_table_base # editpc entry .word Lmatchc-case_table_base # matchc entry .word Llocc-case_table_base # locc entry .word Lskpc-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. such # exceptions will simply be passed through to vms. (in the bootstrap emulator, # there is no operating system to reflect the exception. we simply halt.)1: pushl $vax$_opcdec # this is the signal name pushl $13 # signal array has 13 longwords jmp vax$reflect_to_vms # use common exit to vms #+ # functional description: # # this routine is entered through the ^xcc(scb) exception vector when an # instruction that is not a part of the microvax architecture executes # and the fpd bit is set in the psl. the software state that was # preserved by each instruction must be restored and instruction # execution resumed. access mode and ipl are preserved across the # exception occurrence. # # before the various vax$xxxxxx (or vax$xxxxxx_restart) routines regain # control, this dispatcher must retrieve the delta pc from wherever # it was stored and place the stack in the same state that it is in # when the normal (fpd bit not set) instruction dispatcher passes # control to the various vax$xxxxxx routines. the pictures below explain # this. # # input parameters: # # 00(sp) - pc of reserved instruction # 04(sp) - psl at time of exception # # output parameters: # # the following picture shows the state of the stack after the dispatcher # has executed its preliminary code but before control is passed back to # instruction-specific execution. note that this routine makes the # stack look like it does when a reserved instruction executes and fpd # is not yet set. this is done to make the exception exit code independent # of whether a different exception exception occurred while the emulator # was running. # # 00(sp) - return pc (address of exit routine in this module) # 04(sp) - unused placeholder (opcode) # 08(sp) - pc of reserved instruction (old pc) # 12(sp) - unused placeholder (operand_1) # 16(sp) - unused placeholder (operand_2) # 20(sp) - unused placeholder (operand_3) # 24(sp) - unused placeholder (operand_4) # 28(sp) - unused placeholder (operand_5) # 32(sp) - unused placeholder (operand_6) # 36(sp) - unused placeholder (operand_7) # 40(sp) - unused placeholder (operand_8) # 44(sp) - pc of instruction following reserved instruction (new pc) # 48(sp) - psl at time of exception # # before this routine dispatches to opcode-specific code, it calculates # the pc of the next instruction based on the pc of the reserved # instruction and the delta-pc quantity that was stored as part of the # instruction's intermediate state. note that the delta pc quantity # # delta pc = new pc - old pc # # is stored in the upper bytes of one of the general registers, usually # bits <31:24> of r0 or r2. the registers r0 through r3 are stored on # the stack (in the space used for the first four operands when the # reserved instruction is first encountered) so that the same offsets # that were used to store the delta-pc can be used to retrieve it. #- .globl vax$emulate_fpdvax$emulate_fpd: bbcc $psl$v_fpd,4(sp),5f # clear fpd in exception psl5: subl2 $new_pc,sp # create extra stack space movl new_pc(sp),old_pc(sp) # make second copy of old pc movq r0,operand_1(sp) # save r0 and r1 in some extra space movq r2,operand_3(sp) # do the same for r2 and r3 cvtbl *old_pc(sp),r0 # get opcode from instruction stream # movzbl vax$al_delta_pc_table[r0],r1 # get offset to byte with delta-pc subl3 $0xf8,$vax$al_delta_pc_table,r1 # adjust address for table movzbl (r1)[r0],r1 # get offset to byte with delta-pc movzbl operand_1(sp)[r1],r1 # get delta-pc addl2 r1,new_pc(sp) # convert old pc to new pc movl r0,opcode(sp) # store opcode in other than a register movq operand_1(sp),r0 # restore r0 and r1 # (r2 and r3 were not changed) pushab vax$exit_emulator # create return pc to make case like bsb caseb (opcode+4)(sp),$opcode_base,$(0x43) # init_case_table case_table_size,fpd_case_table_base,10$fdp_case_table_base: .word Lvax$ashp-fdp_case_table_base # ashp entry .word Lvax$cvtlp_restart-fdp_case_table_base # cvtlp 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 1f-fdp_case_table_base .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 1f-fdp_case_table_base .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 1f-fdp_case_table_base .word Lvax$cvtsp-fdp_case_table_base # cvtsp entry .word 1f-fdp_case_table_base .word Lvax$crc-fdp_case_table_base # crc 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 1f-fdp_case_table_base .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 1f-fdp_case_table_base .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 1f-fdp_case_table_base .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 1f-fdp_case_table_base .word Lvax$addp4-fdp_case_table_base # addp4 entry .word Lvax$addp6-fdp_case_table_base # addp6 entry .word Lvax$subp4-fdp_case_table_base # subp4 entry .word Lvax$subp6-fdp_case_table_base # subp6 entry .word Lvax$cvtpt_restart-fdp_case_table_base # cvtpt entry .word Lvax$mulp-fdp_case_table_base # mulp entry
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -