5 unsigned long long reg_val_double
[N
];
7 void init_reg_val_double()
9 unsigned long c
= 19650218UL;
11 reg_val_double
[0]= c
& 0xffffffffUL
;
12 for (i
= 1; i
< N
; i
++) {
13 reg_val_double
[i
] = (1812433253UL * (reg_val_double
[i
- 1] ^
14 (reg_val_double
[i
- 1] >> 30)) + i
);
19 /* Make a copy of original array to prevent the unexpected changes by Atomic Add
21 unsigned long long reg_val_double_copy
[N
];
23 void copy_reg_val_double()
26 for (i
= 0; i
< N
; i
++) {
27 reg_val_double_copy
[i
] = reg_val_double
[i
];
31 /* TEST1_32/64 macro is used in load atomic increment/decrement/set/clear
32 instructions. After executing each instruction we must check both memory
33 location and register value.
35 1: Move arguments (offset and base address) to registers
36 2: Add offset and base address to make absolute address
37 3: Execute instruction
38 4: Move result from register ($t3)
39 5: Load memory data ('lw' for 32bit instruction and 'ld' for 64bit addresses)
41 #define TEST1_32(instruction, offset,mem) \
43 unsigned long out = 0; \
44 unsigned long res_mem = 0; \
46 "move $t0, %2" "\n\t" \
47 "move $t1, %3" "\n\t" \
48 "daddu $t0, $t1, $t0" "\n\t" \
49 instruction " $t3, ($t0)" "\n\t" \
50 "move %0, $t3" "\n\t" \
51 "lw %1, 0($t0)" "\n\t" \
52 : "=&r" (out), "=&r"(res_mem) \
53 : "r" (mem) , "r" (offset) \
54 : "$12", "$13", "cc", "memory" \
56 printf("%s :: offset: 0x%x, out: 0x%lx, result:0x%lx\n", \
57 instruction, offset, out, res_mem); \
60 #define TEST1_64(instruction, offset,mem) \
62 unsigned long out = 0; \
63 unsigned long res_mem = 0; \
65 "move $t0, %2" "\n\t" \
66 "move $t1, %3" "\n\t" \
67 "daddu $t0, $t1, $t0" "\n\t" \
68 instruction " $t3, ($t0)" "\n\t" \
69 "move %0, $t3" "\n\t" \
70 "ld %1, 0($t0)" "\n\t" \
71 : "=&r" (out), "=&r"(res_mem) \
72 : "r" (mem) , "r" (offset) \
73 : "$12", "$13", "cc", "memory" \
75 printf("%s :: offset: 0x%x, out: 0x%lx, result: 0x%lx\n", \
76 instruction, offset, out, res_mem); \
79 /* Test 2 macro is used for pop/dpop/baddu instructions. After executing each
80 instructions the macro performs following operations:
82 1: Move arguments to registers
83 2: Execute instruction
84 3: Move result to register ($t3)
86 #define TEST2(instruction, RSVal, RTVal) \
90 "move $t1, %1" "\n\t" \
91 "move $t2, %2" "\n\t" \
93 "move %0, $t3" "\n\t" \
95 : "r" (RSVal), "r" (RTVal) \
96 : "$12", "$13", "cc", "memory" \
98 printf("%s :: rd 0x%lx, rs 0x%llx, rt 0x%llx\n", \
99 instruction, out, (long long) RSVal, (long long) RTVal); \
102 /* TEST3 macro is used for store atomic add and store atomic add doubleword
103 instructions. Following operations are performed by the test macro:
105 1: Move arguments to the register
106 2: Add offset and base address to make absolute address
107 3: Execute instruction
110 #define TEST3(instruction, offset, mem, value) \
112 unsigned long out = 0; \
113 unsigned long outPre = 0; \
115 "move $t0, %2" "\n\t" \
116 "move $t1, %3" "\n\t" \
117 "daddu $t0, $t1, $t0" "\n\t" \
118 "ld %1, 0($t0)" "\n\t" \
119 "move $t2, %4" "\n\t" \
120 instruction " $t2, ($t0)" "\n\t" \
121 "ld %0, 0($t0)" "\n\t" \
122 : "=&r" (out), "=&r" (outPre) \
123 : "r" (mem) , "r" (offset), "r" (value) \
124 : "$12", "$13", "$14", "cc", "memory" \
126 printf("%s :: value: 0x%llx, memPre: 0x%lx, mem: 0x%lx\n", \
127 instruction, value, outPre, out); \
130 /* TEST4_32/64 is used for load atomic add/swap instructions. Following
131 operations are performed by macro after execution of each instruction:
133 1: Move arguments to register.
134 2: Add offset and base address to make absolute address.
135 3: Execute instruction.
136 4: Move result to register.
137 5: Load memory data ('lw' for 32bit instruction and 'ld' for 64bit).
139 #define TEST4_32(instruction, offset, mem) \
141 unsigned long out = 0; \
142 unsigned long res_mem = 0; \
144 "move $t0, %2" "\n\t" \
145 "move $t1, %3" "\n\t" \
146 "daddu $t0, $t0, $t1" "\n\t" \
147 instruction " $t3, ($t0), $t1" "\n\t" \
148 "move %0, $t3" "\n\t" \
149 "lw %1, 0($t0)" "\n\t" \
150 : "=&r" (out), "=&r"(res_mem) \
151 : "r" (mem) , "r" (offset) \
152 : "$12", "$13", "cc", "memory" \
154 printf("%s :: offset: 0x%x, out: 0x%lx, result:0x%lx\n", \
155 instruction, offset, out, res_mem); \
158 #define TEST4_64(instruction, offset, mem) \
160 unsigned long out = 0; \
161 unsigned long res_mem = 0; \
163 "move $t0, %2" "\n\t" \
164 "move $t1, %3" "\n\t" \
165 "daddu $t0, $t0, $t1" "\n\t" \
166 instruction " $t3, ($t0), $t1" "\n\t" \
167 "move %0, $t3" "\n\t" \
168 "ld %1, 0($t0)" "\n\t" \
169 : "=&r" (out), "=&r"(res_mem) \
170 : "r" (mem) , "r" (offset) \
171 : "$12", "$13", "cc", "memory" \
173 printf("%s :: offset: 0x%x, out: 0x%lx, result: 0x%lx\n", \
174 instruction, offset, out, res_mem); \
178 BADDU
, POP
, DPOP
, SAA
, SAAD
, LAA
, LAAD
, LAW
, LAWD
, LAI
, LAID
, LAD
, LADD
,
184 #if (_MIPS_ARCH_OCTEON2)
185 init_reg_val_double();
188 for (op
= BADDU
; op
<= LACD
; op
++) {
190 /* Unsigned Byte Add - BADDU rd, rs, rt; Cavium OCTEON */
192 for(i
= 4; i
< N
; i
+= 4)
193 for(j
= 4; j
< N
; j
+= 4)
194 TEST2("baddu $t3, $t1, $t2", reg_val_double
[i
],
198 case POP
: { /* Count Ones in a Word - POP */
199 for(j
= 4; j
< N
; j
+= 4)
200 TEST2("pop $t3, $t1", reg_val_double
[j
], 0);
203 case DPOP
: { /* Count Ones in a Doubleword - DPOP */
204 for(j
= 8; j
< N
; j
+= 8)
205 TEST2("dpop $t3, $t1", reg_val_double
[j
], 0);
208 case SAA
: { /* Atomic Add Word - saa rt, (base). */
209 copy_reg_val_double();
210 for(j
= 4; j
< N
; j
+= 4)
211 TEST3("saa", j
, reg_val_double_copy
, reg_val_double
[j
]);
214 case SAAD
: { /* Atomic Add Double - saad rt, (base). */
215 copy_reg_val_double();
216 for(j
= 8; j
< N
; j
+= 8)
217 TEST3("saad", j
, reg_val_double_copy
, reg_val_double
[j
]);
220 case LAA
: { /* Load Atomic Add Word - laa rd, (base), rt. */
221 copy_reg_val_double();
222 for(j
= 4; j
< N
; j
+= 4)
223 TEST4_32("laa", j
, reg_val_double_copy
);
226 case LAAD
: { /* Load Atomic Add Double - laad rd, (base), rt */
227 copy_reg_val_double();
228 for(j
= 8; j
< N
; j
+= 8)
229 TEST4_64("laad ", j
, reg_val_double_copy
);
232 case LAW
: { /* Load Atomic Swap Word - law rd, (base), rt */
233 copy_reg_val_double();
234 for(j
= 4; j
< N
; j
+= 4)
235 TEST4_32("law", j
, reg_val_double_copy
);
238 case LAWD
: { /* Load Atomic Swap Double - lawd rd, (base), rt */
239 copy_reg_val_double();
240 for(j
= 8; j
< N
; j
+= 8)
241 TEST4_64("lawd", j
, reg_val_double_copy
);
244 case LAI
: { /* Load Atomic Increment Word - lai rd, (base) */
245 copy_reg_val_double();
246 for(i
= 4; i
< N
; i
+= 4)
247 TEST1_32("lai", i
, reg_val_double_copy
);
250 case LAID
: { /* Load Atomic Increment Double - laid rd, (base) */
251 copy_reg_val_double();
252 for(i
= 8; i
< N
; i
+= 8)
253 TEST1_64("laid ", i
, reg_val_double_copy
);
256 case LAD
: { /* Load Atomic Decrement Word - lad rd, (base) */
257 copy_reg_val_double();
258 for(i
= 4; i
< N
; i
+= 4)
259 TEST1_32("lad", i
, reg_val_double_copy
);
262 case LADD
: { /* Load Atomic Decrement Double - ladd rd, (base) */
263 copy_reg_val_double();
264 for(i
= 8; i
< N
; i
+= 8)
265 TEST1_64("ladd",i
, reg_val_double_copy
);
268 case LAS
:{ /* Load Atomic Set Word - las rd, (base) */
269 copy_reg_val_double();
270 for(i
= 4; i
< N
; i
+= 4)
271 TEST1_32("las",i
, reg_val_double_copy
);
274 case LASD
:{ /* Load Atomic Set Word - lasd rd, (base) */
275 copy_reg_val_double();
276 for(i
= 8; i
< N
; i
+= 8)
277 TEST1_64("lasd",i
, reg_val_double_copy
);
280 case LAC
: { /* Load Atomic Clear Word - lac rd, (base) */
281 copy_reg_val_double();
282 for(i
= 4; i
< N
; i
+= 4)
283 TEST1_32("lac",i
, reg_val_double_copy
);
286 case LACD
: { /* Load Atomic Clear Double - lacd rd, (base) */
287 copy_reg_val_double();
288 for(i
= 8; i
< N
; i
+= 8)
289 TEST1_64("lacd",i
, reg_val_double_copy
);
293 printf("Nothing to be executed \n");