Re: Emulating a 64-bit long with only 32 bits: code anyone?

"walter" <walter@nospamm-digitalmars.com>
14 Jun 2001 00:27:03 -0400

          From comp.compilers

Related articles
[2 earlier articles]
Re: Emulating a 64-bit long with only 32 bits: code anyone? gneuner@dyn.com (2001-05-31)
Re: Emulating a 64-bit long with only 32 bits: code anyone? joewhaley@hotmail.com (John Whaley) (2001-06-03)
Re: Emulating a 64-bit long with only 32 bits: code anyone? Timothy_S_Coffey@bankone.com (2001-06-07)
Re: Emulating a 64-bit long with only 32 bits: code anyone? benji@wohnheim.uni-ulm.de (Markus Ackermann) (2001-06-08)
Re: Emulating a 64-bit long with only 32 bits: code anyone? marcov@toad.stack.nl (2001-06-08)
Re: Emulating a 64-bit long with only 32 bits: code anyone? Klaus.Bergdolt@gmx.de (2001-06-10)
Re: Emulating a 64-bit long with only 32 bits: code anyone? walter@nospamm-digitalmars.com (walter) (2001-06-14)
| List of all articles for this month |

From: "walter" <walter@nospamm-digitalmars.com>
Newsgroups: comp.compilers
Date: 14 Jun 2001 00:27:03 -0400
Organization: Excite@Home - The Leader in Broadband http://home.com/faster
References: 01-05-087 01-06-011
Keywords: arithmetic
Posted-Date: 14 Jun 2001 00:27:03 EDT

This should get you started, it's a multiply, signed divide, unsigned divide
and compare. You can use it as long as you leave the copyright notice in.
The trouble with doing these kinds of things in C is that C doesn't give
access to the carry bit; working around that can be klunky and slow.


-Walter
www.digitalmars.com Free C/C++ compilers


------------------------------------------------------
;_ llmath.asm
; Copyright (C) 1993-2001 by Digital Mars
; All Rights Reserved
; Written by Walter Bright
; www.digitalmars.com


include macros.asm


; 64 bit negate
neg64 macro reg1,reg2
    neg reg1
    neg reg2
    sbb reg1,0
  endm




  begcode llmath


  public __LMUL@,__LDIV@,__ULDIV@,__LCMP@


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Multiply:
; EDX,EAX = EDX,EAX * ECX,EBX
; ECX is destroyed


__LMUL@ proc near
        if 0
  push ESI
  mov ESI,EDX ;ESI = d
  xchg EAX,ECX ;EAX = c, ECX = a
  tst EAX
  jz short M1
  mul ECX ;EAX = acl
M1: xchg EAX,ESI ;ESI = acl, EAX = d
  tst EAX
  jz short M2
  mul EBX ;EAX = bdl
  add ESI,EAX ;ESI = acl + bdl
M2: mov EAX,ECX ;EAX = a
  mul EBX ;EAX = abl, EDX = abh
  add EDX,ESI ;EAX = abl, EDX = abh + acl + bdl
  pop ESI
  ret
        else
  tst ECX
  jnz short M1
  tst EDX
  jnz short M2
  mul EBX
  ret


  even
M1: tst EDX
  jnz short M3
  ;EDX is 0
  xchg EAX,ECX
  mul ECX
  xchg EAX,ECX
  mul EBX
  add EDX,ECX
  ret


  even
M2: ;ECX is 0
  mov ECX,EAX
  mov EAX,EDX
  mul EBX
  xchg EAX,ECX
  mul EBX
  add EDX,ECX
  ret


  even
M3: push ESI
  mov ESI,EDX ;ESI = d
  xchg EAX,ECX ;EAX = c, ECX = a
  mul ECX ;EAX = acl
  xchg EAX,ESI ;ESI = acl, EAX = d
  mul EBX ;EAX = bdl
  add ESI,EAX ;ESI = acl + bdl
  mov EAX,ECX ;EAX = a
  mul EBX ;EAX = abl, EDX = abh
  add EDX,ESI ;EAX = abl, EDX = abh + acl + bdl
  pop ESI
  ret
        endif
__LMUL@ endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Unsigned long divide.
; Input:
; [EDX,EAX],[ECX,EBX]
; Output:
; [EDX,EAX] = [EDX,EAX] / [ECX,EBX]
; [ECX,EBX] = [EDX,EAX] % [ECX,EBX]
; ESI,EDI destroyed


  even


