Star InactiveStar InactiveStar InactiveStar InactiveStar Inactive
 
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