flat assembler
Message board for the users of flat assembler.

Index > Programming Language Design > [FASMG] Floating Point Instructions. Complete FPU

Author
Thread Post new topic Reply to topic
codestar



Joined: 25 Dec 2014
Posts: 254
codestar 30 May 2015, 11:23
Registers
Code:
numeric st, st0=0, st1, st2,\
  st3, st4, st5, st6, st7    
Get Type Size
Code:
; return size of type name

macro fpu_get_size size, type
  size=0
  match =word, type
    size='2'
  else match =dword, type
    size='4'
  else match =qword, type
    size='8'
  else match =tword, type
    size='t'
  else
    error `type, ' - Invalid type'
  end match
end macro    
Get Operand Type
Code:
; given operand, return type='r' (stx),
; 'm', 'm2', 'm4', 'm8', 'mt'

macro fpu_get_type type, p
  local n, is, size
  n=0
  is=0
  type=0
  size=0
  match t[m], p
    fpu_get_size size, t
    if size='2'
      type='m2'
    else if size='4'
      type='m4'
    else if size='8'
      type='m8'
    else if size='t'
      type='mt'
    end if
    get_mode_m m
  else match [m], p
    type='m'
    get_mode_m m
    its_size=0
  else match a, p
    name_length a, n
    if n=2
      match =st, a ; st0
        type='r'
      end match
    else if n=3
      is_in is, a,\
        st0, st1, st2, st3,\
        st4, st5, st6, st7
      if is
        type='r' ; stx
      end if
    end if
  else
    error 'Operand/s expected'
  end match
end macro    
Get Operands Mode
Code:
; return mode = 'r0'=st0, 'rx'=stx,
; 'r0rx'=st0,stx, 'rxr0'=stx,st0,
; 'm2/4/8/t'=m16/32/64/80

macro fpu_get_mode mode, p&
  local n, s, is, type1, type2
  n=0
  s=0
  is=0
  mode=0
  match a=,b, p
    fpu_get_type type1, a
    fpu_get_type type2, b
    if type1='r' & type2='r'
      if a=0
        mode='r0rx'
        its_index=b
      else
        mode='rxr0'
        its_index=a
      end if
    else
      error `a, ',', `b, ' - ',\
        'Invalid operands'
    end if
  else match a, p
    fpu_get_type mode, p
    if mode=0
      error `p, ' - Invalid operand'
    end if
    if mode='r'
      if a=0
        mode='r0'
      else
        mode='rx'
      end if
    end if
  end match
end macro    
Example FPU instructions. See attachment: \INCLUDE\FPU and \EXAMPLES\TEST\:

No-Operands: 1-3 bytes each:
Code:
irp <name,a,b,c>,\
  fclex,$9B,$DB,$E2, finit,$9B,$DB,$E3
  macro name
    db a, b, c
  end macro
end irp

irp <name,a,b>,\
  f2xm1,$D9,$F0, fabs,$D9,$E1,\
  fchs,$D9,$E0, fnclex,$DB,$E2,\
  fcompp,$DE,$D9, fcos,$D9,$FF,\
  fdecstp,$D9,$F6, femms,$0F,$0E,\
  fincstp,$D9,$F7, fninit,$DB,$E3,\
  fld1,$D9,$E8, fldl2e,$D9,$EA,\
  fldl2t,$D9,$E9, fldlg2,$D9,$EC,\
  fldln2,$D9,$ED, fldpi,$D9,$EB,\
  fldz,$D9,$EE, fnop,$D9,$D0,\
  fpatan,$D9,$F3, fptan,$D9,$F2,\
  fprem,$D9,$F8, fprem1,$D9,$F5,\
  frndint,$D9,$FC, fscale,$D9,$FD,\
  fsin,$D9,$FE, fsincos,$D9,$FB,\
  fsqrt,$D9,$FA
  macro name
    db a, b
  end macro
end irp    
Load, Store: FLD, FST/P
Code:
; fld stx   = $D9 C0+r
; fld m32   = $D9 /0
; fld m64   = $DD /0
; fld m80   = $DB /5

macro fld x
  local type
  type=0
  fpu_get_type type, x
  if type='r'
    db $D9, $C0+x
  else if type='m4'
    db $D9
    write_mode 0
  else if type='m8'
    db $DD
    write_mode 0
  else if type='mt'
    db $DB
    write_mode 5
  else
    error `x, ' - Invalid operand/s'
  end if
end macro

; fst stx   = $DD $D0+r
; fst m32   = $D9 /2
; fst m64   = $DD /2

macro fst x
  local type
  type=0
  fpu_get_type type, x
  if type='r'
    db $DD, $D0+x
  else if type='m4'
    db $D9
    write_mode 2
  else if type='m8'
    db $DD
    write_mode 2
  else
    error `x, ' - Invalid operand/s'
  end if
