This macro is the MMX version of the FPU macro I did a while back. It creates global labels for the MMX constants and uses them apon repeated access to the same constant values. The MMX constants are also stored in their own sub-segment of the CONST segment.
mxc MACRO val:REQ

LOCAL w,y,z

z SIZESTR <&val>

;; Attempt to compact data
WHILE (z LT 17) AND (z GT 2)
z = z/2
IFDIF @SubStr(<&val>,1,z),@SubStr(<&val>,1+z,z)
z = z + z + 16
ENDIF
ENDM

IF z GT 16
z = z - 16
ENDIF

w TEXTEQU @SubStr(<&val>,1,z)

;; figure out global name for constant
y CATSTR <__MMX_>,w

IF (OPATTR(y)) EQ 0 ;; not defined
CONST$mmx SEGMENT
y LABEL QWORD
w CATSTR <0>,w,<h>
IF z EQ 16
dq w
ELSEIF z EQ 8
dd w,w
ELSEIF z EQ 4
dw w,w,w,w
ELSEIF z EQ 2
db w,w,w,w,w,w,w,w
ENDIF
CONST$mmx ENDS
ENDIF
EXITM y
ENDM
...and you would use it like this:
movq mm7,mxc(<01>) ; eight bytes

movq mm7,mxc(<0101>) ; four words, but same data as above
movq mm7,mxc(<01234567>) ; two dwords
etc...

q2a PROC dst:DWORD,src:DWORD,bytes:DWORD
mov ecx,bytes
mov eax,src
mov edx,dst
movq mm4, mxc(<0F>)
movq mm5, mxc(<30>)
movq mm6, mxc(<39>)
; movq mm7, mxc(<D8>) ; lowercase
movq mm7, mxc(<F8>) ; uppercase
shr ecx,3
ALIGN 16
db 7 dup (90h) ; required for 9 cycle loop on Athlon!
@@: movq mm0,[eax]
add eax,8
add edx,16
dec ecx
movq mm1,mm0
psrlq mm0,4
pand mm1,mm4
pand mm0,mm4
paddb mm1,mm5
paddb mm0,mm5
movq mm3,mm1
movq mm2,mm0
pcmpgtb mm3,mm6
pcmpgtb mm2,mm6
psubusb mm3,mm7
psubusb mm2,mm7
paddb mm1,mm3
paddb mm0,mm2
movq mm2,mm0
punpckhbw mm0,mm1
punpcklbw mm2,mm1
movq [-16][edx + 8],mm0
movq [-16][edx],mm2
jne @B
emms
q2a ENDP
Posted on 2002-02-23 20:36:29 by bitRAKE
Very cool and useful, Thanks bitrake. :)
Posted on 2002-02-24 06:37:07 by Eóin