This commit is contained in:
Pavel 2023-08-31 12:08:16 +03:00
parent 3cac400a7e
commit ac50c4ca2b
5 changed files with 692 additions and 174 deletions

View File

@ -22,7 +22,6 @@ type
TRegisterTypeSet=Set of TRegisterType;
t_jit_regs =array of t_jit_reg;
t_jit_int64=array of Int64;
t_jit_link_type=(lnkNone,lnkData,lnkLabel);
@ -74,6 +73,11 @@ type
t_jit_builder=object
Const
ah :t_jit_reg=(ARegValue:((AType:regGeneralH;ASize:os8;AIndex:0),(AType:regNone)));
ch :t_jit_reg=(ARegValue:((AType:regGeneralH;ASize:os8;AIndex:1),(AType:regNone)));
dh :t_jit_reg=(ARegValue:((AType:regGeneralH;ASize:os8;AIndex:2),(AType:regNone)));
bh :t_jit_reg=(ARegValue:((AType:regGeneralH;ASize:os8;AIndex:3),(AType:regNone)));
al :t_jit_reg=(ARegValue:((AType:regGeneral;ASize:os8;AIndex: 0),(AType:regNone)));
cl :t_jit_reg=(ARegValue:((AType:regGeneral;ASize:os8;AIndex: 1),(AType:regNone)));
dl :t_jit_reg=(ARegValue:((AType:regGeneral;ASize:os8;AIndex: 2),(AType:regNone)));
@ -208,32 +212,38 @@ type
Procedure LinkData;
Function SaveTo(ptr:PByte;size:Integer):Integer;
//
procedure _mov (op:Byte;reg:t_jit_reg;mem:t_jit_regs);
procedure _mov (op,op8:Byte;reg:t_jit_reg;mem:t_jit_regs);
procedure _mov (op,op8:Byte;reg0:t_jit_reg;reg1:t_jit_reg);
procedure _addi (op,op8,index:Byte;reg:t_jit_reg;imm:Int64);
procedure _movi (op,op8,index:Byte;reg:t_jit_reg;imm:Int64);
procedure _movi (op,op8,index:Byte;size:TOperandSize;mem:t_jit_regs;imm:Int64);
procedure _movi8 (op,index:Byte;reg:t_jit_reg;imm:Byte);
procedure _movi8 (op,index:Byte;size:TOperandSize;mem:t_jit_regs;imm:Byte);
procedure _push (op,index:Byte;size:TOperandSize;mem:t_jit_regs);
procedure _push (op:Byte;reg:t_jit_reg);
procedure _pushi (size:TOperandSize;imm:Integer);
procedure movq (reg0:t_jit_reg ;reg1:t_jit_reg);
procedure movi (reg:t_jit_reg ;imm:Int64);
procedure movq (reg:t_jit_reg ;mem:t_jit_regs);
procedure movq (reg:t_jit_reg ;mem:t_jit_int64);
procedure movq (mem:t_jit_regs ;reg:t_jit_reg);
procedure movq (mem:t_jit_int64;reg:t_jit_reg);
procedure lea (reg:t_jit_reg ;mem:t_jit_regs);
procedure lea (reg:t_jit_reg ;mem:t_jit_int64);
procedure leaq (reg:t_jit_reg ;mem:t_jit_regs);
procedure addq (mem:t_jit_regs ;reg:t_jit_reg);
procedure addq (mem:t_jit_int64;reg:t_jit_reg);
procedure addq (reg:t_jit_reg ;mem:t_jit_regs);
procedure addq (reg:t_jit_reg ;mem:t_jit_int64);
procedure addq (reg0:t_jit_reg ;reg1:t_jit_reg);
procedure addi (reg:t_jit_reg ;imm:Int64);
procedure addi8 (reg:t_jit_reg ;imm:Byte);
procedure subq (mem:t_jit_regs ;reg:t_jit_reg);
procedure subq (mem:t_jit_int64;reg:t_jit_reg);
procedure subq (reg:t_jit_reg ;mem:t_jit_regs);
procedure subq (reg:t_jit_reg ;mem:t_jit_int64);
procedure subq (reg0:t_jit_reg ;reg1:t_jit_reg);
procedure subi (reg:t_jit_reg ;imm:Int64);
procedure subi8 (reg:t_jit_reg ;imm:Byte);
procedure xorq (reg0:t_jit_reg ;reg1:t_jit_reg);
procedure cmpq (mem:t_jit_regs ;reg:t_jit_reg);
procedure cmpq (reg:t_jit_reg ;mem:t_jit_regs);
procedure cmpq (reg0:t_jit_reg ;reg1:t_jit_reg);
procedure cmpi (reg:t_jit_reg ;imm:Int64);
procedure cmpi (size:TOperandSize;mem:t_jit_regs;imm:Int64);
procedure cmpi8 (reg:t_jit_reg;imm:Byte);
procedure cmpi8 (size:TOperandSize;mem:t_jit_regs;imm:Byte);
procedure push16 (mem:t_jit_regs);
procedure push64 (mem:t_jit_regs);
procedure push (reg:t_jit_reg);
@ -252,6 +262,8 @@ type
procedure vmovups (reg:t_jit_reg ;mem:t_jit_regs);
procedure vmovups (mem:t_jit_regs;reg:t_jit_reg);
procedure vmovdqa (reg0:t_jit_reg;reg1:t_jit_reg);
procedure sahf;
procedure lahf;
end;
operator + (A,B:t_jit_reg):t_jit_reg;
@ -439,23 +451,6 @@ begin
end;
end;
function Sums(mem:t_jit_int64):t_jit_reg;
var
i:Integer;
begin
Result:=Default(t_jit_reg);
if (Length(mem)=0) then
begin
//
end else
begin
For i:=0 to High(mem) do
begin
Result.AOffset:=Result.AOffset+mem[i];
end;
end;
end;
////
procedure t_jit_i_link.set_label(id:Integer);
@ -697,7 +692,7 @@ function t_jit_builder.movj(reg:t_jit_reg;mem:t_jit_regs;_label_id:Integer):t_ji
var
i:Integer;
begin
_mov($8B,reg,mem); //MOV r64, r/m64
movq(reg,mem);
i:=High(AInstructions);
@ -712,7 +707,7 @@ function t_jit_builder.leaj(reg:t_jit_reg;mem:t_jit_regs;_label_id:Integer):t_ji
var
i:Integer;
begin
_mov($8D,reg,mem); //LEA r64,m
leaq(reg,mem);
i:=High(AInstructions);
@ -822,7 +817,7 @@ end;
type
t_modrm_info=object
rexB,rexX,rexR:Boolean;
rexF,rexB,rexX,rexR:Boolean;
ModRM:record
Mode,Index,RM:Byte;
@ -837,6 +832,7 @@ type
procedure build(Index:Byte;mreg:t_jit_reg);
procedure build(reg,mreg:t_jit_reg);
procedure emit(var ji:t_jit_instruction);
procedure emit8(var ji:t_jit_instruction);
end;
procedure t_modrm_info.build(Index:Byte;mreg:t_jit_reg);
@ -962,15 +958,38 @@ begin
AOffset:=mreg.AOffset;
end;
function get_force_rex(const reg:t_jit_reg):Boolean; inline;
begin
Result:=False;
if (reg.ARegValue[0].AType=regGeneral) then
if (reg.ARegValue[0].ASize=os8) then
case reg.ARegValue[0].AIndex of
4..7:Result:=True;
else;
end;
end;
procedure t_modrm_info.build(reg,mreg:t_jit_reg);
begin
ModRM.Index:=reg.ARegValue[0].AIndex;
if (ModRM.Index>=8) then
begin
rexR:=true;
Dec(ModRM.Index,8);
case reg.ARegValue[0].AType of
regGeneralH:
begin
ModRM.Index:=ModRM.Index+4;
end;
else
begin
if (ModRM.Index>=8) then
begin
rexR:=true;
Dec(ModRM.Index,8);
end;
end;
end;
rexF:=get_force_rex(reg);
build(ModRM.Index,mreg);
end;
@ -1007,20 +1026,33 @@ begin
end;
end;
procedure t_jit_builder._mov(op:Byte;reg:t_jit_reg;mem:t_jit_regs);
procedure t_modrm_info.emit8(var ji:t_jit_instruction);
begin
ji.EmitModRM(ModRM.Mode,ModRM.Index,ModRM.RM);
if (ModRM.RM=4) then
begin
ji.EmitSIB(SIB.Scale,SIB.Index,SIB.Base);
end;
ji.EmitByte(AOffset); //1
end;
procedure t_jit_builder._mov(op,op8:Byte;reg:t_jit_reg;mem:t_jit_regs);
var
mreg:t_jit_reg;
rexW:Boolean;
Prefix:Byte;
modrm_info:t_modrm_info;
ji:t_jit_instruction;
begin
Assert(is_one_reg(reg));
Assert(is_reg_size(reg,[os16,os32,os64]));
Assert(is_reg_size(reg,[os8,os16,os32,os64]));
Assert(is_reg_type(reg,[regGeneral]));
Assert(is_reg_type(reg,[regGeneral,regGeneralH]));
Assert(reg.ARegValue[0].AScale<=1);
@ -1033,9 +1065,23 @@ begin
ji:=default_jit_instruction;
rexW:=False;
if (reg.ARegValue[0].ASize=os64) then
begin
rexW:=True;
Prefix:=0;
case reg.ARegValue[0].ASize of
os8:
begin
op:=op8;
end;
os16:
begin
Prefix:=$66;
end;
os32:;
os64:
begin
rexW:=True;
end;
else;
end;
modrm_info:=Default(t_modrm_info);
@ -1044,9 +1090,9 @@ begin
ji.EmitSelector(mreg.ASegment);
if (reg.ARegValue[0].ASize=os16) then
if (Prefix<>0) then
begin
ji.EmitByte($66); //Operand-size override prefix (16)
ji.EmitByte(Prefix); //Operand-size override prefix (16)
end;
if (mreg.ARegValue[0].ASize=os32) then
@ -1054,12 +1100,8 @@ begin
ji.EmitByte($67); //Address-size override prefix (32)
end;
if modrm_info.rexB or modrm_info.rexX or modrm_info.rexR or rexW then
if modrm_info.rexF or modrm_info.rexB or modrm_info.rexX or modrm_info.rexR or rexW then
begin
//rexB $4x bit 0: Extension of the ModR/M r/m field, SIB base field, or Opcode reg field
//rexX $4x bit 1: Extension of the SIB index field
//rexR $4x bit 2: Extension of the ModR/M reg field
//rexW $4x bit 3: 64 Bit Operand Size
ji.EmitREX(modrm_info.rexB,modrm_info.rexX,modrm_info.rexR,rexW);
end;
@ -1072,7 +1114,7 @@ end;
procedure t_jit_builder._mov(op,op8:Byte;reg0:t_jit_reg;reg1:t_jit_reg);
var
rexB,rexR,rexW:Boolean;
rexF,rexB,rexR,rexW:Boolean;
ModRM:record
Index,RM:Byte;
@ -1096,8 +1138,11 @@ begin
Assert(reg0.ARegValue[0].ASize=reg1.ARegValue[0].ASize);
Assert(get_force_rex(reg0)=get_force_rex(reg1));
ji:=default_jit_instruction;
rexF:=false;
rexB:=false;
rexR:=false;
rexW:=false;
@ -1134,12 +1179,14 @@ begin
Dec(ModRM.RM,8);
end;
rexF:=get_force_rex(reg0);
if (Prefix<>0) then
begin
ji.EmitByte(Prefix); //Operand-size override prefix (16)
end;
if rexB or rexR or rexW then
if rexF or rexB or rexR or rexW then
begin
ji.EmitREX(rexB,False,rexR,rexW);
end;
@ -1153,9 +1200,9 @@ end;
////
procedure t_jit_builder._addi(op,op8,index:Byte;reg:t_jit_reg;imm:Int64);
procedure t_jit_builder._movi(op,op8,index:Byte;reg:t_jit_reg;imm:Int64);
var
rexB,rexW:Boolean;
rexF,rexB,rexW:Boolean;
RM,Prefix:Byte;
@ -1170,6 +1217,7 @@ begin
ji:=default_jit_instruction;
rexF:=false;
rexB:=false;
rexW:=false;
Prefix:=0;
@ -1181,6 +1229,8 @@ begin
Dec(RM,8);
end;
rexF:=get_force_rex(reg);
case reg.ARegValue[0].ASize of
os8:
begin
@ -1203,7 +1253,7 @@ begin
ji.EmitByte(Prefix); //Operand-size override prefix (16)
end;
if rexB or rexW then
if rexF or rexB or rexW then
begin
ji.EmitREX(rexB,False,False,rexW);
end;
@ -1223,6 +1273,203 @@ begin
_add(ji);
end;
procedure t_jit_builder._movi(op,op8,index:Byte;size:TOperandSize;mem:t_jit_regs;imm:Int64);
var
mreg:t_jit_reg;
rexW:Boolean;
Prefix:Byte;
modrm_info:t_modrm_info;
ji:t_jit_instruction;
begin
Assert(size in [os8,os16,os32,os64]);
mreg:=Sums(mem);
Assert(is_reg_size(mreg,[os0,os32,os64]));
Assert(is_reg_type(mreg,[regNone,regGeneral,regRip]));
Assert(is_valid_scale(mreg));
ji:=default_jit_instruction;
rexW:=False;
Prefix:=0;
case size of
os8:
begin
op:=op8;
end;
os16:
begin
Prefix:=$66;
end;
os32:;
os64:
begin
rexW:=True;
end;
else;
end;
modrm_info:=Default(t_modrm_info);
modrm_info.build(Index,mreg);
ji.EmitSelector(mreg.ASegment);
if (Prefix<>0) then
begin
ji.EmitByte(Prefix); //Operand-size override prefix (16)
end;
if (mreg.ARegValue[0].ASize=os32) then
begin
ji.EmitByte($67); //Address-size override prefix (32)
end;
if modrm_info.rexF or modrm_info.rexB or modrm_info.rexX or modrm_info.rexR or rexW then
begin
ji.EmitREX(modrm_info.rexB,modrm_info.rexX,modrm_info.rexR,rexW);
end;
ji.EmitByte(op);
modrm_info.emit(ji);
_add(ji);
end;
procedure t_jit_builder._movi8(op,index:Byte;reg:t_jit_reg;imm:Byte);
var
rexF,rexB,rexW:Boolean;
RM,Prefix:Byte;
ji:t_jit_instruction;
begin
Assert(is_one_reg(reg));
Assert(is_reg_size(reg,[os16,os32,os64]));
Assert(is_reg_type(reg,[regGeneral]));
Assert(reg.ARegValue[0].AScale<=1);
ji:=default_jit_instruction;
rexF:=false;
rexB:=false;
rexW:=false;
Prefix:=0;
RM:=reg.ARegValue[0].AIndex;
if (RM>=8) then
begin
rexB:=true;
Dec(RM,8);
end;
rexF:=get_force_rex(reg);
case reg.ARegValue[0].ASize of
os16:
begin
Prefix:=$66;
end;
os32:;
os64:
begin
rexW:=True;
end;
else;
end;
if (Prefix<>0) then
begin
ji.EmitByte(Prefix); //Operand-size override prefix (16)
end;
if rexF or rexB or rexW then
begin
ji.EmitREX(rexB,False,False,rexW);
end;
ji.EmitByte(op);
ji.EmitModRM(3,index,RM);
ji.EmitByte(imm);
_add(ji);
end;
procedure t_jit_builder._movi8(op,index:Byte;size:TOperandSize;mem:t_jit_regs;imm:Byte);
var
mreg:t_jit_reg;
rexW:Boolean;
Prefix:Byte;
modrm_info:t_modrm_info;
ji:t_jit_instruction;
begin
Assert(size in [os16,os32,os64]);
mreg:=Sums(mem);
Assert(is_reg_size(mreg,[os0,os32,os64]));
Assert(is_reg_type(mreg,[regNone,regGeneral,regRip]));
Assert(is_valid_scale(mreg));
ji:=default_jit_instruction;
rexW:=False;
Prefix:=0;
case size of
os16:
begin
Prefix:=$66;
end;
os32:;
os64:
begin
rexW:=True;
end;
else;
end;
modrm_info:=Default(t_modrm_info);
modrm_info.build(Index,mreg);
ji.EmitSelector(mreg.ASegment);
if (Prefix<>0) then
begin
ji.EmitByte(Prefix); //Operand-size override prefix (16)
end;
if (mreg.ARegValue[0].ASize=os32) then
begin
ji.EmitByte($67); //Address-size override prefix (32)
end;
if modrm_info.rexF or modrm_info.rexB or modrm_info.rexX or modrm_info.rexR or rexW then
begin
ji.EmitREX(modrm_info.rexB,modrm_info.rexX,modrm_info.rexR,rexW);
end;
ji.EmitByte(op);
modrm_info.emit8(ji);
_add(ji);
end;
////
procedure t_jit_builder._push(op,index:Byte;size:TOperandSize;mem:t_jit_regs);
@ -1259,7 +1506,7 @@ begin
ji.EmitByte($67); //Address-size override prefix (32)
end;
if modrm_info.rexB or modrm_info.rexX or modrm_info.rexR then
if modrm_info.rexF or modrm_info.rexB or modrm_info.rexX or modrm_info.rexR then
begin
ji.EmitREX(modrm_info.rexB,modrm_info.rexX,modrm_info.rexR,False);
end;
@ -1375,7 +1622,7 @@ end;
procedure t_jit_builder.movi(reg:t_jit_reg;imm:Int64);
var
rexB,rexW:Boolean;
rexF,rexB,rexW:Boolean;
Index,Prefix,op:Byte;
@ -1390,6 +1637,7 @@ begin
ji:=default_jit_instruction;
rexF:=false;
rexB:=false;
rexW:=false;
Prefix:=0;
@ -1401,6 +1649,8 @@ begin
Dec(Index,8);
end;
rexF:=get_force_rex(reg);
case reg.ARegValue[0].ASize of
os8:
begin
@ -1428,7 +1678,7 @@ begin
ji.EmitByte(Prefix); //Operand-size override prefix (16)
end;
if rexB or rexW then
if rexF or rexB or rexW then
begin
ji.EmitREX(rexB,False,False,rexW);
end;
@ -1448,56 +1698,33 @@ end;
procedure t_jit_builder.movq(reg:t_jit_reg;mem:t_jit_regs);
begin
_mov($8B,reg,mem); //MOV r64, r/m64
end;
procedure t_jit_builder.movq(reg:t_jit_reg;mem:t_jit_int64);
begin
movq(reg,[Sums(mem)]);
_mov($8B,$8A,reg,mem); //MOV r64, r/m64
end;
procedure t_jit_builder.movq(mem:t_jit_regs;reg:t_jit_reg);
begin
_mov($89,reg,mem); //MOV r/m64, r64
end;
procedure t_jit_builder.movq(mem:t_jit_int64;reg:t_jit_reg);
begin
movq([Sums(mem)],reg);
_mov($89,$88,reg,mem); //MOV r/m64, r64
end;
//
procedure t_jit_builder.lea(reg:t_jit_reg;mem:t_jit_regs);
procedure t_jit_builder.leaq(reg:t_jit_reg;mem:t_jit_regs);
begin
_mov($8D,reg,mem); //LEA r64,m
end;
Assert(is_reg_size(reg,[os16,os32,os64]));
procedure t_jit_builder.lea(reg:t_jit_reg;mem:t_jit_int64);
begin
lea(reg,[Sums(mem)]);
_mov($8D,$8D,reg,mem); //LEA r64,m
end;
//
procedure t_jit_builder.addq(mem:t_jit_regs;reg:t_jit_reg);
begin
_mov($01,reg,mem); //ADD r/m64, r64
end;
procedure t_jit_builder.addq(mem:t_jit_int64;reg:t_jit_reg);
begin
addq([Sums(mem)],reg);
_mov($01,$00,reg,mem); //ADD r/m64, r64
end;
procedure t_jit_builder.addq(reg:t_jit_reg;mem:t_jit_regs);
begin
_mov($03,reg,mem); //ADD r64, r/m64
end;
procedure t_jit_builder.addq(reg:t_jit_reg;mem:t_jit_int64);
begin
addq(reg,[Sums(mem)]);
_mov($03,$02,reg,mem); //ADD r64, r/m64
end;
procedure t_jit_builder.addq(reg0:t_jit_reg;reg1:t_jit_reg);
@ -1507,29 +1734,24 @@ end;
procedure t_jit_builder.addi(reg:t_jit_reg;imm:Int64);
begin
_addi($81,$80,0,reg,imm);
_movi($81,$80,0,reg,imm);
end;
procedure t_jit_builder.addi8(reg:t_jit_reg;imm:Byte);
begin
_movi8($83,0,reg,imm);
end;
//
procedure t_jit_builder.subq(mem:t_jit_regs;reg:t_jit_reg);
begin
_mov($29,reg,mem); //SUB r/m64, r64
end;
procedure t_jit_builder.subq(mem:t_jit_int64;reg:t_jit_reg);
begin
addq([Sums(mem)],reg);
_mov($29,$28,reg,mem); //SUB r/m64, r64
end;
procedure t_jit_builder.subq(reg:t_jit_reg;mem:t_jit_regs);
begin
_mov($2B,reg,mem); //SUB r64, r/m64
end;
procedure t_jit_builder.subq(reg:t_jit_reg;mem:t_jit_int64);
begin
addq(reg,[Sums(mem)]);
_mov($2B,$2A,reg,mem); //SUB r64, r/m64
end;
procedure t_jit_builder.subq(reg0:t_jit_reg;reg1:t_jit_reg);
@ -1539,9 +1761,59 @@ end;
procedure t_jit_builder.subi(reg:t_jit_reg;imm:Int64);
begin
_addi($81,$80,5,reg,imm);
_movi($81,$80,5,reg,imm);
end;
procedure t_jit_builder.subi8(reg:t_jit_reg;imm:Byte);
begin
_movi8($83,5,reg,imm);
end;
///
procedure t_jit_builder.xorq(reg0:t_jit_reg;reg1:t_jit_reg);
begin
_mov($31,$30,reg0,reg1);
end;
///
procedure t_jit_builder.cmpq(mem:t_jit_regs;reg:t_jit_reg);
begin
_mov($39,$38,reg,mem);
end;
procedure t_jit_builder.cmpq(reg:t_jit_reg;mem:t_jit_regs);
begin
_mov($3B,$3A,reg,mem);
end;
procedure t_jit_builder.cmpq(reg0:t_jit_reg;reg1:t_jit_reg);
begin
_mov($39,$38,reg0,reg1);
end;
procedure t_jit_builder.cmpi(reg:t_jit_reg;imm:Int64);
begin
_movi($81,$80,7,reg,imm);
end;
procedure t_jit_builder.cmpi(size:TOperandSize;mem:t_jit_regs;imm:Int64);
begin
_movi($81,$80,7,size,mem,imm);
end;
procedure t_jit_builder.cmpi8(reg:t_jit_reg;imm:Byte);
begin
_movi8($83,7,reg,imm);
end;
procedure t_jit_builder.cmpi8(size:TOperandSize;mem:t_jit_regs;imm:Byte);
begin
_movi8($83,7,size,mem,imm);
end;
///
procedure t_jit_builder.push16(mem:t_jit_regs);
@ -1762,7 +2034,27 @@ begin
_add(ji);
end;
procedure t_jit_builder.sahf;
var
ji:t_jit_instruction;
begin
ji:=default_jit_instruction;
ji.EmitByte($9E);
_add(ji);
end;
procedure t_jit_builder.lahf;
var
ji:t_jit_instruction;
begin
ji:=default_jit_instruction;
ji.EmitByte($9F);
_add(ji);
end;
end.