uldiv proc near
  tst EDX
  jnz short D3
  ;High words are 0, we can use the DIV instruction
  div EBX
  mov EBX,EDX
  mov EDX,ECX ;EDX = ECX = 0
  ret


  even
D3: ;Divide [EDX,EAX] by EBX
  mov ECX,EAX
  mov EAX,EDX
  clr EDX
  div EBX
  xchg ECX,EAX
  div EBX
  ;ECX,EAX = result
  ;EDX = remainder
  mov EBX,EDX
  mov EDX,ECX
  clr ECX
  ret
uldiv endp


  even


__ULDIV@ proc near
  test ECX,ECX
  jz uldiv


  push EBP


  ;left justify [ECX,EBX] and leave count of shifts + 1 in EBP


  mov EBP,1 ;at least 1 shift
  tst ECX ;left justified?
  js short L1 ;yes
  jnz short L2
  add EBP,8
  mov CH,CL
  mov CL,BH
  mov BH,BL
  clr BL ;[ECX,EBX] <<= 8
  tst ECX
  js short L1
  even
L2: inc EBP ;another shift
  shl EBX,1
  rcl ECX,1 ;[ECX,EBX] <<= 1
  jno short L2 ;not left justified yet


L1: mov ESI,ECX
  mov EDI,EBX ;[ESI,EDI] = divisor


  mov ECX,EDX
  mov EBX,EAX ;[ECX,EBX] = [EDX,EAX]
  clr EAX
  cwd ;[EDX,EAX] = 0
  even
L4: _if ESI a ECX, L3 ;is [ECX,EBX] > [ESI,EDI]?
  jb L5 ;definitely less than
  _if EDI a EBX, L3 ;check low order word
L5: sub EBX,EDI
  sbb ECX,ESI ;[ECX,EBX] -= [ESI,EDI]
  stc ;rotate in a 1
L3: rcl EAX,1
  rcl EDX,1 ;[EDX,EAX] = ([EDX,EAX] << 1) + C
  shr ESI,1
  rcr EDI,1 ;[ESI,EDI] >>= 1
  dec EBP ;control count
  jne short L4
  pop EBP
  ret


div0: mov EAX,-1
  cwd ;quotient is -1
; clr ECX
; mov EBX,ECX ;remainder is 0 (ECX and EBX already 0)
  pop EBP
  ret


L10: tst ECX ;[ECX,EBX] negative?
  jns __ULDIV@ ;no (all is positive)
  neg64 ECX,EBX
  call __ULDIV@
  neg64 EDX,EAX ;quotient is negative
  ret
__ULDIV@ endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Signed long divide.
; Input:
; [EDX,EAX],[ECX,EBX]
; Output:
; [EDX,EAX] = [EDX,EAX] / [ECX,EBX]
; [ECX,EBX] = [EDX,EAX] % [ECX,EBX]
; ESI,EDI destroyed


  even


__LDIV@ proc near
  tst EDX ;[EDX,EAX] negative?
  jns short L10 ;no
  neg64 EDX,EAX ;[EDX,EAX] = -[EDX,EAX]
  tst ECX ;[ECX,EBX] negative?
  jns short L11 ;no
  neg64 ECX,EBX
  call __ULDIV@
  neg64 ECX,EBX ;remainder same sign as dividend
  ret


L11: call __ULDIV@
  neg64 ECX,EBX ;remainder same sign as dividend
  neg64 EDX,EAX ;quotient is negative
  ret


__LDIV@ endp




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Compare [EDX,EAX] with [ECX,EBX]
; Signed


  even
__LCMP@ proc near
  cmp EDX,ECX
  jne short C1
  push EDX
  clr EDX
  cmp EAX,EBX
  jz short C2
  ja short C3
  dec EDX
  pop EDX
  ret


C3: inc EDX
C2: pop EDX
C1: ret
__LCMP@ endp


  endcode lmath


  end


------------------------------------------------------


John Whaley wrote in message 01-06-011...
> My apologies if this is a FAQ. I'm designing a Java system for a machine
> that has only 32-bit longs (though it does have 64-bit doubles). I'm
> hoping that someone may know where you can find open source for code which
> manipulates 64-bit longs (multiply, divide, subtract, add, shift, bitwise
> and logical operations, etc.) using only 32 bits


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.