64 bit bitwise ops

new topic     » topic index » view thread      » older message » newer message

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" )

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu