feat(asm): lock prefix + negl/xaddl encoders
This commit is contained in:
parent
8467eed451
commit
85a46aa1ec
|
|
@ -180,6 +180,7 @@ type
|
|||
NumOps: Integer;
|
||||
RawLine: string; { original line text }
|
||||
LineNum: Integer;
|
||||
HasLock: Boolean; { a `lock` prefix preceded the mnemonic }
|
||||
end;
|
||||
|
||||
{ Internal assembler state for a single section }
|
||||
|
|
@ -706,6 +707,21 @@ begin
|
|||
Mnemonic := Mnemonic + Chr(S[P]);
|
||||
P := P + 1;
|
||||
end;
|
||||
|
||||
{ `lock` prefix: record it and read the real mnemonic that follows. }
|
||||
if Mnemonic = 'lock' then
|
||||
begin
|
||||
Result.HasLock := True;
|
||||
while (P < Length(S)) and ((S[P] = Ord(' ')) or (S[P] = 9)) do
|
||||
P := P + 1;
|
||||
Mnemonic := '';
|
||||
while (P < Length(S)) and (IsAlnum(S[P])) do
|
||||
begin
|
||||
Mnemonic := Mnemonic + Chr(S[P]);
|
||||
P := P + 1;
|
||||
end;
|
||||
end;
|
||||
|
||||
Result.Mnemonic := Mnemonic;
|
||||
|
||||
{ Skip whitespace }
|
||||
|
|
@ -1249,6 +1265,10 @@ begin
|
|||
Op1 := AParsed.Op1;
|
||||
Op2 := AParsed.Op2;
|
||||
|
||||
{ ---- lock prefix (F0) — emitted ahead of the instruction it guards ---- }
|
||||
if AParsed.HasLock then
|
||||
CBEmit(CB, $F0);
|
||||
|
||||
{ ---- ret ---- }
|
||||
if Mnem = 'ret' then
|
||||
begin
|
||||
|
|
@ -1567,6 +1587,45 @@ begin
|
|||
Exit;
|
||||
end;
|
||||
|
||||
{ ---- negl / negq ---- (F7 /3, same group as notl/notq) }
|
||||
if (Mnem = 'negl') or (Mnem = 'negq') then
|
||||
begin
|
||||
if Op1.Kind = opReg then
|
||||
begin
|
||||
EmitRexIfNeeded(CB, Mnem = 'negq', 0, Op1.Reg, False);
|
||||
CBEmit(CB, $F7);
|
||||
CBEmit(CB, MakeModRM(3, 3, Op1.Reg));
|
||||
end
|
||||
else
|
||||
raise EAssembler.Create(Mnem + ': unsupported operand');
|
||||
Result := CB.Data;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
{ ---- xaddl / xaddq ---- (0F C1 /r: xadd src-reg, r/m). Atomic with the
|
||||
lock prefix (emitted above). src register is in the ModRM reg field. }
|
||||
if (Mnem = 'xaddl') or (Mnem = 'xaddq') then
|
||||
begin
|
||||
if (Op1.Kind = opReg) and IsMemLike(Op2) then
|
||||
begin
|
||||
EmitRexForMem(CB, Mnem = 'xaddq', Op1.Reg, Op2, False);
|
||||
CBEmit(CB, $0F);
|
||||
CBEmit(CB, $C1);
|
||||
EncodeMemOperand(CB, ACtx, Op2, Op1.Reg and 7);
|
||||
end
|
||||
else if (Op1.Kind = opReg) and (Op2.Kind = opReg) then
|
||||
begin
|
||||
EmitRexIfNeeded(CB, Mnem = 'xaddq', Op1.Reg, Op2.Reg, False);
|
||||
CBEmit(CB, $0F);
|
||||
CBEmit(CB, $C1);
|
||||
CBEmit(CB, MakeModRM(3, Op1.Reg, Op2.Reg));
|
||||
end
|
||||
else
|
||||
raise EAssembler.Create(Mnem + ': unsupported operand combination');
|
||||
Result := CB.Data;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
{ ---- shll/shlq/shrl/shrq ---- }
|
||||
if (Mnem = 'shll') or (Mnem = 'shlq') or (Mnem = 'shrl') or (Mnem = 'shrq') then
|
||||
begin
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ type
|
|||
procedure TestErrorMessage_HasLineNumber;
|
||||
procedure TestMovqXmmToReg_SseEncoding;
|
||||
procedure TestMovqRegToXmm_SseEncoding;
|
||||
procedure TestNegl_F7Slash3;
|
||||
procedure TestLockXaddl_AtomicEncoding;
|
||||
end;
|
||||
|
||||
{ ---- ELF writer unit tests ---- }
|
||||
|
|
@ -148,6 +150,28 @@ begin
|
|||
ContainsBytes(Obj, Chr($48) + Chr($8B) + Chr($07)));
|
||||
end;
|
||||
|
||||
procedure TAsmEncodingTests.TestNegl_F7Slash3;
|
||||
var
|
||||
Obj: string;
|
||||
begin
|
||||
{ negl %esi -> f7 de (F7 /3, reg=esi=6). Verified vs `cc`. }
|
||||
Obj := AssembleToBytes('negl %esi' + LineEnding);
|
||||
AssertTrue('f7 de missing',
|
||||
ContainsBytes(Obj, Chr($F7) + Chr($DE)));
|
||||
end;
|
||||
|
||||
procedure TAsmEncodingTests.TestLockXaddl_AtomicEncoding;
|
||||
var
|
||||
Obj: string;
|
||||
begin
|
||||
{ lock xaddl %eax, (%rdi) -> f0 0f c1 07. The atomic RTL primitive
|
||||
(_AtomicAddInt32). f0 = lock prefix, 0f c1 = xadd, 07 = ModRM
|
||||
(reg=eax=0, r/m=[rdi]). Verified vs `cc`. }
|
||||
Obj := AssembleToBytes('lock xaddl %eax, (%rdi)' + LineEnding);
|
||||
AssertTrue('f0 0f c1 07 missing',
|
||||
ContainsBytes(Obj, Chr($F0) + Chr($0F) + Chr($C1) + Chr($07)));
|
||||
end;
|
||||
|
||||
procedure TAsmEncodingTests.TestQuadSymbol_EmitsReloc;
|
||||
var
|
||||
Obj: string;
|
||||
|
|
|
|||
Loading…
Reference in a new issue