View File

@ -286,7 +286,7 @@ begin
addr:=SCE_REPLAY_EXEC_START;
end;
end else
if (p_proc.p_sce_replay_exec=0) and
if (p_proc.p_sce_replay_exec<>0) and
(addr<QWORD($ff0000001)) and
((length+addr)>QWORD($7efffffff)) then
begin

View File

@ -662,10 +662,8 @@ asm
movqq %rax,%r11 //save rax
movqq %rcx,%r10 //save rcx
lahf //load to AH
shr $8,%rax
andl $0xFF,%rax //filter flags
movqq %rax,%rcx //save flags
lahf //load to AH
movb %ah,%ch //save flags to CH
movqq %gs:teb.thread,%rax //curkthread
test %rax,%rax
@ -676,6 +674,9 @@ asm
andl NOT_PCB_FULL_IRET,kthread.pcb_flags(%rax) //clear PCB_FULL_IRET
movqq $0 ,kthread.td_frame.tf_rflags(%rax) //clear
movb %ch ,kthread.td_frame.tf_rflags(%rax) //save flags
movqq %rdi,kthread.td_frame.tf_rdi (%rax)
movqq %rsi,kthread.td_frame.tf_rsi (%rax)
movqq %rdx,kthread.td_frame.tf_rdx (%rax)
@ -690,7 +691,6 @@ asm
movqq %r13,kthread.td_frame.tf_r13 (%rax)
movqq %r14,kthread.td_frame.tf_r14 (%rax)
movqq %r15,kthread.td_frame.tf_r15 (%rax)
movqq %rcx,kthread.td_frame.tf_rflags(%rax)
movqq $0 ,kthread.td_frame.tf_trapno(%rax)
movqq $0 ,kthread.td_frame.tf_addr (%rax)
@ -720,8 +720,9 @@ asm
jne _ast
//Restore preserved registers.
movqq kthread.td_frame.tf_rflags(%rcx),%rax
shl $8,%rax
//get flags
movb kthread.td_frame.tf_rflags(%rcx),%ah
sahf //restore flags
movqq kthread.td_frame.tf_rdi(%rcx),%rdi
@ -744,10 +745,9 @@ asm
//fail (curkthread=nil)
_fail:
movqq %rcx,%rax //get flags
shl $8,%rax
or $1,%ah //CF
sahf //restore flags
movb %ch,%ah //get flags
or $1,%ah //set CF
sahf //restore flags
movqq $14,%rax //EFAULT
movqq $0,%rdx
@ -874,9 +874,8 @@ asm
test %rsp,%rsp
jz _fail
shr $8,%rax
andl $0xFF,%rax //filter flags
movqq %rax,kthread.td_frame.tf_rflags(%rsp) //save flags
movqq $0 ,kthread.td_frame.tf_rflags(%rsp) //clear
movb %ah,kthread.td_frame.tf_rflags(%rsp) //save flags
movqq %gs:teb.jit_rax,%rax //load %rax
movqq %rax,kthread.td_frame.tf_rax(%rsp) //save %rax
@ -940,8 +939,7 @@ asm
movqq %rax,%gs:teb.jitcall //save ret
//get flags
movqq kthread.td_frame.tf_rflags(%rcx),%rax
shl $8,%rax
movb kthread.td_frame.tf_rflags(%rcx),%ah
sahf //restore flags
movqq kthread.td_frame.tf_rdi(%rcx),%rdi
@ -1008,11 +1006,11 @@ function IS_TRAP_FUNC(rip:qword):Boolean;
begin
Result:=(
(rip>=QWORD(@fast_syscall)) and
(rip<=(QWORD(@fast_syscall)+$1AA)) //fast_syscall func size
(rip<=(QWORD(@fast_syscall)+$19C)) //fast_syscall func size
) or
(
(rip>=QWORD(@jit_call)) and
(rip<=(QWORD(@jit_call)+$240)) //jit_call func size
(rip<=(QWORD(@jit_call)+$23C)) //jit_call func size
);
end;

