home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / callmon / src / callmon$alphacode.c < prev    next >
C/C++ Source or Header  |  1996-08-06  |  34KB  |  922 lines

  1. /*  CALLMON - A Call Monitor for OpenVMS Alpha
  2.  *
  3.  *  File:     CALLMON$ALPHACODE.C
  4.  *  Author:   Thierry Lelegard
  5.  *  Version:  1.0
  6.  *  Date:     24-JUL-1996
  7.  *
  8.  *  Abstract: This module contains utility routines to analyze
  9.  *            Alpha machine code.
  10.  */
  11.  
  12.  
  13. #include "callmon$private.h"
  14.  
  15.  
  16. /*
  17.  *  The Alpha architecture introduced a number of new instructions
  18.  *  (like byte access instructions) which not defined in older
  19.  *  header files.
  20.  */
  21.  
  22. #ifndef EVX$OPC_STB
  23.  
  24. #define EVX$OPC_LDBU       10
  25. #define EVX$OPC_LDWU       12
  26. #define EVX$OPC_STW        13
  27. #define EVX$OPC_STB        14
  28. #define EVX$OPC_EXTI       28
  29.  
  30. #define EVX$EXTI_SEXTB      0
  31. #define EVX$EXTI_SEXTW      1
  32.  
  33. #define EVX$LOGI_AMASK     97
  34. #define EVX$LOGI_IMPLVER  108
  35.  
  36. #endif
  37.  
  38.  
  39. /*******************************************************************************
  40.  *
  41.  *  Description of Alpha instructions.
  42.  */
  43.  
  44. typedef enum {
  45.     IT_RESERVED, IT_PAL, IT_SYNC, IT_OPER, IT_MEMORY, IT_JUMP, IT_BRANCH,
  46.     IT_FP, IT_FPAUX
  47. } inst_type_t;
  48.  
  49. typedef struct {
  50.     int   function;
  51.     char* name;
  52. } inst_name_t;
  53.  
  54. typedef struct {
  55.     int    function;
  56.     char*  name;
  57.     uint32 read_regs;
  58.     uint32 write_regs;
  59. } inst_pal_t;
  60.  
  61. typedef struct {
  62.     int   function;
  63.     char* name;
  64.     int   use_ra;
  65.     int   use_rb;
  66. } inst_sync_t;
  67.  
  68. typedef struct {
  69.     int   function;
  70.     char* name;
  71.     int   use_fa;
  72. } inst_fpaux_t;
  73.  
  74. typedef struct {
  75.     int          opcode;
  76.     char*        name;
  77.     inst_type_t  type;
  78.     int          float_inst;
  79.     int          is_store;
  80.     void*        name_list;
  81. } inst_desc_t;
  82.  
  83. static char* fp_inst_name [] = {
  84.     "ADD%s",   "SUB%s",   "MUL%s",   "DIV%s",
  85.     "CMP%sUN", "CMP%sEQ", "CMP%sLT", "CMP%sLE",
  86.     "fp",      "fp",      "fp",      "fp",
  87.     "CVT%s%s", "CVT%s%s", "CVT%s%s", "CVT%s%s",
  88. };
  89.  
  90. static char* fp_ieee_name [] = {"S", "", "T", "Q"};
  91. static char* fp_dec_name [] = {"F", "D", "G", "Q"};
  92. static char* fp_trap_name [] = {"", "U", "2", "3", "S", "SU", "6", "SUI"};
  93. static char* fp_round_name [] = {"C", "M", "", "D"};
  94.  
  95. static inst_fpaux_t fpaux_opcodes [] = {
  96.     {EVX$FPAUX_CPYSEE,   "CPYSEE",   1},
  97.     {EVX$FPAUX_CPYS,     "CPYS",     1},
  98.     {EVX$FPAUX_CPYSN,    "CPYSN",    1},
  99.     {EVX$FPAUX_CPYSE,    "CPYSE",    1},
  100.     {EVX$FPAUX_WR_FPCTL, "MT_FPCR",  1},
  101.     {EVX$FPAUX_RD_FPCTL, "MF_FPCR",  1},
  102.     {EVX$FPAUX_FCMOVEQ,  "FCMOVEQ",  1},
  103.     {EVX$FPAUX_FCMOVNE,  "FCMOVNE",  1},
  104.     {EVX$FPAUX_FCMOVLT,  "FCMOVLT",  1},
  105.     {EVX$FPAUX_FCMOVGE,  "FCMOVGE",  1},
  106.     {EVX$FPAUX_FCMOVLE,  "FCMOVLE",  1},
  107.     {EVX$FPAUX_FCMOVGT,  "FCMOVGT",  1},
  108.     {EVX$FPAUX_CVTLQ,    "CVTLQ",    0},
  109.     {EVX$FPAUX_CVTQL,    "CVTQL",    0},
  110.     {EVX$FPAUX_CVTQLV,   "CVTQL/V",  0},
  111.     {EVX$FPAUX_CVTQLSV , "CVTQL/SV", 0},
  112.     {0,                  NULL,       0}
  113. };
  114.  
  115. static inst_sync_t sync_opcodes [] = {
  116.     {EVX$SYNC_TRAPB,   "TRAPB",   0, 0},
  117.     {EVX$SYNC_EXCB,    "EXCB",    0, 0},
  118.     {EVX$SYNC_MB,      "MB",      0, 0},
  119.     {EVX$SYNC_WMB,     "WMB",     0, 0},
  120.     {EVX$SYNC_MB8,     "MB8",     0, 0},
  121.     {EVX$SYNC_MBC,     "MBC",     0, 0},
  122.     {EVX$SYNC_FETCH,   "FETCH",   0, 1},
  123.     {EVX$SYNC_FETCH_M, "FETCH_M", 0, 1},
  124.     {EVX$SYNC_RCC,     "RCC",     1, 0},
  125.     {EVX$SYNC_RC,      "RC",      1, 0},
  126.     {EVX$SYNC_RS,      "RS",      1, 0},
  127.     {0,                NULL,      0, 0}
  128. };
  129.  
  130. static inst_name_t addi_names [] = {
  131.     {EVX$ADDI_ADDL,     "ADDL"},
  132.     {EVX$ADDI_ADDLV,    "ADDL/V"},
  133.     {EVX$ADDI_ADDQ,     "ADDQ"},
  134.     {EVX$ADDI_ADDQV,    "ADDQ/V"},
  135.     {EVX$ADDI_S4ADDL,   "S4ADDL"},
  136.     {EVX$ADDI_S4ADDQ,   "S4ADDQ"},
  137.     {EVX$ADDI_S8ADDL,   "S8ADDL"},
  138.     {EVX$ADDI_S8ADDQ,   "S8ADDQ"},
  139.     {EVX$ADDI_S4SUBL,   "S4SUBL"},
  140.     {EVX$ADDI_S4SUBQ,   "S4SUBQ"},
  141.     {EVX$ADDI_S8SUBL,   "S8SUBL"},
  142.     {EVX$ADDI_S8SUBQ,   "S8SUBQ"},
  143.     {EVX$ADDI_SUBL,     "SUBL"},
  144.     {EVX$ADDI_SUBLV,    "SUBL/V"},
  145.     {EVX$ADDI_SUBQ,     "SUBQ"},
  146.     {EVX$ADDI_SUBQV,    "SUBQ/V"},
  147.     {EVX$ADDI_CMPEQ,    "CMPEQ"},
  148.     {EVX$ADDI_CMPLT,    "CMPLT"},
  149.     {EVX$ADDI_CMPLE,    "CMPLE"},
  150.     {EVX$ADDI_CMPULT,   "CMPULT"},
  151.     {EVX$ADDI_CMPULE,   "CMPULE"},
  152.     {EVX$ADDI_CMPBGE,   "CMPBGE"},
  153.     {0,                 NULL}
  154. };
  155.  
  156. static inst_name_t exti_names [] = {
  157.     {EVX$EXTI_SEXTB, "SEXTB"},
  158.     {EVX$EXTI_SEXTW, "SEXTW"},
  159.     {0,              NULL}
  160. };
  161.  
  162. static inst_name_t logi_names [] = {
  163.     {EVX$LOGI_AND,     "AND"},
  164.     {EVX$LOGI_BIC,     "BIC"},
  165.     {EVX$LOGI_CMOVEQ,  "CMOVEQ"},
  166.     {EVX$LOGI_CMOVNE,  "CMOVNE"},
  167.     {EVX$LOGI_CMOVLBS, "CMOVLBS"},
  168.     {EVX$LOGI_BIS,     "BIS"},
  169.     {EVX$LOGI_ORNOT,   "ORNOT"},
  170.     {EVX$LOGI_CMOVLT,  "CMOVLT"},
  171.     {EVX$LOGI_CMOVGE,  "CMOVGE"},
  172.     {EVX$LOGI_CMOVLBC, "CMOVLBC"},
  173.     {EVX$LOGI_XOR,     "XOR"},
  174.     {EVX$LOGI_EQV,     "EQV"},
  175.     {EVX$LOGI_CMOVLE,  "CMOVLE"},
  176.     {EVX$LOGI_CMOVGT,  "CMOVGT"},
  177.     {EVX$LOGI_AMASK,   "AMASK"},
  178.     {EVX$LOGI_IMPLVER, "IMPLVER"},
  179.     {0,                NULL}
  180. };
  181.  
  182. static inst_name_t shfi_names [] = {
  183.     {EVX$SHFI_SLL,    "SLL"},
  184.     {EVX$SHFI_SRA,    "SRA"},
  185.     {EVX$SHFI_SRL,    "SRL"},
  186.     {EVX$SHFI_EXTBL,  "EXTBL"},
  187.     {EVX$SHFI_EXTWL,  "EXTWL"},
  188.     {EVX$SHFI_EXTLL,  "EXTLL"},
  189.     {EVX$SHFI_EXTQL,  "EXTQL"},
  190.     {EVX$SHFI_EXTWH,  "EXTWH"},
  191.     {EVX$SHFI_EXTLH,  "EXTLH"},
  192.     {EVX$SHFI_EXTQH,  "EXTQH"},
  193.     {EVX$SHFI_INSBL,  "INSBL"},
  194.     {EVX$SHFI_INSWL,  "INSWL"},
  195.     {EVX$SHFI_INSLL,  "INSLL"},
  196.     {EVX$SHFI_INSQL,  "INSQL"},
  197.     {EVX$SHFI_INSWH,  "INSWH"},
  198.     {EVX$SHFI_INSLH,  "INSLH"},
  199.     {EVX$SHFI_INSQH,  "INSQH"},
  200.     {EVX$SHFI_MSKBL,  "MSKBL"},
  201.     {EVX$SHFI_MSKWL,  "MSKWL"},
  202.     {EVX$SHFI_MSKLL,  "MSKLL"},
  203.     {EVX$SHFI_MSKQL,  "MSKQL"},
  204.     {EVX$SHFI_MSKWH,  "MSKWH"},
  205.     {EVX$SHFI_MSKLH,  "MSKLH"},
  206.     {EVX$SHFI_MSKQH,  "MSKQH"},
  207.     {EVX$SHFI_ZAP,    "ZAP"},
  208.     {EVX$SHFI_ZAPNOT, "ZAPNOT"},
  209.     {0,               NULL}
  210. };
  211.  
  212. static inst_name_t muli_names [] = {
  213.     {EVX$MULI_MULL,  "MULL"},
  214.     {EVX$MULI_MULQV, "MULQ/V"},
  215.     {EVX$MULI_MULLV, "MULL/V"},
  216.     {EVX$MULI_UMULH, "UMULH"},
  217.     {EVX$MULI_MULQ,  "MULQ"},
  218.     {0,              NULL}
  219. };
  220.  
  221. static inst_pal_t pal_names [] = {
  222.     {EVX$PAL_HALT,           "HALT",         0x00000000, 0x00000000},
  223.     {EVX$PAL_CFLUSH,         "CFLUSH",       0x00000000, 0x00000000},
  224.     {EVX$PAL_DRAINA,         "DRAINA",       0x00000000, 0x00000000},
  225.     {EVX$PAL_LDQP,           "LDQP",         0x00010000, 0x00000001},
  226.     {EVX$PAL_STQP,           "STQP",         0x00030000, 0x00000000},
  227.     {EVX$PAL_SWPCTX,         "SWPCTX",       0x00010000, 0x00000000},
  228.     {EVX$PAL_MFPR_ASN,       "MFPR_ASN"  ,   0x00000000, 0x00030003},
  229.     {EVX$PAL_MTPR_ASTEN,     "MTPR_ASTEN",   0x00030000, 0x00030003},
  230.     {EVX$PAL_MTPR_ASTSR,     "MTPR_ASTSR",   0x00030000, 0x00030003},
  231.     {EVX$PAL_CSERVE,         "CSERVE",       0x00000000, 0x00000000},
  232.     {EVX$PAL_SWPPAL,         "SWPPAL",       0x003F0000, 0x003F0001},
  233.     {EVX$PAL_MFPR_FEN,       "MFPR_FEN",     0x00000000, 0x00030003},
  234.     {EVX$PAL_MTPR_FEN,       "MTPR_FEN",     0x00030000, 0x00030003},
  235.     {EVX$PAL_MTPR_IPIR,      "MTPR_IPIR" ,   0x00030000, 0x00030003},
  236.     {EVX$PAL_MFPR_IPL,       "MFPR_IPL",     0x00000000, 0x00030003},
  237.     {EVX$PAL_MTPR_IPL,       "MTPR_IPL",     0x00030000, 0x00030003},
  238.     {EVX$PAL_MFPR_MCES,      "MFPR_MCES",    0x00000000, 0x00030003},
  239.     {EVX$PAL_MTPR_MCES,      "MTPR_MCES",    0x00030000, 0x00030003},
  240.     {EVX$PAL_MFPR_PCBB,      "MFPR_PCBB",    0x00000000, 0x00030003},
  241.     {EVX$PAL_MFPR_PRBR,      "MFPR_PRBR",    0x00000000, 0x00030003},
  242.     {EVX$PAL_MTPR_PRBR,      "MTPR_PRBR",    0x00030000, 0x00030003},
  243.     {EVX$PAL_MFPR_PTBR,      "MFPR_PTBR",    0x00000000, 0x00030003},
  244.     {EVX$PAL_MFPR_SCBB,      "MFPR_SCBB",    0x00000000, 0x00030003},
  245.     {EVX$PAL_MTPR_SCBB,      "MTPR_SCBB",    0x00030000, 0x00030003},
  246.     {EVX$PAL_MTPR_SIRR,      "MTPR_SIRR",    0x00030000, 0x00030003},
  247.     {EVX$PAL_MFPR_SISR,      "MFPR_SISR",    0x00000000, 0x00030003},
  248.     {EVX$PAL_MFPR_TBCHK,     "MFPR_TBCHK",   0x00000000, 0x00030003},
  249.     {EVX$PAL_MTPR_TBIA,      "MTPR_TBIA",    0x00030000, 0x00030003},
  250.     {EVX$PAL_MTPR_TBIAP,     "MTPR_TBIAP",   0x00030000, 0x00030003},
  251.     {EVX$PAL_MTPR_TBIS,      "MTPR_TBIS",    0x00030000, 0x00030003},
  252.     {EVX$PAL_MFPR_ESP,       "MFPR_ESP",     0x00000000, 0x00030003},
  253.     {EVX$PAL_MTPR_ESP,       "MTPR_ESP",     0x00030000, 0x00030003},
  254.     {EVX$PAL_MFPR_SSP,       "MFPR_SSP",     0x00000000, 0x00030003},
  255.     {EVX$PAL_MTPR_SSP,       "MTPR_SSP",     0x00030000, 0x00030003},
  256.     {EVX$PAL_MFPR_USP,       "MFPR_USP",     0x00000000, 0x00030003},
  257.     {EVX$PAL_MTPR_USP,       "MTPR_USP",     0x00030000, 0x00030003},
  258.     {EVX$PAL_MTPR_TBISD,     "MTPR_TBISD",   0x00030000, 0x00030003},
  259.     {EVX$PAL_MTPR_TBISI,     "MTPR_TBISI",   0x00030000, 0x00030003},
  260.     {EVX$PAL_MFPR_ASTEN,     "MFPR_ASTEN",   0x00000000, 0x00030003},
  261.     {EVX$PAL_MFPR_ASTSR,     "MFPR_ASTSR",   0x00000000, 0x00030003},
  262.     {EVX$PAL_VMS2OSF,        "VMS2OSF",      0x00000000, 0x00000000},
  263.     {EVX$PAL_MFPR_VPTBASE,   "MFPR_VPTBASE", 0x00000000, 0x00030003},
  264.     {EVX$PAL_MTPR_VPTBASE,   "MTPR_VPTBASE", 0x00030000, 0x00030003},
  265.     {EVX$PAL_MTPR_PERFMON,   "MTPR_PERFMON", 0x00030000, 0x00030003},
  266.     {EVX$PAL_WRVPTPTR,       "WRVPTPTR",     0x00000000, 0x00000000},
  267.     {EVX$PAL_MTPR_DATAFX,    "MTPR_DATAFX",  0x00030000, 0x00030003},
  268.     {EVX$PAL_OSFSWPCTX,      "OSFSWPCTX",    0x00000000, 0x00000000},
  269.     {EVX$PAL_WRVAL,          "WRVAL",        0x00000000, 0x00000000},
  270.     {EVX$PAL_RDVAL,          "RDVAL",        0x00000000, 0x00000000},
  271.     {EVX$PAL_TBI,            "TBI",          0x00000000, 0x00000000},
  272.     {EVX$PAL_WRENT,          "WRENT",        0x00000000, 0x00000000},
  273.     {EVX$PAL_SWPIPL,         "SWPIPL",       0x00000000, 0x00000000},
  274.     {EVX$PAL_RDPS,           "RDPS",         0x00000000, 0x00000000},
  275.     {EVX$PAL_WRKGP,          "WRKGP",        0x00000000, 0x00000000},
  276.     {EVX$PAL_WRUSP,          "WRUSP",        0x00000000, 0x00000000},
  277.     {EVX$PAL_WRPERFMON,      "WRPERFMON",    0x00000000, 0x00000000},
  278.     {EVX$PAL_RDUSP,          "RDUSP",        0x00000000, 0x00000000},
  279.     {EVX$PAL_WHAMI,          "WHAMI",        0x00000000, 0x00000000},
  280.     {EVX$PAL_RETSYS,         "RETSYS",       0x00000000, 0x00000000},
  281.     {EVX$PAL_MFPR_WHAMI,     "MFPR_WHAMI",   0x00000000, 0x00030003},
  282.     {EVX$PAL_RESERVED_GETSS, "GETSS",        0x00000000, 0x00000000},
  283.     {EVX$PAL_RESERVED_PUTSS, "PUTSS",        0x00000000, 0x00000000},
  284.     {EVX$PAL_RESERVED_RLS1,  "RLS1",         0x00000000, 0x00000000},
  285.     {EVX$PAL_RESERVED_RLS2,  "RLS2",         0x00000000, 0x00000000},
  286.     {EVX$PAL_RESERVED_DVT1,  "DVT1",         0x00000000, 0x00000000},
  287.     {EVX$PAL_BPT,            "BPT",          0x00000000, 0x00000000},
  288.     {EVX$PAL_BUGCHK,         "BUGCHK"  ,     0x00000000, 0x00000000},
  289.     {EVX$PAL_CHME,           "CHME",         0x000000FC, 0x09C00000},
  290.     {EVX$PAL_CHMK,           "CHMK",         0x000000FC, 0x09C00000},
  291.     {EVX$PAL_CHMS,           "CHMS",         0x000000FC, 0x00000000},
  292.     {EVX$PAL_CHMU,           "CHMU",         0x000000FC, 0x00000000},
  293.     {EVX$PAL_IMB,            "IMB",          0x00000000, 0x00000000},
  294.     {EVX$PAL_INSQHIL,        "INSQHIL",      0x00030000, 0x00000001},
  295.     {EVX$PAL_INSQTIL,        "INSQTIL",      0x00030000, 0x00000001},
  296.     {EVX$PAL_INSQHIQ,        "INSQHIQ",      0x00030000, 0x00000001},
  297.     {EVX$PAL_INSQTIQ,        "INSQTIQ",      0x00030000, 0x00000001},
  298.     {EVX$PAL_INSQUEL,        "INSQUEL",      0x00030000, 0x00000001},
  299.     {EVX$PAL_INSQUEQ,        "INSQUEQ",      0x00030000, 0x00000001},
  300.     {EVX$PAL_INSQUELD,       "INSQUELD",     0x00030000, 0x00000001},
  301.     {EVX$PAL_INSQUEQD,       "INSQUEQD",     0x00030000, 0x00000001},
  302.     {EVX$PAL_PROBER,         "PROBER",       0x00070000, 0x00000001},
  303.     {EVX$PAL_PROBEW,         "PROBEW",       0x00070000, 0x00000001},
  304.     {EVX$PAL_RD_PS,          "RD_PS",        0x00000000, 0x00000001},
  305.     {EVX$PAL_REI,            "REI",          0x00000000, 0x000000FC},
  306.     {EVX$PAL_REMQHIL,        "REMQHIL",      0x00010000, 0x00000003},
  307.     {EVX$PAL_REMQTIL,        "REMQTIL",      0x00010000, 0x00000003},
  308.     {EVX$PAL_REMQHIQ,        "REMQHIQ",      0x00010000, 0x00000003},
  309.     {EVX$PAL_REMQTIQ,        "REMQTIQ",      0x00010000, 0x00000003},
  310.     {EVX$PAL_REMQUEL,        "REMQUEL",      0x00010000, 0x00000003},
  311.     {EVX$PAL_REMQUEQ,        "REMQUEQ",      0x00010000, 0x00000003},
  312.     {EVX$PAL_REMQUELD,       "REMQUELD",     0x00010000, 0x00000003},
  313.     {EVX$PAL_REMQUEQD,       "REMQUEQD",     0x00010000, 0x00000003},
  314.     {EVX$PAL_SWASTEN,        "SWASTEN",      0x00010000, 0x00000001},
  315.     {EVX$PAL_WR_PS_SW,       "WR_PS_SW",     0x00010000, 0x00000000},
  316.     {EVX$PAL_RSCC,           "RSCC",         0x00000000, 0x00000001},
  317.     {EVX$PAL_RDUNIQUE,       "RDUNIQUE",     0x00000000, 0x00000001},
  318.     {EVX$PAL_WRUNIQUE,       "WRUNIQUE",     0x00010000, 0x00000000},
  319.     {EVX$PAL_AMOVRR,         "AMOVRR",       0x003F0000, 0x00000000},
  320.     {EVX$PAL_AMOVRM,         "AMOVRM",       0x003F0000, 0x00000000},
  321.     {EVX$PAL_INSQHILR,       "INSQHILR",     0x00030000, 0x00000001},
  322.     {EVX$PAL_INSQTILR,       "INSQTILR",     0x00030000, 0x00000001},
  323.     {EVX$PAL_INSQHIQR,       "INSQHIQR",     0x00030000, 0x00000001},
  324.     {EVX$PAL_INSQTIQR,       "INSQTIQR",     0x00030000, 0x00000001},
  325.     {EVX$PAL_REMQHILR,       "REMQHILR",     0x00010000, 0x00000003},
  326.     {EVX$PAL_REMQTILR,       "REMQTILR",     0x00010000, 0x00000003},
  327.     {EVX$PAL_REMQHIQR,       "REMQHIQR",     0x00010000, 0x00000003},
  328.     {EVX$PAL_REMQTIQR,       "REMQTIQR",     0x00010000, 0x00000003},
  329.     {EVX$PAL_GENTRAP,        "GENTRAP",      0x000000FC, 0x00000000},
  330.     {EVX$PAL_NPHALT,         "NPHALT",       0x00000000, 0x00000000},
  331.     {EVX$PAL_RESERVED_DVT,   "DVT",          0x00000000, 0x00000000},
  332.     {EVX$PAL_RESERVED_SIM,   "SIM",          0x00000000, 0x00000000},
  333.     {0,                      NULL,           0x00000000, 0x00000000} 
  334. };
  335.  
  336. /*
  337.  *  The array alpha_opcodes is sorted by opcodes value. Use the opcode value
  338.  *  (6 bits: 0 to 63) as index. The "opcode" field is here for sanity check.
  339.  */
  340.  
  341. static inst_desc_t alpha_opcodes [] = {
  342.     {EVX$OPC_PAL,    "CALL_PAL", IT_PAL,      0, 0, pal_names},
  343.     {EVX$OPC_OPC01,  "OPC01",    IT_RESERVED, 0, 0, NULL},
  344.     {EVX$OPC_OPC02,  "OPC02",    IT_RESERVED, 0, 0, NULL},
  345.     {EVX$OPC_OPC03,  "OPC03",    IT_RESERVED, 0, 0, NULL},
  346.     {EVX$OPC_OPC04,  "OPC04",    IT_RESERVED, 0, 0, NULL},
  347.     {EVX$OPC_OPC05,  "OPC05",    IT_RESERVED, 0, 0, NULL},
  348.     {EVX$OPC_OPC06,  "OPC06",    IT_RESERVED, 0, 0, NULL},
  349.     {EVX$OPC_OPC07,  "OPC07",    IT_RESERVED, 0, 0, NULL},
  350.     {EVX$OPC_LDA,    "LDA",      IT_MEMORY,   0, 0, NULL},
  351.     {EVX$OPC_LDAH,   "LDAH",     IT_MEMORY,   0, 0, NULL},
  352.     {EVX$OPC_LDBU,   "LDB_U",    IT_MEMORY,   0, 0, NULL},
  353.     {EVX$OPC_LDQU,   "LDQ_U",    IT_MEMORY,   0, 0, NULL},
  354.     {EVX$OPC_LDWU,   "LDW_U",    IT_MEMORY,   0, 0, NULL},
  355.     {EVX$OPC_STW,    "STW",      IT_MEMORY,   0, 1, NULL},
  356.     {EVX$OPC_STB,    "STB",      IT_MEMORY,   0, 1, NULL},
  357.     {EVX$OPC_STQU,   "STQ_U",    IT_MEMORY,   0, 1, NULL},
  358.     {EVX$OPC_ADDI,   "ADDI",     IT_OPER,     0, 0, addi_names},
  359.     {EVX$OPC_LOGI,   "LOGI",     IT_OPER,     0, 0, logi_names},
  360.     {EVX$OPC_SHFI,   "SHFI",     IT_OPER,     0, 0, shfi_names},
  361.     {EVX$OPC_MULI,   "MULI",     IT_OPER,     0, 0, muli_names},
  362.     {EVX$OPC_OPC14,  "OPC14",    IT_RESERVED, 0, 0, NULL},
  363.     {EVX$OPC_FPDEC,  "FPDEC",    IT_FP,       1, 0, NULL},
  364.     {EVX$OPC_FPIEEE, "FPIEEE",   IT_FP,       1, 0, NULL},
  365.     {EVX$OPC_FPAUX,  "FPAUX",    IT_FPAUX,    1, 0, NULL},
  366.     {EVX$OPC_SYNC,   "SYNC",     IT_SYNC,     0, 0, NULL},
  367.     {EVX$OPC_PAL19,  "PAL19",    IT_PAL,      0, 0, NULL},
  368.     {EVX$OPC_JSR,    "JSR",      IT_JUMP,     0, 0, NULL},
  369.     {EVX$OPC_PAL1B,  "PAL1B",    IT_PAL,      0, 0, NULL},
  370.     {EVX$OPC_EXTI,   "EXTI",     IT_OPER,     0, 0, exti_names},
  371.     {EVX$OPC_PAL1D,  "PAL1D",    IT_PAL,      0, 0, NULL},
  372.     {EVX$OPC_PAL1E,  "PAL1E",    IT_PAL,      0, 0, NULL},
  373.     {EVX$OPC_PAL1F,  "PAL1F",    IT_PAL,      0, 0, NULL},
  374.     {EVX$OPC_LDF,    "LDF",      IT_MEMORY,   1, 0, NULL},
  375.     {EVX$OPC_LDD,    "LDD",      IT_MEMORY,   1, 0, NULL},
  376.     {EVX$OPC_LDS,    "LDS",      IT_MEMORY,   1, 0, NULL},
  377.     {EVX$OPC_LDT,    "LDT",      IT_MEMORY,   1, 0, NULL},
  378.     {EVX$OPC_STF,    "STF",      IT_MEMORY,   1, 1, NULL},
  379.     {EVX$OPC_STD,    "STD",      IT_MEMORY,   1, 1, NULL},
  380.     {EVX$OPC_STS,    "STS",      IT_MEMORY,   1, 1, NULL},
  381.     {EVX$OPC_STT,    "STT",      IT_MEMORY,   1, 1, NULL},
  382.     {EVX$OPC_LDL,    "LDL",      IT_MEMORY,   0, 0, NULL},
  383.     {EVX$OPC_LDQ,    "LDQ",      IT_MEMORY,   0, 0, NULL},
  384.     {EVX$OPC_LDLL,   "LDL_L",    IT_MEMORY,   0, 0, NULL},
  385.     {EVX$OPC_LDQL,   "LDQ_L",    IT_MEMORY,   0, 0, NULL},
  386.     {EVX$OPC_STL,    "STL",      IT_MEMORY,   0, 1, NULL},
  387.     {EVX$OPC_STQ,    "STQ",      IT_MEMORY,   0, 1, NULL},
  388.     {EVX$OPC_STLC,   "STL_C",    IT_MEMORY,   0, 1, NULL},
  389.     {EVX$OPC_STQC,   "STQ_C",    IT_MEMORY,   0, 1, NULL},
  390.     {EVX$OPC_BR,     "BR",       IT_BRANCH,   0, 0, NULL},
  391.     {EVX$OPC_FBEQ,   "FBEQ",     IT_BRANCH,   1, 0, NULL},
  392.     {EVX$OPC_FBLT,   "FBLT",     IT_BRANCH,   1, 0, NULL},
  393.     {EVX$OPC_FBLE,   "FBLE",     IT_BRANCH,   1, 0, NULL},
  394.     {EVX$OPC_BSR,    "BSR",      IT_BRANCH,   0, 0, NULL},
  395.     {EVX$OPC_FBNE,   "FBNE",     IT_BRANCH,   1, 0, NULL},
  396.     {EVX$OPC_FBGE,   "FBGE",     IT_BRANCH,   1, 0, NULL},
  397.     {EVX$OPC_FBGT,   "FBGT",     IT_BRANCH,   1, 0, NULL},
  398.     {EVX$OPC_BLBC,   "BLBC",     IT_BRANCH,   0, 0, NULL},
  399.     {EVX$OPC_BEQ,    "BEQ",      IT_BRANCH,   0, 0, NULL},
  400.     {EVX$OPC_BLT,    "BLT",      IT_BRANCH,   0, 0, NULL},
  401.     {EVX$OPC_BLE,    "BLE",      IT_BRANCH,   0, 0, NULL},
  402.     {EVX$OPC_BLBS,   "BLBS",     IT_BRANCH,   0, 0, NULL},
  403.     {EVX$OPC_BNE,    "BNE",      IT_BRANCH,   0, 0, NULL},
  404.     {EVX$OPC_BGE,    "BGE",      IT_BRANCH,   0, 0, NULL},
  405.     {EVX$OPC_BGT,    "BGT",      IT_BRANCH,   0, 0, NULL},
  406. };
  407.  
  408.  
  409. /*******************************************************************************
  410.  *
  411.  *  Default output routine for callmon$disassemble
  412.  */
  413.  
  414. static void default_output (void* pc, char* opcode, char* operands, void* data)
  415. {
  416.     printf ("  %08X:  %-7s %s\n", pc, opcode, operands);
  417. }
  418.  
  419.  
  420. /*******************************************************************************
  421.  *
  422.  *  This routine formats and displays Alpha machine code instructions.
  423.  */
  424.  
  425. void callmon$$disassemble (
  426.     inst_t*                          address,
  427.     size_t                           size_in_bytes,
  428.     void*                            displayed_pc,
  429.     callmon$disassemble_output_t     output_routine,
  430.     callmon$disassemble_output_dsc_t output_routine_dsc,
  431.     void*                            user_data)
  432. {
  433.     inst_t* end = (inst_t*) ((char*) address + size_in_bytes);
  434.     inst_t* pc;
  435.     inst_t* disp_pc;
  436.     inst_desc_t* inst;
  437.     char opcode [40], operands [80];
  438.     desc_t opcode_d, operands_d;
  439.  
  440.     /* Ensure that there is at least one output routine */
  441.  
  442.     if (output_routine == NULL && output_routine_dsc == NULL)
  443.         output_routine = default_output;
  444.  
  445.     for (pc = address, disp_pc = displayed_pc; pc < end; pc++, disp_pc++) {
  446.  
  447.         inst = alpha_opcodes + pc->u.op.opcode;
  448.  
  449.         /* Opcode will be filled, operands are optional */
  450.  
  451.         operands [0] = '\0';
  452.  
  453.         /* Look for "stylized code forms". */
  454.  
  455.         /* NOP = BIS R31, R31, R31 */
  456.  
  457.         if (pc->u.instr ==
  458.             (EVX$OPC32_BIS | INST_RA_MASK | INST_RB_MASK | INST_RC_MASK)) {
  459.  
  460.             strcpy (opcode, "NOP");
  461.         }
  462.  
  463.         /* FNOP = CPYS F31, F31, F31 */
  464.  
  465.         else if (pc->u.instr 
  466.             == (EVX$OPC32_CPYS | INST_RA_MASK | INST_RB_MASK | INST_RC_MASK)) {
  467.  
  468.             strcpy (opcode, "FNOP");
  469.         }
  470.  
  471.         /* CLR Rx = BIS R31, R31, Rx */
  472.  
  473.         else if ((pc->u.instr & ~INST_RC_MASK) 
  474.             == (EVX$OPC32_BIS | INST_RA_MASK | INST_RB_MASK)) {
  475.  
  476.             strcpy (opcode, "CLR");
  477.             sprintf (operands, "R%d", pc->u.op.rc);
  478.         }
  479.  
  480.         /* FCLR Fx = CPYS F31, F31, Fx */
  481.  
  482.         else if ((pc->u.instr & ~INST_RC_MASK)
  483.             == (EVX$OPC32_CPYS | INST_RA_MASK | INST_RB_MASK)) {
  484.  
  485.             strcpy (opcode, "FCLR");
  486.             sprintf (operands, "F%d", pc->u.op.rc);
  487.         }
  488.  
  489.         /* MOV Rx, Ry = BIS R31, Rx, Ry = BIS Rx, Rx, Ry */
  490.  
  491.         else if ((pc->u.instr & ~INST_RB_MASK & ~INST_RC_MASK) 
  492.             == (EVX$OPC32_BIS | INST_RA_MASK) ||
  493.             ((pc->u.instr & ~INST_RA_MASK & ~INST_RB_MASK & ~INST_RC_MASK)
  494.             == EVX$OPC32_BIS && pc->u.op.ra == pc->u.op.rb)) {
  495.  
  496.             strcpy (opcode, "MOV");
  497.             sprintf (operands, "R%d, R%d", pc->u.op.rb, pc->u.op.rc);
  498.         }
  499.  
  500.         /* MOV #lit, Ry = BIS R31, #lit, Ry */
  501.  
  502.         else if ((pc->u.instr & ~INST_LIT_MASK & ~INST_RC_MASK)
  503.             == (EVX$OPC32_BIS | INST_RA_MASK | INST_LITFLG_MASK)) {
  504.  
  505.             strcpy (opcode, "MOV");
  506.             sprintf (operands, "#%d, R%d", pc->u.oplit.lit, pc->u.oplit.rc);
  507.         }
  508.  
  509.         /* FMOV Fx, Fy = CPYS Fx, Fx, Fy */
  510.  
  511.         else if ((pc->u.instr & ~INST_RA_MASK & ~INST_RB_MASK & ~INST_RC_MASK)
  512.             == EVX$OPC32_CPYS && pc->u.op.ra == pc->u.op.rb) {
  513.  
  514.             strcpy (opcode, "FMOV");
  515.             sprintf (operands, "F%d, F%d", pc->u.op.rb, pc->u.op.rc);
  516.         }
  517.  
  518.         /* NOT Rx, Ry = ORNOT R31, Rx, Ry */
  519.  
  520.         else if ((pc->u.instr & ~INST_RB_MASK & ~INST_RC_MASK)
  521.             == (EVX$OPC32_ORNOT | INST_RA_MASK)) {
  522.  
  523.             strcpy (opcode, "NOT");
  524.             sprintf (operands, "R%d, R%d", pc->u.op.rb, pc->u.op.rc);
  525.         }
  526.  
  527.         /* NEGL Rx, Ry = SUBL R31, Rx, Ry */
  528.  
  529.         else if ((pc->u.instr & ~INST_RB_MASK & ~INST_RC_MASK)
  530.             == (EVX$OPC32_SUBL | INST_RA_MASK)) {
  531.  
  532.             strcpy (opcode, "NEGL");
  533.             sprintf (operands, "R%d, R%d", pc->u.op.rb, pc->u.op.rc);
  534.         }
  535.  
  536.         /* NEGQ Rx, Ry = SUBQ R31, Rx, Ry */
  537.  
  538.         else if ((pc->u.instr & ~INST_RB_MASK & ~INST_RC_MASK)
  539.             == (EVX$OPC32_SUBQ | INST_RA_MASK)) {
  540.  
  541.             strcpy (opcode, "NEGQ");
  542.             sprintf (operands, "R%d, R%d", pc->u.op.rb, pc->u.op.rc);
  543.         }
  544.  
  545.         /* Standard code form processing */
  546.  
  547.         else {
  548.             switch (inst->type) {
  549.  
  550.                 case IT_RESERVED: {
  551.                     strcpy (opcode, inst->name);
  552.                     break;
  553.                 }
  554.  
  555.                 case IT_PAL: {
  556.                     inst_pal_t* pal;
  557.                     strcpy (opcode, inst->name);
  558.                     if ((pal = inst->name_list) != NULL) {
  559.                         for (; pal->name != NULL; pal++) {
  560.                             if (pc->u.pal.number == pal->function) {
  561.                                 strcpy (operands, pal->name);
  562.                                 break;
  563.                             }
  564.                         }
  565.                     }
  566.                     if (pal == NULL || pal->name == NULL)
  567.                         sprintf (operands, "%d", pc->u.pal.number);
  568.                     break;
  569.                 }
  570.  
  571.                 case IT_SYNC: {
  572.                     inst_sync_t* sync;
  573.                     char* op;
  574.                     for (sync = sync_opcodes; sync->name != NULL; sync++) {
  575.                         if (pc->u.umem.func == sync->function) {
  576.                             strcpy (opcode, sync->name);
  577.                             op = operands;
  578.                             if (sync->use_ra)
  579.                                 op += sprintf (op, "R%s", pc->u.umem.ra);
  580.                             if (sync->use_ra && sync->use_rb)
  581.                                 op += strlen (strcpy (op, ", "));
  582.                             if (sync->use_rb)
  583.                                 sprintf (op, "(R%s)", pc->u.umem.rb);
  584.                             break;
  585.                         }
  586.                     }
  587.                     if (sync->name == NULL)
  588.                         sprintf (opcode, "%s_%d", inst->name, pc->u.umem.func);
  589.                     break;
  590.                 }
  591.  
  592.                 case IT_OPER: {
  593.                     inst_name_t* name;
  594.                     for (name = inst->name_list; name->name != NULL; name++) {
  595.                         if (pc->u.op.func == name->function) {
  596.                             strcpy (opcode, name->name);
  597.                             break;
  598.                         }
  599.                     }
  600.                     if (name->name == NULL)
  601.                         sprintf (opcode, "%s_%d", inst->name, pc->u.op.func);
  602.                     sprintf (operands, "R%d, %c%d, R%d", pc->u.op.ra,
  603.                         pc->u.op.litflg ? '#' : 'R',
  604.                         pc->u.op.litflg ? pc->u.oplit.lit : pc->u.op.rb,
  605.                         pc->u.op.rc);
  606.                     break;
  607.                 }
  608.  
  609.                 case IT_MEMORY: {
  610.                     strcpy (opcode, inst->name);
  611.                     sprintf (operands, "%c%d, %d (R%d)",
  612.                         inst->float_inst ? 'F' : 'R',
  613.                         pc->u.mem.ra, pc->u.mem.disp, pc->u.mem.rb);
  614.                     break;
  615.                 }
  616.  
  617.                 case IT_BRANCH: {
  618.                     routine_t* routine;
  619.                     inst_t* target = disp_pc + 1 + pc->u.branch.disp;
  620.                     char* op = operands;
  621.                     strcpy (opcode, inst->name);
  622.                     if (pc->u.branch.opcode != EVX$OPC_BR ||
  623.                         pc->u.branch.ra != 31) {
  624.                         op += sprintf (op, "%c%d, ",
  625.                             inst->float_inst ? 'F' : 'R',
  626.                             pc->u.branch.ra);
  627.                     }
  628.                     if (pc->u.branch.opcode == EVX$OPC_BSR && (routine =
  629.                         callmon$$get_routine_by_entry ((int64) target)) != NULL)
  630.                         strcpy (op, routine->name);
  631.                     else
  632.                         sprintf (op, "%08X", target);
  633.                     break;
  634.                 }
  635.  
  636.                 case IT_JUMP: {
  637.                     static char* jsr_names [] = {
  638.                         "JMP", "JSR", "RET", "JSR_COROUTINE"};
  639.                     char* op = operands;
  640.                     strcpy (opcode, jsr_names [pc->u.jump.hint]);
  641.                     if (pc->u.jump.ra != 31)
  642.                         op += sprintf (op, "R%d, ", pc->u.jump.ra);
  643.                     sprintf (op, "(R%d)", pc->u.jump.rb);
  644.                     break;
  645.                 }
  646.  
  647.                 case IT_FPAUX: {
  648.                     inst_fpaux_t* fp;
  649.                     char* op = operands;
  650.                     for (fp = fpaux_opcodes; fp->name != NULL; fp++) {
  651.                         if (pc->u.fpaux.func == fp->function) {
  652.                             strcpy (opcode, fp->name);
  653.                             if (fp->use_fa)
  654.                                 op += sprintf (op, "F%d, ", pc->u.fpaux.fa);
  655.                             sprintf (op, "F%d, F%d", pc->u.fpaux.fb,
  656.                                 pc->u.fpaux.fc);
  657.                             break;
  658.                         }
  659.                     }
  660.                     if (fp->name == NULL)
  661.                         sprintf (opcode, "%s_%d", inst->name, pc->u.fpaux.func);
  662.                     break;
  663.                 }
  664.  
  665.                 case IT_FP: {
  666.                     char* op;
  667.                     char** names = pc->u.fp.opcode == EVX$OPC_FPIEEE ?
  668.                         fp_ieee_name : fp_dec_name;
  669.                     op = opcode + sprintf (opcode, fp_inst_name [pc->u.fp.func],
  670.                         names [pc->u.fp.src], names [pc->u.fp.func & 0x03]);
  671.                     op += sprintf (op, "/%s%s", fp_trap_name [pc->u.fp.trp],
  672.                         fp_round_name [pc->u.fp.rnd]);
  673.                     if (op [-1] == '/')
  674.                         op [-1] = '\0';
  675.                     op = operands;
  676.                     if (pc->u.fp.func < 8)
  677.                         op += sprintf (op, "F%d, ", pc->u.fp.fa);
  678.                     sprintf (op, "F%d, F%d", pc->u.fp.fb, pc->u.fp.fc);
  679.                     break;
  680.                 }
  681.  
  682.             } /* switch */
  683.         } /* else */
  684.  
  685.         /* Call the display routine */
  686.  
  687.         if (output_routine != NULL)
  688.             output_routine (disp_pc, opcode, operands, user_data);
  689.  
  690.         if (output_routine_dsc != NULL)
  691.             output_routine_dsc (disp_pc, set_str_desc (&opcode_d, opcode),
  692.                 set_str_desc (&operands_d, operands), user_data);
  693.  
  694.     } /* for */
  695. }
  696.  
  697.  
  698. /*******************************************************************************
  699.  *
  700.  *  These public routines format and display Alpha machine code instructions.
  701.  */
  702.  
  703. void callmon$disassemble (
  704.     void*                        address,
  705.     size_t                       size_in_bytes,
  706.     void*                        displayed_pc,
  707.     callmon$disassemble_output_t output_routine,
  708.     void*                        user_data)
  709. {
  710.     callmon$initialize ();
  711.  
  712.     callmon$$disassemble (address, size_in_bytes, displayed_pc,
  713.         output_routine, NULL, user_data);
  714. }
  715.  
  716. void callmon$disassemble_dsc (
  717.     void*                            address,
  718.     size_t                           size_in_bytes,
  719.     void*                            displayed_pc,
  720.     callmon$disassemble_output_dsc_t output_routine,
  721.     void*                            user_data)
  722. {
  723.     callmon$initialize ();
  724.  
  725.     callmon$$disassemble (address, size_in_bytes, displayed_pc,
  726.         NULL, output_routine, user_data);
  727. }
  728.  
  729.  
  730. /*******************************************************************************
  731.  *
  732.  *  This routine returns the list of integer registers which are read
  733.  *  by the specified instruction. Return a mask.
  734.  */
  735.  
  736. uint32 callmon$$read_register_mask (inst_t* pc)
  737. {
  738.     uint32 result = 0;
  739.     inst_desc_t* inst = alpha_opcodes + pc->u.op.opcode;
  740.  
  741.     switch (inst->type) {
  742.  
  743.         case IT_PAL: {
  744.             inst_pal_t* pal;
  745.             if ((pal = inst->name_list) != NULL) {
  746.                 for (; pal->name != NULL; pal++) {
  747.                     if (pc->u.pal.number == pal->function) {
  748.                         result = pal->read_regs;
  749.                         break;
  750.                     }
  751.                 }
  752.             }
  753.             break;
  754.         }
  755.  
  756.         case IT_JUMP:
  757.         case IT_MEMORY: {
  758.             result = 1 << pc->u.mem.rb;
  759.             if (!inst->float_inst && inst->is_store)
  760.                 result |= 1 << pc->u.mem.ra;
  761.             break;
  762.         }
  763.  
  764.         case IT_BRANCH: {
  765.             if (!inst->float_inst &&
  766.                 pc->u.branch.opcode != EVX$OPC_BR &&
  767.                 pc->u.branch.opcode != EVX$OPC_BSR)
  768.                 result = 1 << pc->u.branch.ra;
  769.             break;
  770.         }
  771.  
  772.         case IT_SYNC: {
  773.             inst_sync_t* sync;
  774.             for (sync = sync_opcodes; sync->name != NULL; sync++) {
  775.                 if (pc->u.umem.func == sync->function) {
  776.                     result = sync->use_rb ? (1 << pc->u.umem.rb) : 0;
  777.                     break;
  778.                 }
  779.             }
  780.             break;
  781.         }
  782.  
  783.         case IT_OPER: {
  784.             result = 1 << pc->u.op.ra;
  785.             if (!pc->u.op.litflg)
  786.                 result |= 1 << pc->u.op.rb;
  787.             break;
  788.         }
  789.     }
  790.  
  791.     /* Register R31 is not significant */
  792.  
  793.     return result & 0x7FFFFFFF;
  794. }
  795.  
  796.  
  797. /*******************************************************************************
  798.  *
  799.  *  This routine returns the list of integer registers which are written
  800.  *  by the specified instruction. Return a mask.
  801.  */
  802.  
  803. uint32 callmon$$write_register_mask (inst_t* pc)
  804. {
  805.     uint32 result = 0;
  806.     inst_desc_t* inst = alpha_opcodes + pc->u.op.opcode;
  807.  
  808.     switch (inst->type) {
  809.  
  810.         case IT_PAL: {
  811.             inst_pal_t* pal;
  812.             if ((pal = inst->name_list) != NULL) {
  813.                 for (; pal->name != NULL; pal++) {
  814.                     if (pc->u.pal.number == pal->function) {
  815.                         result = pal->write_regs;
  816.                         break;
  817.                     }
  818.                 }
  819.             }
  820.             break;
  821.         }
  822.  
  823.         case IT_JUMP:
  824.         case IT_MEMORY: {
  825.             if (!inst->float_inst && !inst->is_store)
  826.                 result = 1 << pc->u.mem.ra;
  827.             break;
  828.         }
  829.  
  830.         case IT_BRANCH: {
  831.             if (pc->u.branch.opcode == EVX$OPC_BR ||
  832.                 pc->u.branch.opcode == EVX$OPC_BSR)
  833.                 result = 1 << pc->u.branch.ra;
  834.             break;
  835.         }
  836.  
  837.         case IT_SYNC: {
  838.             inst_sync_t* sync;
  839.             for (sync = sync_opcodes; sync->name != NULL; sync++) {
  840.                 if (pc->u.umem.func == sync->function) {
  841.                     result = sync->use_ra ? (1 << pc->u.umem.ra) : 0;
  842.                     break;
  843.                 }
  844.             }
  845.             break;
  846.         }
  847.  
  848.         case IT_OPER: {
  849.             result = 1 << pc->u.op.rc;
  850.             break;
  851.         }
  852.     }
  853.  
  854.     /* Register R31 is not significant */
  855.  
  856.     return result & 0x7FFFFFFF;
  857. }
  858.  
  859.  
  860. /*******************************************************************************
  861.  *
  862.  *  This routine checks if the specified instruction takes a branch.
  863.  *  Possible return values are:
  864.  *
  865.  *    0 : no branch
  866.  *    1 : call to PAL (returns in sequence)
  867.  *    2 : call to subroutine (should return in sequence)
  868.  *    3 : conditional branch
  869.  *    4 : unconditional branch
  870.  */
  871.  
  872. int callmon$$branch_instruction (inst_t* pc)
  873. {
  874.     inst_desc_t* inst = alpha_opcodes + pc->u.op.opcode;
  875.  
  876.     switch (inst->type) {
  877.  
  878.         case IT_PAL: {
  879.             return 1;
  880.         }
  881.  
  882.         case IT_BRANCH: {
  883.             if (pc->u.branch.opcode == EVX$OPC_BSR)
  884.                 return 2;
  885.             else if (pc->u.branch.opcode == EVX$OPC_BR)
  886.                 return 4;
  887.             else
  888.                 return 3;
  889.         }
  890.  
  891.         case IT_JUMP: {
  892.             static int jsr_values [] = {
  893.                 /*JMP*/ 4, /*JSR*/ 2, /*RET*/ 4, /*JSR_COROUTINE*/ 2};
  894.             return jsr_values [pc->u.jump.hint];
  895.         }
  896.     }
  897.  
  898.     return 0;
  899. }
  900.  
  901.  
  902. /*******************************************************************************
  903.  *
  904.  *  This routine checks if the specified instruction is a PC-relative
  905.  *  branch instruction. If yes, return the target of the branch. If no,
  906.  *  return NULL.
  907.  */
  908.  
  909. inst_t* callmon$$branch_target (inst_t* pc)
  910. {
  911.     inst_desc_t* inst = alpha_opcodes + pc->u.op.opcode;
  912.  
  913.     /* Compute the target of the branch. Note that displacement must
  914.      * be applied on the adjusted PC and uses a factor of 4, which
  915.      * is the factor used by C since this is the size of inst_t. */
  916.  
  917.     if (inst->type == IT_BRANCH)
  918.         return pc + 1 + pc->u.branch.disp;
  919.     else
  920.         return NULL;
  921. }
  922.