main.cpp
#include "../commonfiles/mmxval.h"
// The order of the name constants in the following enum must
// correspond to the table that is defined in MmxShift_.asm.
enum MmxShiftOp : unsigned int
{
psllw, // shift left logical word
psrlw, // shift right logical word
psraw, // shift right arithmetic word
pslld, // shift left logical dword
psrld, // shift right logical dword
psrad // shift right arithmetic dword
};
extern "C" bool MmxShift(MmxVal a, MmxShiftOp shift_op, int count, MmxVal* b);
void MmxShiftWords(void)
{
MmxVal a, b;
int count;
char buff[256];
a.u16[0] = 0x1234;
a.u16[1] = 0xFF00;
a.u16[2] = 0x00CC;
a.u16[3] = 0x8080;
count = 2;
MmxShift(a, MmxShiftOp::psllw, count, &b);
printf("\nResults for psllw - count = %d\n", count);
printf("a: %s\n", a.ToString_x16(buff, sizeof(buff)));
printf("b: %s\n", b.ToString_x16(buff, sizeof(buff)));
MmxShift(a, MmxShiftOp::psrlw, count, &b);
printf("\nResults for psrlw - count = %d\n", count);
printf("a: %s\n", a.ToString_x16(buff, sizeof(buff)));
printf("b: %s\n", b.ToString_x16(buff, sizeof(buff)));
MmxShift(a, MmxShiftOp::psraw, count, &b);
printf("\nResults for psraw - count = %d\n", count);
printf("a: %s\n", a.ToString_x16(buff, sizeof(buff)));
printf("b: %s\n", b.ToString_x16(buff, sizeof(buff)));
}
void MmxShiftDwords(void)
{
MmxVal a, b;
int count;
char buff[256];
a.u32[0] = 0x00010001;
a.u32[1] = 0x80008000;
count = 3;
MmxShift(a, MmxShiftOp::pslld, count, &b);
printf("\nResults for pslld - count = %d\n", count);
printf("a: %s\n", a.ToString_x32(buff, sizeof(buff)));
printf("b: %s\n", b.ToString_x32(buff, sizeof(buff)));
MmxShift(a, MmxShiftOp::psrld, count, &b);
printf("\nResults for psrld - count = %d\n", count);
printf("a: %s\n", a.ToString_x32(buff, sizeof(buff)));
printf("b: %s\n", b.ToString_x32(buff, sizeof(buff)));
MmxShift(a, MmxShiftOp::psrad, count, &b);
printf("\nResults for psrad - count = %d\n", count);
printf("a: %s\n", a.ToString_x32(buff, sizeof(buff)));
printf("b: %s\n", b.ToString_x32(buff, sizeof(buff)));
}
int main(int argc, char* argv[])
{
MmxShiftWords();
MmxShiftDwords();
return 0;
}
mmxshift.asm
; extern "C" bool MmxShift(MmxVal a, MmxShiftOp shift_op, int count, MmxVal* b);
;
; Description: The following function demonstrates use of various MMX
; shift instructions.
;
; Returns: 0 = invalid 'shift_op' argument
; 1 = success
;
; Name: mmxshift.asm
;
; Build: g++ -c -m32 main.cpp -o main.o -std=c++11
; nasm -f elf32 -o mmxshift.o mmxshift.asm
; g++ -m32 -o mmxshift mmxshift.o main.o ../commonfiles/mmxval.o
;
; Source: Modern X86 Assembly Language Programming p.156
global MmxShift
section .data
align 4
; The order of the labels in the following table must correspond
; to the enum that is defined in MmxShift.cpp.
%define DWORD_SIZE 4
ShiftOpTable: dd MmxShift.mmxPsllw
dd MmxShift.mmxPsrlw
dd MmxShift.mmxPsraw
dd MmxShift.mmxPslld
dd MmxShift.mmxPsrld
dd MmxShift.mmxPsrad
ShiftOpTableCount equ ($ - ShiftOpTable) / DWORD_SIZE
section .text
MmxShift:
%define a [ebp+8]
%define shift_op [ebp+16]
%define count [ebp+20]
%define b [ebp+24]
push ebp
mov ebp,esp
; Make sure 'shift_op' is valid
xor eax,eax ;set error code
mov edx,shift_op ;load 'shift_op'
cmp edx,ShiftOpTableCount ;compare against table count
jae .badShiftOp ;jump if 'shift_op' invalid
; Jump to the specfied shift operation
mov eax,1 ;set success return code
movq mm0,a ;load 'a'
movd mm1,dword count ;load 'count' into low dword
jmp [ShiftOpTable+edx*DWORD_SIZE]
.mmxPsllw:
psllw mm0,mm1 ;shift left logical word
jmp .saveResult
.mmxPsrlw:
psrlw mm0,mm1 ;shift right logical word
jmp .saveResult
.mmxPsraw:
psraw mm0,mm1 ;shift right arithmetic word
jmp .saveResult
.mmxPslld:
pslld mm0,mm1 ;shift left logical dword
jmp .saveResult
.mmxPsrld:
psrld mm0,mm1 ;shift right logical dword
jmp .saveResult
.mmxPsrad:
psrad mm0,mm1 ;shift right arithmetic dword
jmp .saveResult
.badShiftOp:
pxor mm0,mm0 ;use 0 if 'shift_op' is bad
jmp .done
.saveResult:
mov edx,b ;edx = ptr to 'b'
movq [edx],mm0 ;save shift result
emms ;clear MMX state
.done:
pop ebp
ret
build
g++ -c -m32 main.cpp -o main.o -std=c++11
nasm -f elf32 -o mmxshift.o mmxshift.asm
g++ -m32 -o mmxshift mmxshift.o main.o ../commonfiles/mmxval.o