; Thomas 1.9+ object file [special integer types]
; by Thomas Lack¢, http://togye.host.sk
IDEAL
MODEL LARGE,PASCAL
P386

CODESEG

macro lodsw_es
  db 26h
  lodsw
endm

macro lodsd_es
  db 26h
  lodsd
endm

macro lodsb_fs
  db 64h
  lodsb
endm

macro lodsw_fs
  db 64h
  lodsw
endm

macro lodsd_fs
  db 64h
  lodsd
endm

macro lodsd_ss
  db 36h
  lodsd
endm

;***** MIN / MAX  *****
public MinT,MaxT,Min24,Max24,Min64,Max64

proc MinT vA:dword,vB:dword ; function:Longint
  lfs   si,[vA]
  les   di,[vB]
  lodsw_fs
  movsx dx,[fs:si]
  mov   cx,[es:di]
  movsx bx,[es:di+2]
  cmp   dx,bx
  ja    @@b
  jb    @@a
  cmp   ax,cx
  jbe   @@a
@@b:
  xchg  ax,cx
  mov   dx,bx
@@a:
  ret
endp

proc MaxT vA:dword,vB:dword ; function:Longint
  lfs   si,[vA]
  les   di,[vB]
  lodsw_fs
  movsx dx,[fs:si]
  mov   cx,[es:di]
  movsx bx,[es:di+2]
  cmp   dx,bx
  ja    @@a
  jb    @@b
  cmp   ax,cx
  ja    @@a
@@b:
  xchg  ax,cx
  mov   dx,bx
@@a:
  ret
endp

proc Min24 vA:dword,vB:dword ; function:Longint
  lfs   si,[vA]
  les   di,[vB]
  lodsw_fs
  movsx dx,[fs:si]
  mov   cx,[es:di]
  movsx bx,[es:di+2]
  cmp   dx,bx
  jg    @@b
  jl    @@a
  cmp   ax,cx
  jbe   @@a
@@b:
  xchg  ax,cx
  mov   dx,bx
@@a:
  ret
endp

proc Max24 vA:dword,vB:dword ; function:Longint
  lfs   si,[vA]
  les   di,[vB]
  lodsw_fs
  movsx dx,[fs:si]
  mov   cx,[es:di]
  movsx bx,[es:di+2]
  cmp   dx,bx
  jg    @@a
  jl    @@b
  cmp   ax,cx
  ja    @@a
@@b:
  xchg  ax,cx
  mov   dx,bx
@@a:
  ret
endp

proc Min64 vA:dword,vB:dword,vDest:dword
  lfs   si,[vA]
  les   di,[vB]
  lodsd_fs
  mov   edx,[fs:si]
  mov   ecx,[es:di]
  mov   ebx,[es:di+4]
  les   di,[vDest]
  cmp   edx,ebx
  jg    @@b
  jl    @@a
  cmp   eax,ecx
  jbe   @@a
@@b:
  mov   [es:di],ecx
  mov   [es:di+4],ebx
  ret
@@a:
  stosd
  mov   [es:di],edx
  ret
endp

proc Max64 vA:dword,vB:dword,vDest:dword
  lfs   si,[vA]
  les   di,[vB]
  lodsd_fs
  mov   edx,[fs:si]
  mov   ecx,[es:di]
  mov   ebx,[es:di+4]
  les   di,[vDest]
  cmp   edx,ebx
  jg    @@a
  jl    @@b
  cmp   eax,ecx
  ja    @@a
@@b:
  mov   [es:di],ecx
  mov   [es:di+4],ebx
  ret
@@a:
  stosd
  mov   [es:di],edx
  ret
endp

;***** SET / GET / GETSWAP *****
public SetT,GetT,Set24,Get24,Set64, GetSwapT,GetSwap24

proc SetT vX:dword,L:dword ; function:Boolean
  les   di,[vX]
  mov   ax,[word ptr L]
  stosw
  mov   al,[byte ptr L+2]
  stosb
  cmp   [byte ptr L+3],0
  sete  al
  ret
endp

proc Set24 vX:dword,L:dword ; function:Boolean
  les   di,[vX]
  mov   ax,[word ptr L]
  stosw
  mov   al,[byte ptr L+2]
  stosb
  cbw
  cmp   [byte ptr L+3],ah
  sete  al
  ret
endp

proc Set64 vX:dword,L:dword
  les   di,[vX]
  mov   eax,[L]
  cdq
  stosd
  mov   [es:di],edx
  ret
endp