View File

@ -178,6 +178,7 @@ begin
case p^.ExceptionRecord^.ExceptionCode of
FPC_EXCEPTION_CODE :Exit;
EXCEPTION_BREAKPOINT :Exit;
EXCEPTION_SET_THREADNAME:Exit;
end;
@ -206,6 +207,7 @@ begin
case p^.ExceptionRecord^.ExceptionCode of
FPC_EXCEPTION_CODE :Exit;
EXCEPTION_BREAKPOINT :Exit;
EXCEPTION_SET_THREADNAME:Exit;
end;
@ -252,6 +254,7 @@ begin
write(stderr,msg);
Writeln(stderr,' (',FName,', line ',LineNo,').');
print_backtrace(stderr,Get_pc_addr,get_frame,0);
DebugBreak;
md_halt(217);
end;

View File

@ -85,10 +85,10 @@ begin
os8:
begin
case RegValue.AIndex of
0:Result := @p_kthread(nil)^.td_frame.tf_rax+1;
1:Result := @p_kthread(nil)^.td_frame.tf_rcx+1;
2:Result := @p_kthread(nil)^.td_frame.tf_rdx+1;
3:Result := @p_kthread(nil)^.td_frame.tf_rbx+1;
0:Result := (@p_kthread(nil)^.td_frame.tf_rax)+1;
1:Result := (@p_kthread(nil)^.td_frame.tf_rcx)+1;
2:Result := (@p_kthread(nil)^.td_frame.tf_rdx)+1;
3:Result := (@p_kthread(nil)^.td_frame.tf_rbx)+1;
else;
end;
end;
@ -408,7 +408,7 @@ begin
adr:=t_jit_builder.rdi;
adr.ARegValue[0].ASize:=RegValue[0].ASize;
tdr:=t_jit_builder.rsi;
tdr:=t_jit_builder.rcx;
with ctx.builder do
begin
@ -417,13 +417,16 @@ begin
i:=GetFrameOffsetInt(RegValue[0]);
Assert(i<>0,'build_lea');
//xor adr,adr needed
if (RegValue[0].ASize<>os64) then
begin
xorq(rdi,rdi);
end;
movq(adr,[tdr+i]);
if (RegValue[0].AScale>1) then
begin
lea(adr,[adr*RegValue[0].AScale])
leaq(adr,[adr*RegValue[0].AScale])
end;
if (RegValue[1].AType<>regNone) then
@ -440,48 +443,55 @@ begin
begin
with ctx.builder do
begin
lea(adr,[adr+ofs]);
leaq(adr,[adr+ofs]);
end;
end;
end;
//
procedure build_mov(var ctx:t_jit_context;id:Byte;memop:t_memop_type);
var
i,copy_size:Integer;
imm:Int64;
link:t_jit_i_link;
dst:t_jit_reg;
procedure get_size_info(Size:TOperandSize;var byte_size:Integer;var reg:t_jit_reg);
begin
case ctx.din.Operand[id].Size of
case Size of
os8:
begin
byte_size:=1;
reg:=t_jit_builder.sil;
end;
os16:
begin
byte_size:=2;
reg:=t_jit_builder.si;
end;
os32:
begin
copy_size:=4;
dst:=t_jit_builder.esi;
byte_size:=4;
reg:=t_jit_builder.esi;
end;
os64:
begin
copy_size:=8;
dst:=t_jit_builder.rsi;
end
byte_size:=8;
reg:=t_jit_builder.rsi;
end;
else
begin
Writeln('build_mov (',ctx.din.Operand[id].Size,')');
Assert(false,'build_mov (size)');
Writeln('get_size_info (',Size,')');
Assert(false,'get_size_info (size)');
end;
end;
end;
if (ctx.din.Operand[1].Size<>ctx.din.Operand[2].Size) then
begin
Writeln(ctx.din.OpCode.Opcode,' ',
ctx.din.OpCode.Suffix,' ',
ctx.din.Operand[1].Size,' ',
ctx.din.Operand[2].Size);
procedure build_mov(var ctx:t_jit_context;id:Byte;memop:t_memop_type);
var
i,copy_size,reg_size:Integer;
imm:Int64;
link:t_jit_i_link;
mem,reg:t_jit_reg;
begin
Assert(false,'TODO');
end;
get_size_info(ctx.din.Operand[get_lea_id(memop)].Size,copy_size,mem);
get_size_info(ctx.din.Operand[id].Size,reg_size,reg);
case memop of
moCopyout:
@ -490,33 +500,54 @@ begin
begin
//input:rdi
link:=leaj(rsi,[rip+$FFFF],-1);
if (copy_size=1) then
begin
call(@uplift); //input:rdi output:rax=rdi
end else
begin
link:=leaj(rsi,[rip+$FFFF],-1);
movi(edx,copy_size);
movi(edx,copy_size);
call(@copyout_mov); //rdi,rsi,edx
call(@copyout_mov); //rdi,rsi,edx
reta;
reta;
//input:rdi
//input:rdi
link._label:=_label;
link._label:=_label;
end;
imm:=0;
if GetTargetOfs(ctx,id,imm) then
begin
//imm const
movi(dst,imm);
movq([rdi],dst); //TODO movi([rdi],imm);
if (copy_size>reg_size) or (imm=0) then
begin
xorq(rsi,rsi);
end;
if (imm<>0) then
begin
movi(reg,imm);
end;
movq([rdi],mem); //TODO movi([rdi],imm);
end else
begin
movq(rax,[GS+Integer(teb_thread)]);
movq(rcx,[GS+Integer(teb_thread)]);
i:=GetFrameOffsetInt(ctx.din.Operand[id].RegValue[0]);
Assert(i<>0,'build_mov');
movq(dst,[rax+i]);
movq([rdi],dst);
if (copy_size>reg_size) then
begin
xorq(rsi,rsi);
end;
movq(reg,[rcx+i]);
movq([rdi],mem);
end;
reta;
@ -529,32 +560,209 @@ begin
begin
//input:rdi
link:=movj(rsi,[rip+$FFFF],-1);
if (copy_size=1) then
begin
call(@uplift); //input:rdi output:rax=rdi
end else
begin
link:=movj(rsi,[rip+$FFFF],-1);
movi(edx,copy_size);
movi(edx,copy_size);
call(@copyin_mov); //rdi,rsi,edx
call(@copyin_mov); //rdi,rsi,edx
reta;
reta;
//input:rdi
//input:rdi
link._label:=_label;
link._label:=_label;
end;
movq(rax,[GS+Integer(teb_thread)]);
movq(rcx,[GS+Integer(teb_thread)]);
i:=GetFrameOffsetInt(ctx.din.Operand[id].RegValue[0]);
Assert(i<>0,'build_mov');
movq(dst,[rdi]);
movq([rax+i],dst);
if (copy_size<reg_size) then
begin
xorq(rsi,rsi);
end;
movq(mem,[rdi]);
movq([rcx+i],reg);
reta;
end;
end;
end; //case
end;
//
Const
rflags_offset=Integer(ptruint(@p_kthread(nil)^.td_frame.tf_rflags));
procedure build_load_flags(var ctx:t_jit_context);
begin
//input rcx:curkthread
with ctx.builder do
begin
movq(ah,[rcx+rflags_offset]);
sahf
end;
end;
procedure build_save_flags(var ctx:t_jit_context);
begin
//input rcx:curkthread
with ctx.builder do
begin
lahf;
movq([rcx+rflags_offset],ah);
end;
end;
//
procedure build_cmp(var ctx:t_jit_context;id:Byte;memop:t_memop_type);
var
i,copy_size,reg_size:Integer;
imm:Int64;
link:t_jit_i_link;
mem,reg:t_jit_reg;
begin
get_size_info(ctx.din.Operand[get_lea_id(memop)].Size,copy_size,mem);
get_size_info(ctx.din.Operand[id].Size,reg_size,reg);
with ctx.builder do
begin
case memop of
moCopyout:
begin
with ctx.builder do
begin
//input:rdi
if (copy_size=1) then
begin
call(@uplift); //input:rdi output:rax=rdi
end else
begin
link:=leaj(rsi,[rip+$FFFF],-1);
movi(edx,copy_size);
call(@copyout_mov); //rdi,rsi,edx
reta;
//input:rdi
link._label:=_label;
end;
movq(rcx,[GS+Integer(teb_thread)]);
//load flags
build_load_flags(ctx);
//load flags
imm:=0;
if GetTargetOfs(ctx,id,imm) then
begin
//imm const
if (reg_size=1) and (copy_size<>1) then
begin
cmpi8(mem.ARegValue[0].ASize,[rdi],imm);
end else
begin
cmpi(mem.ARegValue[0].ASize,[rdi],imm);
end;
end else
begin
i:=GetFrameOffsetInt(ctx.din.Operand[id].RegValue[0]);
Assert(i<>0,'build_cmp');
if (copy_size>reg_size) then
begin
xorq(rsi,rsi);
end;
movq(reg,[rcx+i]);
cmpq([rdi],mem);
end;
//save flags
build_save_flags(ctx);
//save flags
reta;
end;
end;
moCopyin:
begin
with ctx.builder do
begin
//input:rdi
if (copy_size=1) then
begin
call(@uplift); //input:rdi output:rax=rdi
end else
begin
link:=leaj(rsi,[rip+$FFFF],-1);
movi(edx,copy_size);
call(@copyout_mov); //rdi,rsi,edx
reta;
//input:rdi
link._label:=_label;
end;
movq(rcx,[GS+Integer(teb_thread)]);
i:=GetFrameOffsetInt(ctx.din.Operand[id].RegValue[0]);
Assert(i<>0,'build_cmp');
//load flags
build_load_flags(ctx);
//load flags
if (copy_size<reg_size) then
begin
xorq(rsi,rsi);
end;
movq(reg,[rcx+i]);
cmpq(mem,[rdi]);
//save flags
build_save_flags(ctx);
//save flags
reta;
end;
end;
end; //case
end;
end;
//
procedure build_vmovdqu(var ctx:t_jit_context;id:Byte;memop:t_memop_type);
@ -625,7 +833,7 @@ begin
reta;
end;
end;
end;
end; //case
end;
procedure build_vmovups(var ctx:t_jit_context;id:Byte;memop:t_memop_type);
@ -696,7 +904,7 @@ begin
reta;
end;
end;
end;
end; //case
end;
procedure build_vmovdqa(var ctx:t_jit_context;id:Byte;memop:t_memop_type);
@ -736,7 +944,7 @@ begin
reta;
end;
end;
end;
end; //case
end;
procedure print_disassemble(addr:Pointer;vsize:Integer);
@ -770,7 +978,7 @@ var
jit_size,size,i:Integer;
begin
ctx.builder.call(@test_jit); //test
//ctx.builder.call(@test_jit); //test
case ctx.din.OpCode.Opcode of
OPmov:
@ -806,6 +1014,23 @@ begin
end; //case
end; //OPmov
OPcmp:
begin
case ctx.din.OpCode.Suffix of
OPSnone:
begin
memop:=classif_memop(ctx.din);
build_lea(ctx,get_lea_id(memop));
build_cmp(ctx,get_reg_id(memop),memop);
end;
else
goto _err;
end; //case
end; //OPcmp
OPmovu:
begin
case ctx.din.OpCode.Suffix of