Special casing some VC++ traps.
This commit is contained in:
parent
ef75042f38
commit
2a68a1b35b
|
@ -309,8 +309,15 @@ int Translate_DEBUG_BREAK_TRUE(TranslationContext& ctx, Instr* i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t IntCode_TRAP(IntCodeState& ics, const IntCode* i) {
|
uint32_t IntCode_TRAP(IntCodeState& ics, const IntCode* i) {
|
||||||
// 0x0FE00014 is a 'debug print' where r3 = buffer r4 = length
|
|
||||||
// TODO(benvanik): post software interrupt to debugger.
|
// TODO(benvanik): post software interrupt to debugger.
|
||||||
|
switch (i->flags) {
|
||||||
|
case 20:
|
||||||
|
// 0x0FE00014 is a 'debug print' where r3 = buffer r4 = length
|
||||||
|
break;
|
||||||
|
case 22:
|
||||||
|
// Always trap?
|
||||||
|
break;
|
||||||
|
}
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
return IA_NEXT;
|
return IA_NEXT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,10 +219,23 @@ void X64Emitter::DebugBreak() {
|
||||||
db(0xCC);
|
db(0xCC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::Trap() {
|
void X64Emitter::Trap(uint16_t trap_type) {
|
||||||
|
switch (trap_type) {
|
||||||
|
case 20:
|
||||||
// 0x0FE00014 is a 'debug print' where r3 = buffer r4 = length
|
// 0x0FE00014 is a 'debug print' where r3 = buffer r4 = length
|
||||||
|
// TODO(benvanik): debug print at runtime.
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
case 22:
|
||||||
|
// Always trap?
|
||||||
// TODO(benvanik): post software interrupt to debugger.
|
// TODO(benvanik): post software interrupt to debugger.
|
||||||
db(0xCC);
|
db(0xCC);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
XELOGW("Unknown trap type %d", trap_type);
|
||||||
|
db(0xCC);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::UnimplementedInstr(const hir::Instr* i) {
|
void X64Emitter::UnimplementedInstr(const hir::Instr* i) {
|
||||||
|
|
|
@ -117,7 +117,7 @@ public:
|
||||||
void MarkSourceOffset(const hir::Instr* i);
|
void MarkSourceOffset(const hir::Instr* i);
|
||||||
|
|
||||||
void DebugBreak();
|
void DebugBreak();
|
||||||
void Trap();
|
void Trap(uint16_t trap_type = 0);
|
||||||
void UnimplementedInstr(const hir::Instr* i);
|
void UnimplementedInstr(const hir::Instr* i);
|
||||||
void UnimplementedExtern(const hir::Instr* i);
|
void UnimplementedExtern(const hir::Instr* i);
|
||||||
|
|
||||||
|
|
|
@ -191,7 +191,7 @@ EMITTER_OPCODE_TABLE(
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
EMITTER(TRAP, MATCH(I<OPCODE_TRAP, VoidOp>)) {
|
EMITTER(TRAP, MATCH(I<OPCODE_TRAP, VoidOp>)) {
|
||||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||||
e.Trap();
|
e.Trap(i.instr->flags);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
EMITTER_OPCODE_TABLE(
|
EMITTER_OPCODE_TABLE(
|
||||||
|
@ -207,7 +207,7 @@ EMITTER(TRAP_TRUE_I8, MATCH(I<OPCODE_TRAP_TRUE, VoidOp, I8<>>)) {
|
||||||
e.test(i.src1, i.src1);
|
e.test(i.src1, i.src1);
|
||||||
Xbyak::Label skip;
|
Xbyak::Label skip;
|
||||||
e.jz(skip);
|
e.jz(skip);
|
||||||
e.Trap();
|
e.Trap(i.instr->flags);
|
||||||
e.L(skip);
|
e.L(skip);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -216,7 +216,7 @@ EMITTER(TRAP_TRUE_I16, MATCH(I<OPCODE_TRAP_TRUE, VoidOp, I16<>>)) {
|
||||||
e.test(i.src1, i.src1);
|
e.test(i.src1, i.src1);
|
||||||
Xbyak::Label skip;
|
Xbyak::Label skip;
|
||||||
e.jz(skip);
|
e.jz(skip);
|
||||||
e.Trap();
|
e.Trap(i.instr->flags);
|
||||||
e.L(skip);
|
e.L(skip);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -225,7 +225,7 @@ EMITTER(TRAP_TRUE_I32, MATCH(I<OPCODE_TRAP_TRUE, VoidOp, I32<>>)) {
|
||||||
e.test(i.src1, i.src1);
|
e.test(i.src1, i.src1);
|
||||||
Xbyak::Label skip;
|
Xbyak::Label skip;
|
||||||
e.jz(skip);
|
e.jz(skip);
|
||||||
e.Trap();
|
e.Trap(i.instr->flags);
|
||||||
e.L(skip);
|
e.L(skip);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -234,7 +234,7 @@ EMITTER(TRAP_TRUE_I64, MATCH(I<OPCODE_TRAP_TRUE, VoidOp, I64<>>)) {
|
||||||
e.test(i.src1, i.src1);
|
e.test(i.src1, i.src1);
|
||||||
Xbyak::Label skip;
|
Xbyak::Label skip;
|
||||||
e.jz(skip);
|
e.jz(skip);
|
||||||
e.Trap();
|
e.Trap(i.instr->flags);
|
||||||
e.L(skip);
|
e.L(skip);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -243,7 +243,7 @@ EMITTER(TRAP_TRUE_F32, MATCH(I<OPCODE_TRAP_TRUE, VoidOp, F32<>>)) {
|
||||||
e.vptest(i.src1, i.src1);
|
e.vptest(i.src1, i.src1);
|
||||||
Xbyak::Label skip;
|
Xbyak::Label skip;
|
||||||
e.jz(skip);
|
e.jz(skip);
|
||||||
e.Trap();
|
e.Trap(i.instr->flags);
|
||||||
e.L(skip);
|
e.L(skip);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -252,7 +252,7 @@ EMITTER(TRAP_TRUE_F64, MATCH(I<OPCODE_TRAP_TRUE, VoidOp, F64<>>)) {
|
||||||
e.vptest(i.src1, i.src1);
|
e.vptest(i.src1, i.src1);
|
||||||
Xbyak::Label skip;
|
Xbyak::Label skip;
|
||||||
e.jz(skip);
|
e.jz(skip);
|
||||||
e.Trap();
|
e.Trap(i.instr->flags);
|
||||||
e.L(skip);
|
e.L(skip);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -482,6 +482,12 @@ XEEMITTER(twi, 0x0C000000, D )(PPCHIRBuilder& f, InstrData& i) {
|
||||||
// if (a = EXTS(SI)) & TO[2] then TRAP
|
// if (a = EXTS(SI)) & TO[2] then TRAP
|
||||||
// if (a <u EXTS(SI)) & TO[3] then TRAP
|
// if (a <u EXTS(SI)) & TO[3] then TRAP
|
||||||
// if (a >u EXTS(SI)) & TO[4] then TRAP
|
// if (a >u EXTS(SI)) & TO[4] then TRAP
|
||||||
|
if (i.D.RA == 0 && i.D.RT == 0x1F) {
|
||||||
|
// This is a special trap. Probably.
|
||||||
|
uint16_t type = (uint16_t)XEEXTS16(i.D.DS);
|
||||||
|
f.Trap(type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Value* ra = f.SignExtend(f.Truncate(
|
Value* ra = f.SignExtend(f.Truncate(
|
||||||
f.LoadGPR(i.D.RA), INT32_TYPE), INT64_TYPE);
|
f.LoadGPR(i.D.RA), INT32_TYPE), INT64_TYPE);
|
||||||
Value* rb = f.LoadConstant(XEEXTS16(i.D.DS));
|
Value* rb = f.LoadConstant(XEEXTS16(i.D.DS));
|
||||||
|
|
|
@ -577,21 +577,21 @@ void HIRBuilder::DebugBreakTrue(Value* cond) {
|
||||||
EndBlock();
|
EndBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIRBuilder::Trap() {
|
void HIRBuilder::Trap(uint16_t trap_code) {
|
||||||
Instr* i = AppendInstr(OPCODE_TRAP_info, 0);
|
Instr* i = AppendInstr(OPCODE_TRAP_info, trap_code);
|
||||||
i->src1.value = i->src2.value = i->src3.value = NULL;
|
i->src1.value = i->src2.value = i->src3.value = NULL;
|
||||||
EndBlock();
|
EndBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIRBuilder::TrapTrue(Value* cond) {
|
void HIRBuilder::TrapTrue(Value* cond, uint16_t trap_code) {
|
||||||
if (cond->IsConstant()) {
|
if (cond->IsConstant()) {
|
||||||
if (cond->IsConstantTrue()) {
|
if (cond->IsConstantTrue()) {
|
||||||
Trap();
|
Trap(trap_code);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instr* i = AppendInstr(OPCODE_TRAP_TRUE_info, 0);
|
Instr* i = AppendInstr(OPCODE_TRAP_TRUE_info, trap_code);
|
||||||
i->set_src1(cond);
|
i->set_src1(cond);
|
||||||
i->src2.value = i->src3.value = NULL;
|
i->src2.value = i->src3.value = NULL;
|
||||||
EndBlock();
|
EndBlock();
|
||||||
|
|
|
@ -71,8 +71,8 @@ public:
|
||||||
void DebugBreak();
|
void DebugBreak();
|
||||||
void DebugBreakTrue(Value* cond);
|
void DebugBreakTrue(Value* cond);
|
||||||
|
|
||||||
void Trap();
|
void Trap(uint16_t trap_code = 0);
|
||||||
void TrapTrue(Value* cond);
|
void TrapTrue(Value* cond, uint16_t trap_code = 0);
|
||||||
|
|
||||||
void Call(runtime::FunctionInfo* symbol_info, uint32_t call_flags = 0);
|
void Call(runtime::FunctionInfo* symbol_info, uint32_t call_flags = 0);
|
||||||
void CallTrue(Value* cond, runtime::FunctionInfo* symbol_info,
|
void CallTrue(Value* cond, runtime::FunctionInfo* symbol_info,
|
||||||
|
|
Loading…
Reference in New Issue