end macro

; fstp stx  = $DD $D8+r
; fstp m32  = $D9 /3
; fstp m64  = $DD /3
; fstp m80  = $DB /7

macro fstp x
  local type
  type=0
  fpu_get_type type, x
  if type='r'
    db $DD, $D8+x
  else if type='m4'
    db $D9
    write_mode 3
  else if type='m8'
    db $DD
    write_mode 3
  else if type='mt'
    db $DB
    write_mode 7
  else
    error `x, '- Invalid operand/s'
  end if
end macro    
Integer Load, Store: FILD, FIST/P
Code:
; fild m16 = $DF /0
; fild m32 = $DB /0
; fild m64 = $DF /5

macro fild x
  local type
  type=0
  fpu_get_type type, x
  if type='m2'
    db $DF
    write_mode 0
  else if type='m4'
    db $DB
    write_mode 0
  else if type='m8'
    db $DF
    write_mode 5
  else
    error `x, ' - Invalid operand'
  end if
end macro

; fist m16 = $DF /2
; fist m32 = $DB /2

macro fist x
  local type
  type=0
  fpu_get_type type, x
  if type='m2'
    db $DF
    write_mode 2
  else if type='m4'
    db $DB
    write_mode 2
  else
    error `x, ' - Invalid operand'
  end if
end macro

; fistp m16 = $DF /3
; fistp m32 = $DB /3
; fistp m64 = $DF /7

macro fistp x
  local type
  type=0
  fpu_get_type type, x
  if type='m2'
    db $DF
    write_mode 3
  else if type='m4'
    db $DB
    write_mode 3
  else if type='m8'
    db $DF
    write_mode 7
  else
    error `x, ' - Invalid operand'
  end if
end macro    
Arithmetic: FADD/P, FMUL/P, FDIV/P, FDIVR/P
Code:
; fadd stx      = $D8 $C0+r
; fadd st0,stx  = $D8 $C0+r
; fadd stx,st0  = $DC $C0+r
; fadd m32      = $D8 /0
; fadd m64      = $DC /0
; fmul stx      = $D8 $C8+r
; fmul st0,stx  = $D8 $C8+r
; fmul stx,st0  = $DC $C8+r
; fmul m32      = $D8 /1
; fmul m64      = $DC /1
; fdiv stx      = $D8 $F0+r
; fdiv st0,stx  = $D8 $F0+r
; fdiv stx,st0  = $DC $F8+r
; fdiv m32      = $D8 /6
; fdiv m64      = $DC /6
; fdivr stx     = $D8 $F8+r
; fdivr st0,stx = $D8 $F8+r
; fdivr stx,st0 = $DC $F0+r
; fdivr m32     = $D8 /7
; fdivr m64     = $DC /7

irp <name,opcode,opcode2,digit>,\
  fadd,$C0,$C0,0, fmul,$C8,$C8,1,\
  fdiv,$F0,$F8,6, fdivr,$F8,$F0,7
  macro name p&
    local r, mode
    r=0
    mode=0
    fpu_get_mode mode, p
    r=its_index
    if mode='r0'         ; st0
      db $D8, opcode+0
    else if mode='rx'    ; stx
      db $D8, opcode+r
    else if mode='r0rx'  ; st0, stx
      db $D8, opcode+r
    else if mode='rxr0'  ; stx, st0
      db $DC, opcode2+r
    else if mode='m4'    ; dword [m]
      db $D8
      write_mode digit
    else if mode='m8'    ; qword [m]
      db $DC
      write_mode digit
    else
      error `p, ' - Invalid mode'
    end if
  end macro
end irp

; faddp stx      = $DE C0+r
; faddp stx,st0  = $DE C0+r
; fmulp stx      = $DE C8+r
; fmulp stx,st0  = $DE C8+r
; fdivp stx      = $DE F8+r
; fdivp stx,st0  = $DE F8+r
; fdivrp stx     = $DE F0+r
; fdivrp stx,st0 = $DE F0+r

irp <name,opcode>,\
  faddp,$C0, fmulp,$C8,\
  fdivp,$F8, fdivrp,$F0
  macro name p&
   local r, mode
    r=0
    mode=0
    fpu_get_mode mode, p
    r=its_index
    if mode='r0' | mode='rx' \
      | mode='rxr0'
      db $DE, opcode+r
    else
      error `p, ' - Invalid mode'
    end if
  end macro
