ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/sigsegv.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/sigsegv.cpp (file contents):
Revision 1.37 by gbeauche, 2003-12-20T07:43:56Z vs.
Revision 1.38 by gbeauche, 2003-12-20T10:06:18Z

# Line 226 | Line 226 | static void powerpc_decode_instruction(i
226   #include <ucontext.h>
227   #define SIGSEGV_CONTEXT_REGS                    (((ucontext_t *)scp)->uc_mcontext.gregs)
228   #define SIGSEGV_FAULT_INSTRUCTION               (unsigned long)SIGSEGV_CONTEXT_REGS[CTX_EPC]
229 + #if (defined(mips) || defined(__mips))
230 + #define SIGSEGV_REGISTER_FILE                   SIGSEGV_CONTEXT_REGS
231 + #define SIGSEGV_SKIP_INSTRUCTION                mips_skip_instruction
232 + #endif
233   #endif
234   #if defined(__sun__)
235   #if (defined(sparc) || defined(__sparc__))
# Line 924 | Line 928 | static bool powerpc_skip_instruction(uns
928          return true;
929   }
930   #endif
931 +
932 + // Decode and skip MIPS instruction
933 + #if (defined(mips) || defined(__mips))
934 + enum {
935 + #if (defined(sgi) || defined(__sgi))
936 +  MIPS_REG_EPC = 35,
937 + #endif
938 + };
939 + static bool mips_skip_instruction(greg_t * regs)
940 + {
941 +  unsigned int * epc = (unsigned int *)(unsigned long)regs[MIPS_REG_EPC];
942 +
943 +  if (epc == 0)
944 +        return false;
945 +
946 + #if DEBUG
947 +  printf("IP: %p [%08x]\n", epc, epc[0]);
948 + #endif
949 +
950 +  transfer_type_t transfer_type = SIGSEGV_TRANSFER_UNKNOWN;
951 +  transfer_size_t transfer_size = SIZE_LONG;
952 +  int direction = 0;
953 +
954 +  const unsigned int opcode = epc[0];
955 +  switch (opcode >> 26) {
956 +  case 32: // Load Byte
957 +  case 36: // Load Byte Unsigned
958 +        transfer_type = SIGSEGV_TRANSFER_LOAD;
959 +        transfer_size = SIZE_BYTE;
960 +        break;
961 +  case 33: // Load Halfword
962 +  case 37: // Load Halfword Unsigned
963 +        transfer_type = SIGSEGV_TRANSFER_LOAD;
964 +        transfer_size = SIZE_WORD;
965 +        break;
966 +  case 35: // Load Word
967 +  case 39: // Load Word Unsigned
968 +        transfer_type = SIGSEGV_TRANSFER_LOAD;
969 +        transfer_size = SIZE_LONG;
970 +        break;
971 +  case 34: // Load Word Left
972 +        transfer_type = SIGSEGV_TRANSFER_LOAD;
973 +        transfer_size = SIZE_LONG;
974 +        direction = -1;
975 +        break;
976 +  case 38: // Load Word Right
977 +        transfer_type = SIGSEGV_TRANSFER_LOAD;
978 +        transfer_size = SIZE_LONG;
979 +        direction = 1;
980 +        break;
981 +  case 55: // Load Doubleword
982 +        transfer_type = SIGSEGV_TRANSFER_LOAD;
983 +        transfer_size = SIZE_QUAD;
984 +        break;
985 +  case 26: // Load Doubleword Left
986 +        transfer_type = SIGSEGV_TRANSFER_LOAD;
987 +        transfer_size = SIZE_QUAD;
988 +        direction = -1;
989 +        break;
990 +  case 27: // Load Doubleword Right
991 +        transfer_type = SIGSEGV_TRANSFER_LOAD;
992 +        transfer_size = SIZE_QUAD;
993 +        direction = 1;
994 +        break;
995 +  case 40: // Store Byte
996 +        transfer_type = SIGSEGV_TRANSFER_STORE;
997 +        transfer_size = SIZE_BYTE;
998 +        break;
999 +  case 41: // Store Halfword
1000 +        transfer_type = SIGSEGV_TRANSFER_STORE;
1001 +        transfer_size = SIZE_WORD;
1002 +        break;
1003 +  case 43: // Store Word
1004 +  case 42: // Store Word Left
1005 +  case 46: // Store Word Right
1006 +        transfer_type = SIGSEGV_TRANSFER_STORE;
1007 +        transfer_size = SIZE_LONG;
1008 +        break;
1009 +  case 63: // Store Doubleword
1010 +  case 44: // Store Doubleword Left
1011 +  case 45: // Store Doubleword Right
1012 +        transfer_type = SIGSEGV_TRANSFER_STORE;
1013 +        transfer_size = SIZE_QUAD;
1014 +        break;
1015 +  /* Misc instructions unlikely to be used within CPU emulators */
1016 +  case 48: // Load Linked Word
1017 +        transfer_type = SIGSEGV_TRANSFER_LOAD;
1018 +        transfer_size = SIZE_LONG;
1019 +        break;
1020 +  case 52: // Load Linked Doubleword
1021 +        transfer_type = SIGSEGV_TRANSFER_LOAD;
1022 +        transfer_size = SIZE_QUAD;
1023 +        break;
1024 +  case 56: // Store Conditional Word
1025 +        transfer_type = SIGSEGV_TRANSFER_STORE;
1026 +        transfer_size = SIZE_LONG;
1027 +        break;
1028 +  case 60: // Store Conditional Doubleword
1029 +        transfer_type = SIGSEGV_TRANSFER_STORE;
1030 +        transfer_size = SIZE_QUAD;
1031 +        break;
1032 +  }
1033 +
1034 +  if (transfer_type == SIGSEGV_TRANSFER_UNKNOWN) {
1035 +        // Unknown machine code, let it crash. Then patch the decoder
1036 +        return false;
1037 +  }
1038 +
1039 +  // Zero target register in case of a load operation
1040 +  const int reg = (opcode >> 16) & 0x1f;
1041 +  if (transfer_type == SIGSEGV_TRANSFER_LOAD) {
1042 +        if (direction == 0)
1043 +          regs[reg] = 0;
1044 +        else {
1045 +          // FIXME: untested code
1046 +          unsigned long ea = regs[(opcode >> 21) & 0x1f];
1047 +          ea += (signed long)(signed int)(signed short)(opcode & 0xffff);
1048 +          const int offset = ea & (transfer_size == SIZE_LONG ? 3 : 7);
1049 +          unsigned long value;
1050 +          if (direction > 0) {
1051 +                const unsigned long rmask = ~((1L << ((offset + 1) * 8)) - 1);
1052 +                value = regs[reg] & rmask;
1053 +          }
1054 +          else {
1055 +                const unsigned long lmask = (1L << (offset * 8)) - 1;
1056 +                value = regs[reg] & lmask;
1057 +          }
1058 +          // restore most significant bits
1059 +          if (transfer_size == SIZE_LONG)
1060 +                value = (signed long)(signed int)value;
1061 +          regs[reg] = value;
1062 +        }
1063 +  }
1064 +
1065 + #if DEBUG
1066 + #if (defined(_ABIN32) || defined(_ABI64))
1067 +  static const char * mips_gpr_names[32] = {
1068 +        "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3",
1069 +        "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",   "t7",
1070 +        "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
1071 +        "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
1072 +  };
1073 + #else
1074 +  static const char * mips_gpr_names[32] = {
1075 +        "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3",
1076 +        "a4",   "a5",   "a6",   "a7",   "t0",   "t1",   "t2",   "t3",
1077 +        "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
1078 +        "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
1079 +  };
1080 + #endif
1081 +  printf("%s %s register %s\n",
1082 +                 transfer_size == SIZE_BYTE ? "byte" :
1083 +                 transfer_size == SIZE_WORD ? "word" :
1084 +                 transfer_size == SIZE_LONG ? "long" :
1085 +                 transfer_size == SIZE_QUAD ? "quad" : "unknown",
1086 +                 transfer_type == SIGSEGV_TRANSFER_LOAD ? "load to" : "store from",
1087 +                 mips_gpr_names[reg]);
1088 + #endif
1089 +
1090 +  regs[MIPS_REG_EPC] += 4;
1091 +  return true;
1092 + }
1093 + #endif
1094   #endif
1095  
1096   // Fallbacks

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines