summaryrefslogtreecommitdiff
path: root/CSAPP/tmul_asm.c
blob: e496618df871f9939e3a6f67910ede534b9c0347 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
int tmul_bug(long x, long y, long *dest)
{
	long result = 0;
	*dest = x*y;
	asm("setae %al");
	return result;
}

int tmul_ok(long x, long y, long *dest)
{
	int result = 0;
	*dest = x*y;
	asm("setae %%bl		# Set low-order byte\n\t"
	    "movzbl %%bl, %[val]	# Zero extend to be res"
	    : [val] "=r" (result) /* Output */
	    :			  /* No inputs */
	    : "%bl"		  /* Overwrites */
	    );
	return result;
}

int tmul_ok2(long x, long y, long *dest)
{
	unsigned char result = 0;
	*dest = x*y;

	asm("setae %[b]		# Set result"
	    : [b] "=r" (result) /* Output */
	    );
	return (int)result;
}

int umult_ok(unsigned long x, unsigned long y, unsigned long *dest)
{
	/*
	 * GCC's asm choose the register to store asm operands
	 * according to the type/size of the variable
	 */
	unsigned char result;

	asm("movq %[x],%%rax	#Get x\n\t"
	    "mulq %[y]	# Unsigned long mult x*y\n\t"
	    "movq %%rax,%[p]	#Store low-order 8bytes at dest\n\t"
	    "setae %[b]	#Set result"
	    : [p] "=m" (*dest), [b] "=r" (result) /* Outputs */
	    : [x] "r"  (x),	[y] "r"  (y)	  /* Inputs */
	    : "%rax", "%rdx"			  /* Overwrites */
	   );

	return (int) result;
}