proc GetT ; vX:dword ; function:Longint
  mov   bx,sp
  les   si,[ss:bx+4] ;vX
  lodsw_es
  movzx dx,[es:si]
  ret   4
endp

proc Get24 ; vX:dword ; function:Longint
  mov   bx,sp
  les   si,[ss:bx+4] ;vX
  lodsw_es
  movsx dx,[es:si]
  ret   4
endp

proc GetSwapT ; vX:dword ; function:Longint
  mov   bx,sp
  les   di,[ss:bx+4] ;vX
  movzx dx,[es:di]
  mov   ax,[es:di+1]
  xchg  ah,al
  ret   4
endp

proc GetSwap24 ; vX:dword ; function:Longint
  mov   bx,sp
  les   di,[ss:bx+4] ;vX
  movsx dx,[es:di]
  mov   ax,[es:di+1]
  xchg  ah,al
  ret   4
endp

;***** NEG, ZERO, INC/DEC *****
public Neg24,Neg64,ZeroT,Zero24,Zero64
public IncT,DecT,Inc24,Dec24,Inc64,Dec64

proc Neg24 vX:dword
  les di,[vX]
  test [word ptr es:di],0FFFFh
  jnz @@neg
  test [byte ptr es:di+2],7Fh
  jz @@exit
@@neg:
  not [word ptr es:di]
  not [byte ptr es:di+2]
  add [word ptr es:di],1
  adc [byte ptr es:di+2],0
@@exit:
  ret
endp

proc Neg64 vX:dword
  les di,[vX]
  test [dword ptr es:di],0FFFFFFFFh
  jnz @@neg
  test [dword ptr es:di+4],7FFFFFFFh
  jz @@exit
@@neg:
  not [dword ptr es:di]
  not [dword ptr es:di+4]
  add [dword ptr es:di],1
  adc [dword ptr es:di+4],0
@@exit:
  ret
endp

proc ZeroT ; vX:dword ; function:Boolean
proc Zero24
  mov bx,sp
  les di,[ss:bx+4] ;vX
  test [dword ptr es:di],0FFFFFFh
  setz al
  ret 4
endp
endp

proc Zero64 ; vX:dword ; function:Boolean
  mov bx,sp
  les di,[ss:bx+4] ;vX
  test [dword ptr es:di],0FFFFFFFFh
  jnz @@done
  test [dword ptr es:di+4],0FFFFFFFFh
@@done:
  setz al
  ret 4
endp

proc IncT ; vX:dword ; function:Boolean
  mov bx,sp
  les di,[ss:bx+4] ;vX
  add [word ptr es:di],1
  adc [byte ptr es:di+2],0
  setnc al
  jnc @@done
  dec [byte ptr es:di+2]
  dec [word ptr es:di]
@@done:
  ret 4
endp

proc DecT ; vX:dword ; function:Boolean
  mov bx,sp
  les di,[ss:bx+4] ;vX
  sub [word ptr es:di],1
  sbb [byte ptr es:di+2],0
  setnc al
  jnc @@done
  inc [byte ptr es:di+2]
  inc [word ptr es:di]
@@done:
  ret 4
endp

proc Inc24 ; vX:dword ; function:Boolean
  mov bx,sp
  les di,[ss:bx+4] ;vX
  add [word ptr es:di],1
  adc [byte ptr es:di+2],0
  setno al
  jno @@done
  dec [byte ptr es:di+2]
  dec [word ptr es:di]
@@done:
  ret 4
endp

proc Dec24 ; vX:dword ; function:Boolean
  mov bx,sp
  les di,[ss:bx+4] ;vX
  sub [word ptr es:di],1
  sbb [byte ptr es:di+2],0
  setno al
  jno @@done
  inc [byte ptr es:di+2]
  inc [word ptr es:di]
@@done:
  ret 4
endp

proc Inc64 ; vX:dword ; function:Boolean
  mov bx,sp
  les di,[ss:bx+4] ;vX
  add [dword ptr es:di],1
  adc [dword ptr es:di+4],0
  setno al
  jno @@done
  dec [dword ptr es:di+4]
  dec [dword ptr es:di]
@@done:
  ret 4
endp

proc Dec64 ; vX:dword ; function:Boolean
  mov bx,sp
  les di,[ss:bx+4] ;vX
  sub [dword ptr es:di],1
  sbb [dword ptr es:di+4],0
  setno al
  jno @@done
  inc [dword ptr es:di+4]
  inc [dword ptr es:di]
@@done:
  ret 4
endp

;***** ADD / SUB *****
public AddT, SubT, Add24, Sub24, Add64, Sub64
public AddTL,SubTL,Add24L,Sub24L,Add64L,Sub64L