end irp    
Arithmetic with Integer: FIADD, FIMUL, FISUB/R, FIDIV/R
Code:
; fiadd m16  = $DE /0
; fiadd m32  = $DA /0
; fimul m16  = $DE /1
; fimul m32  = $DA /1
; fisub m16  = $DE /4
; fisub m32  = $DA /4
; fisubr m16 = $DE /5
; fisubr m32 = $DA /5
; fidiv m16  = $DE /6
; fidiv m32  = $DA /6
; fidivr m16 = $DE /7
; fidivr m32 = $DA /7

irp <name,digit>,\
  fiadd,0, fimul,1, fisub,4,\
  fisubr,5, fidiv,6, fidivr,7
  macro name p
    local size
    size=0
    match t[m], p
      fpu_get_size size, t
      if size='2'
        db $DE
      else if size='4'
        db $DA
      else
        error 'Invalid size'
      end if
      get_mode_m m
      write_mode digit
    else
      error 'Invalid operand'
    end match
  end macro
end irp    
Compare: FCOM/P, FCOMI/P, FICOM/P
Code:
; fcom stx      = $D8 $D0+r
; fcom st0,stx  = $D8 $D0+r
; fcom m32      = $D8 /2
; fcom m64      = $DC /2
; fcomp stx     = $D8 $D8+r
; fcomp st0,stx = $D8 $D8+r
; fcomp m32     = $D8 /3
; fcomp m64     = $DC /3

irp <name,opcode,digit>,\
  fcom,$D0,2, fcomp,$D8,3
  macro name p&
    local r, mode
    r=0
    mode=0
    fpu_get_mode mode, p
    r=its_index
    if mode='r0'         ; st0
      db $D8, opcode+0
    else if mode='rx'    ; stx
      db $D8, opcode+r
    else if mode='r0rx'  ; st0, stx
      db $D8, opcode+r
    else if mode='m4'    ; dword [m]
      db $D8
      write_mode digit
    else if mode='m8'    ; qword [m]
      db $DC
      write_mode digit
    else
      error `p, ' - Invalid mode'
    end if
  end macro
end irp

; fcomi stx      = $DB $F0+r
; fcomi st0,stx  = $DB $F0+r
; fcomip stx     = $DF $F0+r
; fcomip st0,stx = $DF $F0+r

irp <name,opcode>, fcomi,$DB, fcomip,$DF
  macro name p&
   local r, mode
    r=0
    mode=0
    fpu_get_mode mode, p
    r=its_index
    if mode='r0' | mode='rx' \
      | mode='r0rx'
      db opcode, $F0+r
    else
      error `p, ' - Invalid mode'
    end if
  end macro
end irp

; ficom m16  = $DE /2
; ficom m32  = $DA /2
; ficomp m16 = $DE /3
; ficomp m32 = $DA /3

irp <name,digit>, ficom,2, ficomp,3
  macro name p&
    local size
    size=0
    match t[m], p
      fpu_get_size size, t
      if size='2'
        db $DE
      else if size='4'
        db $DA
      else
        error 'Invalid size'
      end if
      get_mode_m m
      write_mode digit
    else
      error 'Invalid operand'
    end match
  end macro
end irp    
Conditional Move: CMOVX
Code:
; fcmovb stx       = $DA $C0+r
; fcmovb st0,stx   = $DA $C0+r
; fcmove stx       = $DA $C8+r
; fcmove st0,stx   = $DA $C8+r
; fcmovbe stx      = $DA $D0+r
; fcmovbe st0,stx  = $DA $D0+r
; fcmovu stx       = $DA $D8+r
; fcmovu st0,stx   = $DA $D8+r
; fcmovnb stx      = $DB $C0+r
; fcmovnb st0,stx  = $DB $C0+r
; fcmovne stx      = $DB $C8+r
; fcmovne st0,stx  = $DB $C8+r
; fcmovnbe stx     = $DB $D0+r
; fcmovnbe st0,stx = $DB $D0+r
; fcmovnu stx      = $DB $D8+r
; fcmovnu st0,stx  = $DB $D8+r

