diff options
| author | Scott Gasch <[email protected]> | 2026-08-23 11:28:49 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-08-23 11:28:49 -0700 |
| commit | df8facc22815f9eca0897e27ccce30701ba95322 (patch) | |
| tree | bf90ad7ff19383fbac9b0a163f31bf3a9fb11fbe /src/x64.asm | |
| parent | dc0c9dbf405095a6483705b153f4c85c64499d4e (diff) | |
Clean X64 build and ported GetAttacks to x64.
Diffstat (limited to 'src/x64.asm')
| -rw-r--r-- | src/x64.asm | 247 |
1 files changed, 192 insertions, 55 deletions
diff --git a/src/x64.asm b/src/x64.asm index e80dc67..89351f2 100644 --- a/src/x64.asm +++ b/src/x64.asm @@ -3,8 +3,8 @@ [SEGMENT .data] -[EXTERN _g_VectorDelta] -[EXTERN _g_PieceData] +[EXTERN g_VectorDelta] +[EXTERN g_PieceData] %ifdef OSX ;;; Note: The reason for this OSX stuff is that there is a bug in the mac @@ -24,8 +24,8 @@ _g_NasmPieceData: alignb 32, db 0 times 4 * 4 * 8 db 0 %else -[EXTERN _g_VectorDelta] -[EXTERN _g_PieceData] +[EXTERN g_VectorDelta] +[EXTERN g_PieceData] %endif [SEGMENT .text] @@ -39,8 +39,7 @@ _g_NasmPieceData: ;; LastBit: _LastBit: - int 3 - bsr rax, rcx + bsr rax, rdi jnz .found xor rax, rax ret @@ -50,14 +49,13 @@ _LastBit: [GLOBAL FirstBit] [GLOBAL _FirstBit] - ;; + ;; ;; ULONGLONG CDECL ;; FirstBit(BITBOARD bb) - ;; + ;; FirstBit: _FirstBit: - ;movq rcx, [rsp+8] - bsf rax, rcx + bsf rax, rdi jnz .found xor rax, rax ret @@ -67,14 +65,14 @@ _FirstBit: [GLOBAL CountBits] [GLOBAL _CountBits] - ;; + ;; ;; ULONGLONG CDECL ;; CountBits(BITBOARD bb) - ;; -CountBits: + ;; +CountBits: _CountBits: xor rax, rax - mov rcx, [esp+8] + mov rcx, rdi test rcx, rcx jz .done .again: add rax, 1 @@ -94,52 +92,191 @@ _CountBits: iDelta dd -17 dd +15 -%define uSide ebp+0x14 -%define cSquare ebp+0x10 -%define pos ebp+0xC -%define pList ebp+8 -;; retaddr ebp+4 -;; old ebp ebp -;; old ebx ebp-4 -;; old esi ebp-8 -;; old edi ebp-0xC -%define pOldList ebp-0x10 -%define c ebp-0x14 -%define x ebp-0x18 +;; [rbp-0x8] is the saved rbx from the "push rbx" in the prologue below; +;; locals must start below that, not alias it. +%define pOldList qword [rbp-0x10] +%define c dword [rbp-0x14] +%define x dword [rbp-0x18] +%define cSquareSave dword [rbp-0x1C] +%define uSideSave dword [rbp-0x20] %define _cNonPawns 0x478 %define _uNonPawnCount 0x500 %define _rgSquare 0x0 - - ;; - ;; void CDECL - ;; GetAttacks(SEE_LIST *pList, ; ebp + 8 - ;; POSITION *pos, ; ebp + 0xC - ;; COOR cSquare, ; ebp + 0x10 - ;; ULONG uSide) ; ebp + 0x14 - ;; + + ;; + ;; void CDECL (SysV AMD64 ABI) + ;; GetAttacks(SEE_LIST *pList, ; rdi + ;; POSITION *pos, ; rsi + ;; COOR cSquare, ; edx + ;; ULONG uSide) ; ecx + ;; + ;; NOTE: a square (COOR) is always >= 0, but a square-minus- + ;; square delta is not. Any such delta must be sign-extended + ;; into a 64-bit register (movsxd) before being used as a + ;; scaled memory index: using the raw 32-bit register zero- + ;; extends it into a huge positive 64-bit value instead of the + ;; intended negative offset. This is the same bug that turned + ;; up in the C DISTANCE macro -- see chess.h. + ;; GetAttacks: _GetAttacks: - int 3 + push rbp + mov rbp, rsp + push rbx + sub rsp, 0x20 + + mov cSquareSave, edx + mov uSideSave, ecx + + mov pOldList, rdi ; pOldList = pList + mov dword [rdi], 0 ; pList->uCount = 0 + add rdi, 4 ; rdi = &pList->data[0] + + ;; ebx = c = cSquare + iDelta[uSide] + movsxd rax, uSideSave + mov ebx, [iDelta+rax*4] + add ebx, cSquareSave + + ;; ecx = pPawn = BLACK_PAWN | uColor + mov ecx, uSideSave + or ecx, 2 + + ;; + ;; Check the pawns + ;; + test ebx, 0x88 + jnz .try_other_pawn + movsxd rax, ebx + mov eax, dword [rsi+rax*8+_rgSquare] + cmp eax, ecx + jne .try_other_pawn + mov rax, pOldList + mov dword [rax], 1 + mov dword [rdi], ecx + mov dword [rdi+4], ebx + mov dword [rdi+8], 100 + add rdi, 12 + +.try_other_pawn: + add ebx, 2 + test ebx, 0x88 + jnz .done_pawns + movsxd rax, ebx + mov eax, dword [rsi+rax*8+_rgSquare] + cmp eax, ecx + jne .done_pawns + mov dword [rdi], ecx + mov dword [rdi+4], ebx + mov dword [rdi+8], 100 + mov rax, pOldList + add rdi, 12 + add dword [rax], 1 + +.done_pawns: + ;; + ;; Do pieces + ;; + ;; x = pos->uNonPawnCount[uSide][0] + mov eax, uSideSave + shl eax, 5 ; uSide * 32 + movsxd rax, eax + mov ecx, dword [rsi+rax+_uNonPawnCount] + mov x, ecx + +.loop_continue: + mov ecx, x + sub ecx, 1 + cmp ecx, 0 + jl near .done + mov x, ecx + + ;; eax = c = pos->cNonPawns[uSide][x] + mov eax, uSideSave + shl eax, 4 + add eax, ecx ; eax = uSide*16 + x + movsxd rax, eax + mov eax, dword [rsi+rax*4+_cNonPawns] + mov c, eax + + ;; ecx = p = pos->pSquare[c] + movsxd rax, eax + mov ecx, dword [rsi+rax*8+_rgSquare] + + ;; r8 = iIndex = c - cSquare (must stay signed) + sub eax, cSquareSave + movsxd r8, eax + + ;; + ;; If there is no way for that kind of piece to get to this + ;; square then keep looking. + ;; + mov ebx, 1 + mov r9d, ecx ; r9 = p, survives to .nothing_blocks + shr ecx, 1 + shl ebx, cl + test byte [g_VectorDelta+r8*4+512], bl + jz .loop_continue + + ;; if (IS_KNIGHT_OR_KING(p)) goto nothing_blocks + and ecx, 3 + cmp ecx, 2 + mov ecx, c + je .nothing_blocks + + ;; + ;; Not a knight or king. Check to see if there is a piece in + ;; the path from cSquare to c that blocks the attack. + ;; + movsx ebx, byte [g_VectorDelta+r8*4+515] + mov eax, cSquareSave +.block_loop: + add eax, ebx + cmp eax, ecx + je .nothing_blocks + movsxd rdx, eax + cmp dword [rsi+rdx*8], 0 + jne .loop_continue + jmp .block_loop + +.nothing_blocks: + mov dword [rdi], r9d + mov dword [rdi+4], ecx + + ;; index into g_PieceData: sizeof(PIECE_DATA) is 24 on x64 (not + ;; 16, as on x86) because its trailing "CHAR *szName" widens + ;; from 4 to 8 bytes and pads the struct to 8-byte alignment. + mov ecx, r9d + shr ecx, 1 + imul ecx, ecx, 24 + movsxd rcx, ecx + mov ebx, dword [g_PieceData+rcx] + mov dword [rdi+8], ebx + + mov rax, pOldList + add rdi, 12 + add dword [rax], 1 + jmp .loop_continue + +.done: add rsp, 0x20 + pop rbx + pop rbp + ret %endif ; !CROUTINES [GLOBAL LockCompareExchange] [GLOBAL _LockCompareExchange] -%define uComp esp+0xC -%define uExch esp+8 -%define pDest esp+4 - ;; + ;; ;; ULONG CDECL - ;; LockCompareExchange(void *dest, ; esp + 4 - ;; ULONG exch, ; esp + 8 - ;; ULONG comp) ; esp + C - ;; + ;; LockCompareExchange(void *dest, ; rdi (SysV AMD64 ABI) + ;; ULONG exch, ; esi + ;; ULONG comp) ; edx + ;; LockCompareExchange: _LockCompareExchange: - mov ecx, [pDest] - mov edx, [uExch] - mov eax, [uComp] - lock cmpxchg dword [ecx], edx + mov eax, edx ; comp -> eax (cmpxchg's implicit compare reg) + mov rcx, rdi ; dest pointer -> rcx + lock cmpxchg dword [rcx], esi ret int 3 @@ -147,13 +284,13 @@ _LockCompareExchange: [GLOBAL _LockIncrement] ;; ;; ULONG CDECL - ;; LockIncrement(ULONG *pDest) - ;; + ;; LockIncrement(ULONG *pDest) ; rdi (SysV AMD64 ABI) + ;; LockIncrement: _LockIncrement: - mov ecx, [pDest] + mov rcx, rdi mov eax, 1 - lock xadd [ecx], eax + lock xadd [rcx], eax add eax, 1 ret int 3 @@ -162,13 +299,13 @@ _LockIncrement: [GLOBAL _LockDecrement] ;; ;; ULONG CDECL - ;; LockDecrement(ULONG *pDest) - ;; + ;; LockDecrement(ULONG *pDest) ; rdi (SysV AMD64 ABI) + ;; LockDecrement: _LockDecrement: - mov ecx, [pDest] + mov rcx, rdi mov eax, -1 - lock xadd [ecx], eax + lock xadd [rcx], eax add eax, -1 ret int 3 |
