summaryrefslogtreecommitdiff
path: root/src/x86.asm
diff options
context:
space:
mode:
Diffstat (limited to 'src/x86.asm')
-rw-r--r--src/x86.asm422
1 files changed, 422 insertions, 0 deletions
diff --git a/src/x86.asm b/src/x86.asm
new file mode 100644
index 0000000..8a3f51a
--- /dev/null
+++ b/src/x86.asm
@@ -0,0 +1,422 @@
+%ifdef _X86_
+[BITS 32]
+
+;;;
+;;; For some reason MSVC like to put an extra underscore in front of
+;;; global identifer names. If this is gcc, compensate.
+;;;
+%ifdef __GNUC__
+%define _g_VectorDelta g_VectorDelta
+%define _g_PieceData g_PieceData
+%endif
+
+[SEGMENT .data]
+ParallelScratch:
+_ParallelScratch:
+ db 43h,30h,50h,56h, 72h,31h,47h,34h, 54h,20h,32h,30h
+ db 30h,36h,20h,53h, 63h,30h,74h,74h, 20h,47h,61h,73h
+ db 63h,34h,00h,01h, 22h,15h,48h,35h, 31h,21h,55h,46h
+
+%ifdef OSX
+;;; Note: The reason for this OSX stuff is that there is a bug in the mac
+;;; version of nasm. See comments in data.c for more details.
+
+[GLOBAL g_NasmVectorDelta]
+[GLOBAL _g_NasmVectorDelta]
+g_NasmVectorDelta:
+_g_NasmVectorDelta:
+ alignb 32, db 0
+ times 256 * 4 db 0
+
+[GLOBAL g_NasmPieceData]
+[GLOBAL _g_NasmPieceData]
+g_NasmPieceData:
+_g_NasmPieceData:
+ alignb 32, db 0
+ times 4 * 4 * 8 db 0
+%else
+[EXTERN _g_VectorDelta]
+[EXTERN _g_PieceData]
+%endif
+
+[SEGMENT .text]
+
+%ifndef CROUTINES
+[GLOBAL LastBit]
+[GLOBAL _LastBit]
+ ;;
+ ;; ULONG CDECL
+ ;; LastBit(BITBOARD bb)
+ ;;
+LastBit:
+_LastBit:
+ mov ecx, [esp+8]
+ mov edx, [esp+4]
+ bsr eax, ecx
+ jnz .lone
+ bsr eax, edx
+ jnz .ltwo
+ xor eax, eax
+ jmp .ldone
+.lone: add eax, 32
+.ltwo: add eax, 1
+.ldone: ret
+
+ int 3
+
+[GLOBAL FirstBit]
+[GLOBAL _FirstBit]
+ ;;
+ ;; ULONG CDECL
+ ;; FirstBit(BITBOARD bb)
+ ;;
+FirstBit:
+_FirstBit:
+ mov ecx, [esp+8] ; half of bb
+ mov edx, [esp+4] ; the other half
+ bsf eax, edx
+ jnz .low
+ bsf eax, ecx
+ jnz .hi
+ xor eax, eax
+ ret
+.hi: add eax, 32
+.low: add eax, 1
+ ret
+
+ int 3
+
+[GLOBAL CountBits]
+[GLOBAL _CountBits]
+ ;;
+ ;; ULONG CDECL
+ ;; CountBits(BITBOARD bb)
+ ;;
+CountBits:
+_CountBits:
+ xor eax, eax ; eax is the count
+ mov ecx, [esp+4] ; half of bb
+ test ecx, ecx
+ jz .c2 ; skip first loop?
+.c1: add eax, 1
+ mov edx, ecx
+ sub edx, 1
+ and ecx, edx
+ jnz .c1
+.c2: mov ecx, [esp+8] ; the other half of bb
+ test ecx, ecx
+ jz .cdone ; skip second loop?
+.c3: add eax, 1
+ mov edx, ecx
+ sub edx, 1
+ and ecx, edx
+ jnz .c3
+.cdone: ret
+
+ int 3
+%endif
+
+[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:
+_LockCompareExchange:
+ mov ecx, [pDest]
+ mov edx, [uExch]
+ mov eax, [uComp]
+ lock cmpxchg dword [ecx], edx
+ ret
+
+ int 3
+
+[GLOBAL LockIncrement]
+[GLOBAL _LockIncrement]
+ ;;
+ ;; ULONG CDECL
+ ;; LockIncrement(ULONG *pDest)
+ ;;
+LockIncrement:
+_LockIncrement:
+ mov ecx, [pDest]
+ mov eax, 1
+ lock xadd [ecx], eax
+ add eax, 1
+ ret
+
+ int 3
+
+[GLOBAL LockDecrement]
+[GLOBAL _LockDecrement]
+ ;;
+ ;; ULONG CDECL
+ ;; LockDecrement(ULONG *pDest)
+ ;;
+LockDecrement:
+_LockDecrement:
+ mov ecx, [pDest]
+ mov eax, -1
+ lock xadd [ecx], eax
+ add eax, -1
+ ret
+
+ int 3
+
+%ifndef CROUTINES
+[GLOBAL GetAttacks]
+[GLOBAL _GetAttacks]
+
+ db 43h,30h,50h,56h,72h,31h,47h,34h,54h,20h,32h,30h,30h
+ db 36h,20h,53h,63h,30h,74h,74h,20h,47h,61h,73h,63h,34h
+
+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
+
+%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
+ ;;
+GetAttacks:
+_GetAttacks:
+ push ebp
+ mov ebp, esp
+ push ebx
+ push esi
+ push edi
+
+ ;; SEE_LIST *pOldList
+ ;; COOR c
+ ;; int x
+ sub esp, 0xC
+
+ mov ecx, [pList]
+ mov edx, [pos]
+
+ ;; pOldList = pList;
+ mov dword [pOldList], ecx
+
+ ;; pList.uCount = 0;
+ mov dword [ecx], 0
+
+ ;; pList = &(pList.data[0]);
+ add ecx, 4
+ mov edi, ecx
+
+ ;; c = cSquare + iDelta[uColor]
+ mov esi, dword [uSide]
+ mov ebx, dword [cSquare]
+ mov eax, dword [iDelta+esi*4]
+ add ebx, eax
+
+ ;; pPawn = BLACK_PAWN | uColor
+ mov ecx, esi
+ or ecx, 2
+
+ ;;
+ ;; Check the pawns
+ ;;
+
+ ;; if (!IS_ON_BOARD(c)) goto try other pawn
+ test ebx, 0x88
+ jnz .try_other_pawn
+
+ ;; p = pos->pSquare[c];
+ mov eax, dword [edx+ebx*8+_rgSquare]
+
+ ;; if (p != pPawn) then goto try other pawn
+ cmp eax, ecx
+ jne .try_other_pawn
+
+ ;; pOldList->uCount = 1
+ mov dword [edi-4], 1
+
+ ;; pList->pPiece = p;
+ mov dword [edi], ecx
+
+ ;; pList->cLoc = c;
+ mov dword [edi+4], ebx
+
+ ;; pList->iVal = VALUE_PAWN;
+ mov dword [edi+8], 100
+
+ ;; pList++
+ add edi, 12
+
+.try_other_pawn:
+ ;; c = c + 2
+ add ebx, 2
+
+ ;; if (!IS_ON_BOARD(c)) goto done pawns
+ test ebx, 0x88
+ jnz .done_pawns
+
+ ;; p = pos->pSquare[c];
+ mov eax, dword [edx+ebx*8+_rgSquare]
+
+ ;; if (p != pPawn) then goto done pawns
+ cmp eax, ecx
+ jne .done_pawns
+
+ ;; pList->pPiece = p;
+ mov dword [edi], ecx
+
+ ;; pList->cLoc = c;
+ mov dword [edi+4], ebx
+
+ ;; pList->iVal = VALUE_PAWN;
+ mov dword [edi+8], 100
+
+ ;; pOldList->uCount++
+ ;; pList++
+ mov eax, [pOldList]
+ add edi, 12
+ add dword [eax], 1
+
+.done_pawns:
+
+ ;;
+ ;; Do pieces
+ ;;
+
+ ;; for (x = pos->uNonPawnCount[uSide][0] - 1;
+ ;; x >= 0;
+ ;; x--)
+ ;; {
+ lea eax, [esi*8]
+ mov ecx, dword [edx+eax*4+_uNonPawnCount]
+ mov dword [x], ecx
+
+.loop_continue:
+ mov ecx, dword [x]
+ sub ecx, 1
+ cmp ecx, 0
+ jl near .done
+ mov esi, dword [uSide]
+ mov dword [x], ecx
+
+ ;; c = pos->cNonPawns[uSide][x];
+ mov eax, esi
+ shl eax, 4
+ add eax, ecx
+ mov eax, dword [edx+eax*4+_cNonPawns]
+ mov dword [c], eax
+
+ ;; p = pos->pSquare[c];
+ mov ecx, dword [edx+eax*8+_rgSquare]
+
+ ;; iIndex = c - cSquare;
+ sub eax, dword [cSquare]
+
+ ;;
+ ;; If there is no way for that kind of piece to get to this
+ ;; square then keep looking.
+ ;;
+ ;; if (0 == (g_VectorDeltaTable[iIndex].iVector[iSide] &
+ ;; (1 << (PIECE_PIECE(p) >> 1)))) continue;
+ mov ebx, 1
+ mov esi, ecx
+ shr ecx, 1
+ shl ebx, cl
+%ifdef OSX
+ test byte [_g_NasmVectorDelta+eax*4+512], bl
+%else
+ test byte [_g_VectorDelta+eax*4+512], bl
+%endif
+ jz .loop_continue
+
+ ;; if (IS_KNIGHT_OR_KING(p)) goto nothing_blocks
+ and ecx, 3
+ cmp ecx, 2
+ mov ecx, dword [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.
+ ;;
+ ;; iDelta = g_VectorDeltaTable[iIndex].iNegDelta;
+%ifdef OSX
+ movsx ebx, byte [_g_NasmVectorDelta+eax*4+515]
+%else
+ movsx ebx, byte [_g_VectorDelta+eax*4+515]
+%endif
+
+ ;; cBlockIndex = cSquare + iDelta
+ mov eax, dword [cSquare]
+.block_loop:
+ add eax, ebx
+
+ ;; if (cBlockIndex != c)
+ ;; {
+ cmp eax, ecx
+ je .nothing_blocks
+
+ ;; if (IS_EMPTY(pos->pSquare[cBlockIndex]))
+ ;; {
+ cmp dword [edx+eax*8], 0
+ jne .loop_continue
+
+ ;; goto cond
+ jmp .block_loop
+
+.nothing_blocks:
+ ;; pList->pPiece[pList->iCount] = p;
+ mov dword [edi], esi
+
+ ;; pList->cLoc[pList->iCount] = c;
+ mov dword [edi+4], ecx
+
+ ;; pList->iVal[pList->iCount] = PIECE_VALUE(p)
+ mov ecx, esi
+ shr ecx, 1
+ shl ecx, 4
+%ifdef OSX
+ mov ebx, dword [_g_NasmPieceData+ecx]
+%else
+ mov ebx, dword [_g_PieceData+ecx]
+%endif
+ mov dword [edi+8], ebx
+
+ ;; uCount++
+ mov eax, dword [pOldList]
+ add edi, 12
+ add dword [eax], 1
+ jmp .loop_continue
+
+.done: add esp, 0xC
+ pop edi ; restore saved registers
+ pop esi
+ pop ebx
+ leave
+ ret
+%endif ; CROUTINES
+%endif ; X86