irp <name,opcode,opcode2>,\
  fcmovb,$DA,$C0, fcmove,$DA,$C8,\
  fcmovbe,$DA,$D0, fcmovu,$DA,$D8,\
  fcmovnb,$DB,$C0, fcmovne,$DB,$C8,\
  fcmovnbe,$DB,$D0, fcmovnu,$DB,$D8
  macro name p&
   local r, mode
    r=0
    mode=0
    fpu_get_mode mode, p
    r=its_index
    if mode='r0' | mode='rx' \
      | mode='r0rx'
      db opcode, opcode2+r
    else
      error `p, ' - Invalid mode'
    end if
  end macro
end irp    
Test FPU Instructions:
Code:
macro test_fpu_load_store
  fld st1
  fld dword [edi]
  fld qword [eax+ecx*8]
  fld tword [$CAFEBABE]
  fst st3
  fst dword [$12345678]
  fst qword [$ABCD1234]
  fstp st7
  fstp dword [ebx+edx*4]
  fstp qword [edi]
  fstp tword [$CAFEBABE]
  fbld tword [edi]
  fbstp tword [ebx]
  fild word [eax]
  fild dword [ecx]
  fild qword [edx]
  fist word [eax+ecx*2]
  fist dword [esi+$BABE1234]
  fldenv [eax]
  fnsave [ecx]
  frstor [edx]
  ffree st7
end macro

macro test_fpu_arithmetic
  fadd st1
  fadd st1,st0
  fadd dword [$12345678]
  fadd qword [$ABCD1234]
  fmul st1
  fmul st1,st0
  fmul dword [$12345678]
  fmul qword [$ABCD1234]
  fdiv st3
  fdiv st0,st7
  fdiv st7,st0
  fdiv dword [eax+4]
  fdiv qword [ecx+8]
  fdivr st3
  fdivr st0,st7
  fdivr st7,st0
  fdivr dword [eax+4]
  fdivr qword [ecx+$CAFEBABE]
  faddp st1
  faddp st2,st0
  fmulp st3
  fmulp st4,st0
  fdivp st5
  fdivp st7,st0
  fdivrp st1
  fdivrp st2,st0
  fiadd word [eax]
  fiadd dword [ecx]
  fimul word [edx]
  fimul dword [ebx]
  fisub word [eax]
  fisub dword [ecx]
  fisubr word [edx]
  fisubr dword [ebx]
  fidiv word [eax]
  fidiv dword [ecx]
  fidivr word [edx]
  fidivr dword [ebx]
end macro

macro test_fpu_compare
  fcom st1
  fcom st0,st7
  fcom dword [eax]
  fcom qword [ecx]
  fcomp st2
  fcomp st0,st3
  fcomp dword [eax]
  fcomp qword [ecx]
  fcomi st1
  fcomi st0,st2
  fcomip st3
  fcomip st0,st4
  ficom word [eax]
  ficom dword [ecx]
  ficomp word [eax]
  ficomp dword [edi+$CAFEBABE]
end macro

macro test_fpu_cmove
  fcmovb st1
  fcmovb st0,st2
  fcmove st3
  fcmove st0,st4
  fcmovbe st5
  fcmovbe st0,st6
  fcmovu st7
  fcmovu st0,st1
  fcmovnb st2
  fcmovnb st0,st3
  fcmovne st4
  fcmovne st0,st5
  fcmovnbe st6
  fcmovnbe st0,st7
  fcmovnu st1
  fcmovnu st0,st2
end macro

macro test_fpu
  test_fpu_load_store
  test_fpu_arithmetic
  test_fpu_compare
  test_fpu_cmove
end macro    
Verified with PE Browse Pro disassembler:
Code:
D9C1          FLD         ST(1)
D907          FLD         DWORD [EDI]
DD04C8        FLD         QWORD [EAX+ECX*8]
DDD3          FST         ST(3)
D91578563412  FST         DWORD [0x12345678]
DD153412CDAB  FST         QWORD [0xABCD1234]
DDDF          FSTP        ST(7)
D91C93        FSTP        DWORD [EBX+EDX*4]
DD1F          FSTP        QWORD [EDI]
DB3DBEBAFECA  FSTP        TBYTE [0xCAFEBABE]
DF27          FBLD        TBYTE [EDI]
DF33          FBSTP       TBYTE [EBX]
DF00          FILD        WORD [EAX]
DB01          FILD        DWORD [ECX]
DF2A          FILD        QWORD [EDX]
DF1448        FIST        WORD [EAX+ECX*2]
DB963412BEBA  FIST        DWORD [ESI+0xBABE1234]
D920          FLDENV      DWORD [EAX]
DD31          FNSAVE      [ECX]
DD22          FRSTOR      [EDX]
DDC7          FFREE       ST(7)
D8C1          FADD        ST(0),ST(1)
DCC1          FADD        ST(1),ST(0)
D80578563412  FADD        DWORD [0x12345678]
DC053412CDAB  FADD        QWORD [0xABCD1234]
D8C9          FMUL        ST(0),ST(1)
DCC9          FMUL        ST(1),ST(0)
D80D78563412  FMUL        DWORD [0x12345678]
DC0D3412CDAB  FMUL        QWORD [0xABCD1234]
D8F3          FDIV        ST(0),ST(3)
D8F7          FDIV        ST(0),ST(7)
DCFF          FDIV        ST(7),ST(0)
D87004        FDIV        DWORD [EAX+0x4]
DC7108        FDIV        QWORD [ECX+0x8]
D8FB          FDIVR       ST(0),ST(3)
D8FF          FDIVR       ST(0),ST(7)
DCF7          FDIVR       ST(7),ST(0)
D87804        FDIVR       DWORD [EAX+0x4]
DCB9BEBAFECA  FDIVR       QWORD [ECX+0xCAFEBABE]
DEC1          FADDP       ST(1),ST(0)
DEC2          FADDP       ST(2),ST(0)
DECB          FMULP       ST(3),ST(0)
DECC          FMULP       ST(4),ST(0)
DEFD          FDIVP       ST(5),ST(0)
DEFF          FDIVP       ST(7),ST(0)
DEF1          FDIVRP      ST(1),ST(0)
DEF2          FDIVRP      ST(2),ST(0)
DE00          FIADD       WORD [EAX]
DA01          FIADD       DWORD [ECX]
DE0A          FIMUL       WORD [EDX]
DA0B          FIMUL       DWORD [EBX]
DE20          FISUB       WORD [EAX]
DA21          FISUB       DWORD [ECX]
DE2A          FISUBR      WORD [EDX]
DA2B          FISUBR      DWORD [EBX]
DE30          FIDIV       WORD [EAX]
DA31          FIDIV       DWORD [ECX]
DE3A          FIDIVR      WORD [EDX]
DA3B          FIDIVR      DWORD [EBX]
D8D1          FCOM        ST(1)
D8D7          FCOM        ST(7)
D810          FCOM        DWORD [EAX]
DC11          FCOM        QWORD [ECX]
D8DA          FCOMP       ST(2)
D8DB          FCOMP       ST(3)
D818          FCOMP       DWORD [EAX]
DC19          FCOMP       QWORD [ECX]
DBF1          FCOMI       ST,ST(1)
DBF2          FCOMI       ST,ST(2)
DFF3          FCOMIP      ST,ST(3)
DFF4          FCOMIP      ST,ST(4)
DE10          FICOM       WORD [EAX]
DA11          FICOM       DWORD [ECX]
DE18          FICOMP      WORD [EAX]
DA9FBEBAFECA  FICOMP      DWORD [EDI+0xCAFEBABE]
DAC1          FCMOVB      ST(0),ST(1)
DAC2          FCMOVB      ST(0),ST(2)
DACB          FCMOVE      ST(0),ST(3)
DACC          FCMOVE      ST(0),ST(4)
DAD5          FCMOVBE     ST(0),ST(5)
DAD6          FCMOVBE     ST(0),ST(6)
DADF          FCMOVU      ST(0),ST(7)
DAD9          FCMOVU      ST(0),ST(1)
DBC2          FCMOVNB     ST(0),ST(2)
DBC3          FCMOVNB     ST(0),ST(3)
DBCC          FCMOVNE     ST(0),ST(4)
DBCD          FCMOVNE     ST(0),ST(5)
DBD6          FCMOVNBE    ST(0),ST(6)
DBD7          FCMOVNBE    ST(0),ST(7)
DBD9          FCMOVNU     ST(0),ST(1)
DBDA          FCMOVNU     ST(0),ST(2)    


Description: Examples
Download
Filename: fpu_g.zip
Filesize: 19.04 KB
Downloaded: 759 Time(s)

Post 30 May 2015, 11:23
View user's profile Send private message Reply with quote
CandyMan



Joined: 04 Sep 2009
Posts: 413
Location: film "CandyMan" directed through Bernard Rose OR Candy Shop
CandyMan 30 May 2015, 15:51
good work, but where is FISTTP opcode?

_________________
smaller is better
Post 30 May 2015, 15:51
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.