1. 64 bit bitwise ops
- Posted by Falkon 1313 <Falkon1313 at AOL.COM>
Feb 12, 2000
-
Last edited Feb 13, 2000
Well, I got 'em working, but it's not like I'd hoped. When I did it
using straight atoms, it only worked with numbers that didn't use the high
nibble. Numbers like #FF00FF00FF00FF00 would give incorrect results. Don't
know whether that's due to the way Euphoria stores atoms or just the way I
was converting back and forth. But I put 'em in { Hidw, Lowdw } sequences
instead of atoms and it works fine. Guess that kinda negates the point, as
you could just do normal 32 bit ops on the dws then...but anyway, here's
code. Maybe you or someone else can get it to work with straight atoms if
you need to.
------------------------------------------------------------------------------
------------
include machine.e
function Allocate( integer n )
atom a
a = allocate( n )
if not a then
printf( 1, "Couldn't allocate memory. %d more bytes"&
" of memory needed.\n", {n} )
abort( 1 )
end if
return( a )
end function
-- qword format is { hidw, lowdw }
function new_qword( sequence qw )
atom addr
addr = Allocate( 8 )
poke4( addr, qw[2] )
poke4( addr + 4, qw[1] )
return( addr )
end function
function get_qword( atom addr )
return( { peek4u( addr + 4 ), peek4u( addr ) } )
end function
procedure set_qword( atom addr, sequence qw )
poke4( addr, qw[2] )
poke4( addr + 4, qw[1] )
end procedure
-- Instruction Opcode Minimum Processor
--MOV reg32,imm32 ; o32 B8+r id [386]
--MOVQ mmxreg,r/m64 ; 0F 6F /r [PENT,MMX]
--MOVQ r/m64,mmxreg ; 0F 7F /r [PENT,MMX]
--PAND mmxreg,r/m64 ; 0F DB /r [PENT,MMX]
--POR mmxreg,r/m64 ; 0F EB /r [PENT,MMX]
--PXOR mmxreg,r/m64 ; 0F EF /r [PENT,MMX]
--EMMS ; 0F 77 [PENT,MMX]
constant LOGICAL_64_CODE =
{
#50, -- PUSH EAX
#B8, #00, #00, #00, #00, -- MOV EAX, 0 <-- ptr to param1
#0F, #6F, #00, -- MOVQ MM0, [EAX]
#B8, #00, #00, #00, #00, -- MOV EAX, 0 <-- ptr to param2
#0F, #6F, #08, -- MOVQ MM1, [EAX]
#0F, #DB, #C1, -- PAND MM0, MM1 (Will replace PAND with
appropriate op)
#0F, #7F, #00, -- MOVQ [EAX], MM0
#0F, #77, -- EMMS
#58, -- POP EAX
#C3 -- RET
},
LOGICAL_64 = Allocate( length( LOGICAL_64_CODE ) ),
LOGICAL_64_OP = 18, -- offset to poke the op
LOGICAL_64_P1 = 2, LOGICAL_64_P2 = 10 -- offsets to poke parameters
poke( LOGICAL_64, LOGICAL_64_CODE )
-- ops
constant L_64_AND = #DB,
L_64_NAND = #DF,
L_64_OR = #EB,
L_64_XOR = #EF
function Logical_64( integer op, sequence q1, sequence q2 )
atom addr1, addr2
-- poke the op
poke( LOGICAL_64 + LOGICAL_64_OP, op )
-- poke the parameters
addr1 = new_qword( q1 )
addr2 = new_qword( q2 )
-- poke their pointers
poke4( LOGICAL_64 + LOGICAL_64_P1, addr1 )
poke4( LOGICAL_64 + LOGICAL_64_P2, addr2 )
-- call it and read results from parameter 2's pointer
call( LOGICAL_64 )
q1 = get_qword( addr2 )
-- free the memory and return
free( addr1 )
free( addr2 )
return( q1 )
end function
-------- GLOBALS -----------------------------------------------
global function and_64_bits( sequence a, sequence b )
return( Logical_64( L_64_AND, a, b ) )
end function
global function or_64_bits( sequence a, sequence b )
return( Logical_64( L_64_OR, a, b ) )
end function
global function xor_64_bits( sequence a, sequence b )
return( Logical_64( L_64_XOR, a, b ) )
end function
global function nand_64_bits( sequence a, sequence b )
return( Logical_64( L_64_NAND, a, b ) )
end function
-------- TEST CODE ---------------------------------------------
function qw_to_hex( sequence val )
return( sprintf( "%08x%08x", val ) )
end function
sequence q1, q2
q1 = { #0F0F0F0F, #0F0F0F0F }
q2 = { #11111111, #11111111 }
sequence anox
puts( 1, "For #0F0F0F0F0F0F0F0F, #1111111111111111:\n" )
anox = {
qw_to_hex( and_64_bits( q1, q2 ) ),
qw_to_hex( nand_64_bits( q1, q2 ) ),
qw_to_hex( or_64_bits( q1, q2 ) ),
qw_to_hex( xor_64_bits( q1, q2 ) )
}
puts( 1, " and_64_bits: " & anox[1] & "\n" )
puts( 1, "nand_64_bits: " & anox[2] & "\n" )
puts( 1, " or_64_bits: " & anox[3] & "\n" )
puts( 1, " xor_64_bits: " & anox[4] & "\n" )
q1 = { #FF00FF00, #FF00FF00 }
q2 = { #11111111, #11111111 }
puts( 1, "\nFor #FF00FF00FF00FF00, #1111111111111111:\n" )
anox = {
qw_to_hex( and_64_bits( q1, q2 ) ),
qw_to_hex( nand_64_bits( q1, q2 ) ),
qw_to_hex( or_64_bits( q1, q2 ) ),
qw_to_hex( xor_64_bits( q1, q2 ) )
}
puts( 1, " and_64_bits: " & anox[1] & "\n" )
puts( 1, "nand_64_bits: " & anox[2] & "\n" )
puts( 1, " or_64_bits: " & anox[3] & "\n" )
puts( 1, " xor_64_bits: " & anox[4] & "\n" )