proc AddT vX:dword,vY:dword ; function:Boolean
  les   di,[vX]
  lfs   si,[vY]
  lodsw_fs
  add   [es:di],ax
  lodsb_fs
  adc   [es:di+2],al
  setnc al
  ret
endp

proc Add24 vX:dword,vY:dword ; function:Boolean
  les   di,[vX]
  lfs   si,[vY]
  lodsw_fs
  add   [es:di],ax
  lodsb_fs
  adc   [es:di+2],al
  setno al
  ret
endp

proc AddTL vX:dword,L:dword ; function:Boolean
  les   di,[vX]
  mov   ax,[word ptr L]
  add   [es:di],ax
  mov   al,[byte ptr L+2]
  adc   [es:di+2],al
  setnc al
  ret
endp

proc Add24L vX:dword,L:dword ; function:Boolean
  les   di,[vX]
  mov   ax,[word ptr L]
  add   [es:di],ax
  mov   al,[byte ptr L+2]
  adc   [es:di+2],al
  setno al
  ret
endp

proc SubT vX:dword,vY:dword ; function:Boolean
  les   di,[vX]
  lfs   si,[vY]
  lodsw_fs
  sub   [es:di],ax
  lodsb_fs
  sbb   [es:di+2],al
  setnc al
  ret
endp

proc Sub24 vX:dword,vY:dword ; function:Boolean
  les   di,[vX]
  lfs   si,[vY]
  lodsw_fs
  sub   [es:di],ax
  lodsb_fs
  sbb   [es:di+2],al
  setno al
  ret
endp

proc SubTL vX:dword,L:dword ; function:Boolean
  les   di,[vX]
  mov   ax,[word ptr L]
  sub   [es:di],ax
  mov   al,[byte ptr L+2]
  sbb   [es:di+2],al
  setnc al
  ret
endp

proc Sub24L vX:dword,L:dword ; function:Boolean
  les   di,[vX]
  mov   ax,[word ptr L]
  sub   [es:di],ax
  mov   al,[byte ptr L+2]
  sbb   [es:di+2],al
  setno al
  ret
endp

proc Add64 vX:dword,vY:dword ; function:Boolean
  les   di,[vX]
  lfs   si,[vY]
  lodsd_fs
  add   [es:di],eax
  lodsd_fs
  adc   [es:di+4],eax
  setno al
  ret
endp

proc Add64L vX:dword,L:dword ; function:Boolean
  les   di,[vX]
  mov   eax,[L]
  add   [es:di],eax
  adc   [dword ptr es:di+4],0
  setno al
  ret
endp

proc Sub64 vX:dword,vY:dword ; function:Boolean
  les   di,[vX]
  lfs   si,[vY]
  lodsd_fs
  sub   [es:di],eax
  lodsd_fs
  sbb   [es:di+4],eax
  setno al
  ret
endp

proc Sub64L vX:dword,L:dword ; function:Boolean
  les   di,[vX]
  mov   eax,[L]
  sub   [es:di],eax
  sbb   [dword ptr es:di+4],0
  setno al
  ret
endp

;***** MUL *****
public MulT,MulTL,Mul24,Mul24L,Mul64,Mul64L

proc MulT vX:dword,vY:dword ; function:Boolean
  les   si,[vX]
  lfs   di,[vY]
  mov   edx,[fs:di]
  and   edx,0FFFFFFh
  call  near multx
  ret
endp

proc MulTL vX:dword,L:dword ; function:Boolean
  les   si,[vX]
  mov   edx,[L]
  or    edx,edx
  js    @@false
  call  near multx
  ret
@@false:
  mov   al,0
  ret
endp

proc MulTX near ; ES:SI ® [vX], EDX ® Y, [ES:SI] ¯ result?, AL ¯ Boolean
  lodsd_es
  and   eax,0FFFFFFh
  mul   edx
  or    edx,edx
  jnz   @@false
  test  eax,0FF000000h
  jnz   @@false
  mov   [es:si-4],ax
  shr   eax,16
  mov   [es:si-2],al
  mov   al,1
  ret
@@false:
  mov   al,0
  ret
endp

proc Mul24 vX:dword,vY:dword ; function:Boolean
  les   si,[vX]
  lfs   di,[vY]
  movsx dx,[fs:di+2]
  shl   edx,16
  mov   dx,[fs:di]
  call  near mul24x
  ret
endp

proc Mul24L vX:dword,L:dword ; function:Boolean
  les   si,[vX]
  lfs   di,[vY]
  mov   edx,[L]
  call  near mul24x
  ret
