X86: Implement far jmp.

This commit is contained in:
Gabe Black 2009-04-19 03:42:41 -07:00
parent 3b1b21cb15
commit 038225a6ca
3 changed files with 116 additions and 3 deletions

View file

@ -519,7 +519,10 @@
0x1: JMP(Jz);
0x2: decode MODE_SUBMODE {
0x0: UD2();
default: WarnUnimpl::jmp_far_Ap();
0x1: JMP_FAR(Iz);
0x2: JMP_FAR(Iz);
0x3: JMP_FAR_REAL(Iz);
0x4: JMP_FAR_REAL(Iz);
}
0x3: JMP(Jb);
0x4: IN(rAb,rD);
@ -581,7 +584,13 @@
0x2: CALL_NEAR(Ev);
0x3: WarnUnimpl::call_far_Mp();
0x4: JMP(Ev);
0x5: WarnUnimpl::jmp_far_Mp();
0x5: decode MODE_SUBMODE {
0x0: JMP_FAR(Mz);
0x1: JMP_FAR(Mz);
0x2: JMP_FAR(Mz);
0x3: JMP_FAR_REAL(Mz);
0x4: JMP_FAR_REAL(Mz);
}
0x6: PUSH(Ev);
0x7: UD2();
}

View file

@ -90,4 +90,103 @@ def macroop JMP_P
ld t1, seg, riprel, disp
wripi t1, 0
};
def macroop JMP_FAR_M
{
limm t1, 0, dataSize=8
limm t2, 0, dataSize=8
lea t1, seg, sib, disp, dataSize=asz
ld t2, seg, [1, t0, t1], dsz
ld t1, seg, [1, t0, t1]
br rom_label("jmpFarWork")
};
def macroop JMP_FAR_P
{
limm t1, 0, dataSize=8
limm t2, 0, dataSize=8
rdip t7, dataSize=asz
lea t1, seg, riprel, disp, dataSize=asz
ld t2, seg, [1, t0, t1], dsz
ld t1, seg, [1, t0, t1]
br rom_label("jmpFarWork")
};
def macroop JMP_FAR_I
{
# Put the whole far pointer into a register.
limm t2, imm, dataSize=8
# Figure out the width of the offset.
limm t3, dsz, dataSize=8
sll t3, t3, 3, dataSize=8
# Get the selector into t1.
sll t1, t2, t3, dataSize=8
mov t1, t0, t1, dataSize=2
# And get the offset into t2
mov t2, t0, t2
br rom_label("jmpFarWork")
};
def rom
{
extern jmpFarWork:
# t1 has the offset and t2 has the new selector.
# This is intended to run in protected mode.
andi t0, t2, 0xFC, flags=(EZF,), dataSize=2
fault "new GeneralProtection(0)", flags=(CEZF,)
andi t3, t2, 0xF8, dataSize=8
andi t0, t2, 0x4, flags=(EZF,), dataSize=2
br rom_local_label("farJmpGlobalDescriptor"), flags=(CEZF,)
ld t4, tsl, [1, t0, t3], dataSize=8, addressSize=8, atCPL0=True
br rom_local_label("farJmpProcessDescriptor")
farJmpGlobalDescriptor:
ld t4, tsg, [1, t0, t3], dataSize=8, addressSize=8, atCPL0=True
farJmpProcessDescriptor:
rcri t0, t4, 13, flags=(ECF,), dataSize=2
br rom_local_label("farJmpSystemDescriptor"), flags=(nCECF,)
chks t2, t4, CSCheck, dataSize=8
wrdl cs, t4, t2
wrsel cs, t2
wrip t0, t1
eret
farJmpSystemDescriptor:
panic "Far jumps to system descriptors aren't implemented"
eret
};
def macroop JMP_FAR_REAL_M
{
lea t1, seg, sib, disp, dataSize=asz
ld t2, seg, [1, t0, t1], dsz
ld t1, seg, [1, t0, t1]
zexti t3, t1, 15, dataSize=8
slli t3, t3, 4, dataSize=8
wrsel cs, t1, dataSize=2
wrbase cs, t3
wrip t0, t2, dataSize=asz
};
def macroop JMP_FAR_REAL_P
{
panic "Real mode far jump executed in 64 bit mode!"
};
def macroop JMP_FAR_REAL_I
{
# Put the whole far pointer into a register.
limm t2, imm, dataSize=8
# Figure out the width of the offset.
limm t3, dsz, dataSize=8
sll t3, t3, 3, dataSize=8
# Get the selector into t1.
sll t1, t2, t3, dataSize=8
mov t1, t0, t1, dataSize=2
# And get the offset into t2
mov t2, t0, t2
slli t3, t3, 4, dataSize=8
wrsel cs, t1, dataSize=2
wrbase cs, t3
wrip t0, t2, dataSize=asz
};
'''

View file

@ -1102,7 +1102,12 @@ let {{
case SegNoCheck:
break;
case SegCSCheck:
panic("CS checks for far calls/jumps not implemented.\\n");
// Make sure it's the right type
if (desc.s == 0 || desc.type.codeOrData != 1) {
fault = new GeneralProtection(0);
} else if (m5reg.cpl != desc.dpl) {
fault = new GeneralProtection(0);
}
break;
case SegCallGateCheck:
panic("CS checks for far calls/jumps through call gates"