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;
}
|