64 bit bitwise ops
- Posted by Falkon 1313 <Falkon1313 at AOL.COM> Feb 12, 2000
- 644 views
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" )