mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-26 08:32:20 +00:00
The Linux kernel actually allows to restart execution from the specified slot
in the bundle. This is faster and more accurate as this avoids emulation. Also clean-up code so that to prepare the use of lib uaccess on hpux/ia64. XXX: this will need explicit use of uint64_t to define registers because HP/UX is ILP32 capable and all registers are 64-bit capable so "unsigned long" won't fit.
This commit is contained in:
parent
8aadf8e455
commit
58ff9aba45
@ -309,7 +309,7 @@ static void powerpc_decode_instruction(instruction_t *instruction, unsigned int
|
|||||||
#if (defined(ia64) || defined(__ia64__))
|
#if (defined(ia64) || defined(__ia64__))
|
||||||
#define SIGSEGV_CONTEXT_REGS ((struct sigcontext *)scp)
|
#define SIGSEGV_CONTEXT_REGS ((struct sigcontext *)scp)
|
||||||
#define SIGSEGV_FAULT_INSTRUCTION (SIGSEGV_CONTEXT_REGS->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
|
#define SIGSEGV_FAULT_INSTRUCTION (SIGSEGV_CONTEXT_REGS->sc_ip & ~0x3ULL) /* slot number is in bits 0 and 1 */
|
||||||
#define SIGSEGV_REGISTER_FILE (unsigned long *)SIGSEGV_CONTEXT_REGS
|
#define SIGSEGV_REGISTER_FILE SIGSEGV_CONTEXT_REGS
|
||||||
#define SIGSEGV_SKIP_INSTRUCTION ia64_skip_instruction
|
#define SIGSEGV_SKIP_INSTRUCTION ia64_skip_instruction
|
||||||
#endif
|
#endif
|
||||||
#if (defined(powerpc) || defined(__powerpc__))
|
#if (defined(powerpc) || defined(__powerpc__))
|
||||||
@ -1166,26 +1166,19 @@ static bool ix86_skip_instruction(unsigned long * regs)
|
|||||||
// Decode and skip IA-64 instruction
|
// Decode and skip IA-64 instruction
|
||||||
#if defined(__ia64__)
|
#if defined(__ia64__)
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
// XXX: we assume everything is 8-byte aligned
|
// We can directly patch the slot number
|
||||||
#define OREG(REG) offsetof(struct sigcontext, sc_##REG)
|
#define IA64_CAN_PATCH_IP_SLOT 1
|
||||||
#define IREG(REG) ((OREG(REG) - OREG(flags)) / 8)
|
|
||||||
enum {
|
|
||||||
IA64_REG_IP = IREG(ip),
|
|
||||||
IA64_REG_NAT = IREG(nat),
|
|
||||||
IA64_REG_PR = IREG(pr),
|
|
||||||
IA64_REG_GR = IREG(gr)
|
|
||||||
};
|
|
||||||
#undef IREG
|
|
||||||
#undef OREG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Helper macros to access the machine context
|
// Helper macros to access the machine context
|
||||||
#define IA64_CONTEXT (ctx)
|
#define IA64_CONTEXT_TYPE struct sigcontext *
|
||||||
#define IA64_GET_PR(P) ((IA64_CONTEXT[IA64_REG_PR] >> (P)) & 1)
|
#define IA64_CONTEXT scp
|
||||||
#define IA64_GET_NAT(I) ((IA64_CONTEXT[IA64_REG_NAT] >> (I)) & 1)
|
#define IA64_GET_IP() (IA64_CONTEXT->sc_ip)
|
||||||
#define IA64_SET_NAT(I,V) (IA64_CONTEXT[IA64_REG_NAT] = (IA64_CONTEXT[IA64_REG_NAT] & ~(1ul << (I))) | (((unsigned long)!!(V)) << (I)))
|
#define IA64_SET_IP(V) (IA64_CONTEXT->sc_ip = (V))
|
||||||
#define IA64_GET_GR(R) (IA64_CONTEXT[IA64_REG_GR + (R)])
|
#define IA64_GET_PR(P) ((IA64_CONTEXT->sc_pr >> (P)) & 1)
|
||||||
#define IA64_SET_GR(R,V) (IA64_CONTEXT[IA64_REG_GR + (R)] = (V))
|
#define IA64_GET_NAT(I) ((IA64_CONTEXT->sc_nat >> (I)) & 1)
|
||||||
|
#define IA64_SET_NAT(I,V) (IA64_CONTEXT->sc_nat= (IA64_CONTEXT->sc_nat & ~(1ul << (I))) | (((unsigned long)!!(V)) << (I)))
|
||||||
|
#define IA64_GET_GR(R) (IA64_CONTEXT->sc_gr[(R)])
|
||||||
|
#define IA64_SET_GR(R,V) (IA64_CONTEXT->sc_gr[(R)] = (V))
|
||||||
|
#endif
|
||||||
|
|
||||||
// Instruction operations
|
// Instruction operations
|
||||||
enum {
|
enum {
|
||||||
@ -1346,7 +1339,7 @@ static unsigned long ia64_get_instruction(unsigned long raw_ip, int slot)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode group 0 instructions
|
// Decode group 0 instructions
|
||||||
static bool ia64_decode_instruction_0(ia64_instruction_t *inst, unsigned long *ctx)
|
static bool ia64_decode_instruction_0(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
|
||||||
{
|
{
|
||||||
const int r1 = (inst->inst >> 6) & 0x7f;
|
const int r1 = (inst->inst >> 6) & 0x7f;
|
||||||
const int r3 = (inst->inst >> 20) & 0x7f;
|
const int r3 = (inst->inst >> 20) & 0x7f;
|
||||||
@ -1392,7 +1385,7 @@ static bool ia64_decode_instruction_0(ia64_instruction_t *inst, unsigned long *c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode group 4 instructions (load/store instructions)
|
// Decode group 4 instructions (load/store instructions)
|
||||||
static bool ia64_decode_instruction_4(ia64_instruction_t *inst, unsigned long *ctx)
|
static bool ia64_decode_instruction_4(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
|
||||||
{
|
{
|
||||||
const int r1 = (inst->inst >> 6) & 0x7f;
|
const int r1 = (inst->inst >> 6) & 0x7f;
|
||||||
const int r2 = (inst->inst >> 13) & 0x7f;
|
const int r2 = (inst->inst >> 13) & 0x7f;
|
||||||
@ -1464,7 +1457,7 @@ static bool ia64_decode_instruction_4(ia64_instruction_t *inst, unsigned long *c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode group 5 instructions (load/store instructions)
|
// Decode group 5 instructions (load/store instructions)
|
||||||
static bool ia64_decode_instruction_5(ia64_instruction_t *inst, unsigned long *ctx)
|
static bool ia64_decode_instruction_5(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
|
||||||
{
|
{
|
||||||
const int r1 = (inst->inst >> 6) & 0x7f;
|
const int r1 = (inst->inst >> 6) & 0x7f;
|
||||||
const int r2 = (inst->inst >> 13) & 0x7f;
|
const int r2 = (inst->inst >> 13) & 0x7f;
|
||||||
@ -1522,7 +1515,7 @@ static bool ia64_decode_instruction_5(ia64_instruction_t *inst, unsigned long *c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode group 8 instructions (ALU integer)
|
// Decode group 8 instructions (ALU integer)
|
||||||
static bool ia64_decode_instruction_8(ia64_instruction_t *inst, unsigned long *ctx)
|
static bool ia64_decode_instruction_8(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
|
||||||
{
|
{
|
||||||
const int r1 = (inst->inst >> 6) & 0x7f;
|
const int r1 = (inst->inst >> 6) & 0x7f;
|
||||||
const int r2 = (inst->inst >> 13) & 0x7f;
|
const int r2 = (inst->inst >> 13) & 0x7f;
|
||||||
@ -1595,7 +1588,7 @@ static bool ia64_decode_instruction_8(ia64_instruction_t *inst, unsigned long *c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode instruction
|
// Decode instruction
|
||||||
static bool ia64_decode_instruction(ia64_instruction_t *inst, unsigned long *ctx)
|
static bool ia64_decode_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
|
||||||
{
|
{
|
||||||
const int major = (inst->inst >> 37) & 0xf;
|
const int major = (inst->inst >> 37) & 0xf;
|
||||||
|
|
||||||
@ -1604,15 +1597,15 @@ static bool ia64_decode_instruction(ia64_instruction_t *inst, unsigned long *ctx
|
|||||||
memset(&inst->operands[0], 0, sizeof(inst->operands));
|
memset(&inst->operands[0], 0, sizeof(inst->operands));
|
||||||
|
|
||||||
switch (major) {
|
switch (major) {
|
||||||
case 0x0: return ia64_decode_instruction_0(inst, ctx);
|
case 0x0: return ia64_decode_instruction_0(inst, IA64_CONTEXT);
|
||||||
case 0x4: return ia64_decode_instruction_4(inst, ctx);
|
case 0x4: return ia64_decode_instruction_4(inst, IA64_CONTEXT);
|
||||||
case 0x5: return ia64_decode_instruction_5(inst, ctx);
|
case 0x5: return ia64_decode_instruction_5(inst, IA64_CONTEXT);
|
||||||
case 0x8: return ia64_decode_instruction_8(inst, ctx);
|
case 0x8: return ia64_decode_instruction_8(inst, IA64_CONTEXT);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ia64_emulate_instruction(ia64_instruction_t *inst, unsigned long *ctx)
|
static bool ia64_emulate_instruction(ia64_instruction_t *inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
|
||||||
{
|
{
|
||||||
// XXX: handle Register NaT Consumption fault?
|
// XXX: handle Register NaT Consumption fault?
|
||||||
// XXX: this simple emulator assumes instructions in a bundle
|
// XXX: this simple emulator assumes instructions in a bundle
|
||||||
@ -1743,19 +1736,19 @@ static bool ia64_emulate_instruction(ia64_instruction_t *inst, unsigned long *ct
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ia64_emulate_instruction(unsigned long raw_inst, unsigned long *ctx)
|
static bool ia64_emulate_instruction(unsigned long raw_inst, IA64_CONTEXT_TYPE IA64_CONTEXT)
|
||||||
{
|
{
|
||||||
ia64_instruction_t inst;
|
ia64_instruction_t inst;
|
||||||
memset(&inst, 0, sizeof(inst));
|
memset(&inst, 0, sizeof(inst));
|
||||||
inst.inst = raw_inst;
|
inst.inst = raw_inst;
|
||||||
if (!ia64_decode_instruction(&inst, ctx))
|
if (!ia64_decode_instruction(&inst, IA64_CONTEXT))
|
||||||
return false;
|
return false;
|
||||||
return ia64_emulate_instruction(&inst, ctx);
|
return ia64_emulate_instruction(&inst, IA64_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ia64_skip_instruction(unsigned long *ctx)
|
static bool ia64_skip_instruction(IA64_CONTEXT_TYPE IA64_CONTEXT)
|
||||||
{
|
{
|
||||||
unsigned long ip = ctx[IA64_REG_IP];
|
unsigned long ip = IA64_GET_IP();
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
printf("IP: 0x%016lx\n", ip);
|
printf("IP: 0x%016lx\n", ip);
|
||||||
#if 0
|
#if 0
|
||||||
@ -1769,7 +1762,7 @@ static bool ia64_skip_instruction(unsigned long *ctx)
|
|||||||
// Select which decode switch to use
|
// Select which decode switch to use
|
||||||
ia64_instruction_t inst;
|
ia64_instruction_t inst;
|
||||||
inst.inst = ia64_get_instruction(ip, ip & 3);
|
inst.inst = ia64_get_instruction(ip, ip & 3);
|
||||||
if (!ia64_decode_instruction(&inst, ctx)) {
|
if (!ia64_decode_instruction(&inst, IA64_CONTEXT)) {
|
||||||
fprintf(stderr, "ERROR: ia64_skip_instruction(): could not decode instruction\n");
|
fprintf(stderr, "ERROR: ia64_skip_instruction(): could not decode instruction\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1840,7 +1833,7 @@ static bool ia64_skip_instruction(unsigned long *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inst.no_memory = true;
|
inst.no_memory = true;
|
||||||
if (!ia64_emulate_instruction(&inst, ctx)) {
|
if (!ia64_emulate_instruction(&inst, IA64_CONTEXT)) {
|
||||||
fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate fault instruction\n");
|
fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate fault instruction\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1863,9 +1856,9 @@ static bool ia64_skip_instruction(unsigned long *ctx)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (emulate_next) {
|
if (emulate_next && !IA64_CAN_PATCH_IP_SLOT) {
|
||||||
while (slot < 3) {
|
while (slot < 3) {
|
||||||
if (!ia64_emulate_instruction(ia64_get_instruction(ip, slot), ctx)) {
|
if (!ia64_emulate_instruction(ia64_get_instruction(ip, slot), IA64_CONTEXT)) {
|
||||||
fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate instruction\n");
|
fprintf(stderr, "ERROR: ia64_skip_instruction(): could not emulate instruction\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1873,9 +1866,14 @@ static bool ia64_skip_instruction(unsigned long *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx[IA64_REG_IP] = (ip & ~3ul) + 16;
|
#if IA64_CAN_PATCH_IP_SLOT
|
||||||
|
if ((slot = ip & 3) < 2)
|
||||||
|
IA64_SET_IP((ip & ~3ul) + (slot + 1));
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
IA64_SET_IP((ip & ~3ul) + 16);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
printf("IP: 0x%016lx\n", ctx[IA64_REG_IP]);
|
printf("IP: 0x%016lx\n", IA64_GET_IP());
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user