endp

proc Mul24X near ; ES:SI ® [vX], EDX ® Y, [ES:SI] ¯ result?, AL ¯ Boolean
  movsx ax,[es:si+2]
  shl   eax,16
  lodsw_es
  imul  edx
  mov   ecx,edx
  cdq
  cmp   ecx,edx
  jne   @@false
  mov   cx,ax
  shr   eax,16
  mov   dh,ah
  cbw
  cmp   ah,dh
  jne   @@false
  mov   [es:si-2],cx
  mov   [es:si],al
  mov   al,1
  ret
@@false:
  mov   al,0
  ret
endp

proc Mul64 vX:dword,vY:dword,ResHi:dword,ResLo:dword ; function:Boolean
local Res0:dword,Res1:dword,Res2:dword,Res3:dword,Sign:byte
  les   si,[vX]
  lfs   di,[vY]
  mov   ecx,[fs:di]
  mov   ebx,[fs:di+4]
  call  near mul64x
  ret
endp

proc Mul64L vX:dword,L:dword ; function:Boolean
local Res0:dword,Res1:dword,Res2:dword,Res3:dword,Sign:byte
  les   si,[vX]
  mov   ecx,[L]
  xor   ebx,ebx
  call  near mul64x
  ret
endp

proc Mul64X near ; ES:SI ® [vX], EBX:ECX ® Y, [ResHi]:[ResLo] ¯ result, AL ¯ Boolean
  mov   [Sign],0
  mov   edx,[es:si+4]
  lodsd_es
  or    edx,edx
  jns   @@xpos
  not   edx
  not   eax
  add   eax,1
  adc   edx,0
  not   [Sign]
@@xpos:
  or    ebx,ebx
  jns   @@ypos
  not   ebx
  not   ecx
  add   ecx,1
  adc   ebx,0
  not   [Sign]
@@ypos:
  xchg  eax,ebx
  push  edx eax
  mul   edx
  mov   [Res2],eax
  mov   [Res3],edx
  mov   eax,ebx
  mul   ecx
  mov   [Res0],eax
  mov   [Res1],edx
  pop   eax
  mul   ebx
  add   [Res1],eax
  adc   [Res2],edx
  adc   [Res3],0
  pop   eax
  mul   ecx
  add   [Res1],eax
  adc   [Res2],edx
  adc   [Res3],0
  mov   eax,[Res2]
  or    eax,[Res3]
  setz  al
  cmp   [Sign],0
  je    @@done
  not   [Res0]
  not   [Res1]
  not   [Res2]
  not   [Res3]
  add   [Res0],1
  adc   [Res1],0
  adc   [Res2],0
  adc   [Res3],0
@@done:
  push  ax
  lea   si,[Res0]
  les   di,[ResLo]
  lodsd_ss
  stosd
  lodsd_ss
  stosd
  les   di,[ResHi]
  lodsd_ss
  stosd
  lodsd_ss
  stosd
  pop   ax
  ret
endp

;***** CMP *****
public CmpT,Cmp24,Cmp64

proc CmpT vA:dword,vB:dword ; function:Integer
  lfs   si,[vA]
  les   di,[vB]
  lodsw_fs
  mov   dl,[fs:si]
  cmp   dl,[es:di+2]
  ja    @@greater
  jb    @@less
  cmp   ax,[es:di]
  ja    @@greater
  jb    @@less
  xor   ax,ax
  ret
@@greater:
  mov   ax,1
  ret
@@less:
  mov   ax,-1
  ret
endp

proc Cmp24 vA:dword,vB:dword ; function:Integer
  lfs   si,[vA]
  les   di,[vB]
  lodsw_fs
  mov   dl,[fs:si]
  cmp   dl,[es:di+2]
  jg    @@greater
  jl    @@less
  cmp   ax,[es:di]
  ja    @@greater
  jb    @@less
  xor   ax,ax
  ret
@@greater:
  mov   ax,1
  ret
@@less:
  mov   ax,-1
  ret
endp

proc Cmp64 vA:dword,vB:dword ; function:Integer
  lfs   si,[vA]
  les   di,[vB]
  lodsd_fs
  mov   edx,[fs:si]
  cmp   edx,[es:di+4]
  jg    @@greater
  jl    @@less
  cmp   eax,[es:di]
  ja    @@greater
  jb    @@less
  xor   ax,ax
  ret
@@greater:
  mov   ax,1
  ret
@@less:
  mov   ax,-1
  ret
endp

END