190 |
190 |
191 return upd; |
191 return upd; |
192 } |
192 } |
193 |
193 |
194 |
194 |
195 //------------ |
|
196 // Atomic::inc |
|
197 //------------ |
|
198 // These methods force the value in memory to be incremented (augmented by 1). |
|
199 // Both, memory value and increment, are treated as 32bit signed binary integers. |
|
200 // No overflow exceptions are recognized, and the condition code does not hold |
|
201 // information about the value in memory. |
|
202 // |
|
203 // The value in memory is updated by using a compare-and-swap instruction. The |
|
204 // instruction is retried as often as required. |
|
205 |
|
206 inline void Atomic::inc(volatile jint* dest) { |
|
207 unsigned int old, upd; |
|
208 |
|
209 if (VM_Version::has_LoadAndALUAtomicV1()) { |
|
210 // tty->print_cr("Atomic::inc called... dest @%p", dest); |
|
211 __asm__ __volatile__ ( |
|
212 " LGHI 2,1 \n\t" // load increment |
|
213 " LA 3,%[mem] \n\t" // force data address into ARG2 |
|
214 // " LAA %[upd],%[inc],%[mem] \n\t" // increment and get old value |
|
215 // " LAA 2,2,0(3) \n\t" // actually coded instruction |
|
216 " .byte 0xeb \n\t" // LAA main opcode |
|
217 " .byte 0x22 \n\t" // R1,R3 |
|
218 " .byte 0x30 \n\t" // R2,disp1 |
|
219 " .byte 0x00 \n\t" // disp2,disp3 |
|
220 " .byte 0x00 \n\t" // disp4,disp5 |
|
221 " .byte 0xf8 \n\t" // LAA minor opcode |
|
222 " AGHI 2,1 \n\t" // calc new value in register |
|
223 " LR %[upd],2 \n\t" // move to result register |
|
224 //---< outputs >--- |
|
225 : [upd] "=&d" (upd) // write-only, updated counter value |
|
226 , [mem] "+Q" (*dest) // read/write, memory to be updated atomically |
|
227 //---< inputs >--- |
|
228 : |
|
229 // : [inc] "a" (inc) // read-only. |
|
230 //---< clobbered >--- |
|
231 : "cc", "r2", "r3", "memory" |
|
232 ); |
|
233 } else { |
|
234 __asm__ __volatile__ ( |
|
235 " LLGF %[old],%[mem] \n\t" // get old value |
|
236 "0: LA %[upd],1(,%[old]) \n\t" // calc result |
|
237 " CS %[old],%[upd],%[mem] \n\t" // try to xchg res with mem |
|
238 " JNE 0b \n\t" // no success? -> retry |
|
239 //---< outputs >--- |
|
240 : [old] "=&a" (old) // write-only, old counter value |
|
241 , [upd] "=&d" (upd) // write-only, updated counter value |
|
242 , [mem] "+Q" (*dest) // read/write, memory to be updated atomically |
|
243 //---< inputs >--- |
|
244 : |
|
245 //---< clobbered >--- |
|
246 : "cc", "memory" |
|
247 ); |
|
248 } |
|
249 } |
|
250 |
|
251 inline void Atomic::inc_ptr(volatile intptr_t* dest) { |
|
252 unsigned long old, upd; |
|
253 |
|
254 if (VM_Version::has_LoadAndALUAtomicV1()) { |
|
255 __asm__ __volatile__ ( |
|
256 " LGHI 2,1 \n\t" // load increment |
|
257 " LA 3,%[mem] \n\t" // force data address into ARG2 |
|
258 // " LAAG %[upd],%[inc],%[mem] \n\t" // increment and get old value |
|
259 // " LAAG 2,2,0(3) \n\t" // actually coded instruction |
|
260 " .byte 0xeb \n\t" // LAA main opcode |
|
261 " .byte 0x22 \n\t" // R1,R3 |
|
262 " .byte 0x30 \n\t" // R2,disp1 |
|
263 " .byte 0x00 \n\t" // disp2,disp3 |
|
264 " .byte 0x00 \n\t" // disp4,disp5 |
|
265 " .byte 0xe8 \n\t" // LAA minor opcode |
|
266 " AGHI 2,1 \n\t" // calc new value in register |
|
267 " LR %[upd],2 \n\t" // move to result register |
|
268 //---< outputs >--- |
|
269 : [upd] "=&d" (upd) // write-only, updated counter value |
|
270 , [mem] "+Q" (*dest) // read/write, memory to be updated atomically |
|
271 //---< inputs >--- |
|
272 : |
|
273 // : [inc] "a" (inc) // read-only. |
|
274 //---< clobbered >--- |
|
275 : "cc", "r2", "r3", "memory" |
|
276 ); |
|
277 } else { |
|
278 __asm__ __volatile__ ( |
|
279 " LG %[old],%[mem] \n\t" // get old value |
|
280 "0: LA %[upd],1(,%[old]) \n\t" // calc result |
|
281 " CSG %[old],%[upd],%[mem] \n\t" // try to xchg res with mem |
|
282 " JNE 0b \n\t" // no success? -> retry |
|
283 //---< outputs >--- |
|
284 : [old] "=&a" (old) // write-only, old counter value |
|
285 , [upd] "=&d" (upd) // write-only, updated counter value |
|
286 , [mem] "+Q" (*dest) // read/write, memory to be updated atomically |
|
287 //---< inputs >--- |
|
288 : |
|
289 //---< clobbered >--- |
|
290 : "cc", "memory" |
|
291 ); |
|
292 } |
|
293 } |
|
294 |
|
295 inline void Atomic::inc_ptr(volatile void* dest) { |
|
296 inc_ptr((volatile intptr_t*)dest); |
|
297 } |
|
298 |
|
299 //------------ |
|
300 // Atomic::dec |
|
301 //------------ |
|
302 // These methods force the value in memory to be decremented (augmented by -1). |
|
303 // Both, memory value and decrement, are treated as 32bit signed binary integers. |
|
304 // No overflow exceptions are recognized, and the condition code does not hold |
|
305 // information about the value in memory. |
|
306 // |
|
307 // The value in memory is updated by using a compare-and-swap instruction. The |
|
308 // instruction is retried as often as required. |
|
309 |
|
310 inline void Atomic::dec(volatile jint* dest) { |
|
311 unsigned int old, upd; |
|
312 |
|
313 if (VM_Version::has_LoadAndALUAtomicV1()) { |
|
314 __asm__ __volatile__ ( |
|
315 " LGHI 2,-1 \n\t" // load increment |
|
316 " LA 3,%[mem] \n\t" // force data address into ARG2 |
|
317 // " LAA %[upd],%[inc],%[mem] \n\t" // increment and get old value |
|
318 // " LAA 2,2,0(3) \n\t" // actually coded instruction |
|
319 " .byte 0xeb \n\t" // LAA main opcode |
|
320 " .byte 0x22 \n\t" // R1,R3 |
|
321 " .byte 0x30 \n\t" // R2,disp1 |
|
322 " .byte 0x00 \n\t" // disp2,disp3 |
|
323 " .byte 0x00 \n\t" // disp4,disp5 |
|
324 " .byte 0xf8 \n\t" // LAA minor opcode |
|
325 " AGHI 2,-1 \n\t" // calc new value in register |
|
326 " LR %[upd],2 \n\t" // move to result register |
|
327 //---< outputs >--- |
|
328 : [upd] "=&d" (upd) // write-only, updated counter value |
|
329 , [mem] "+Q" (*dest) // read/write, memory to be updated atomically |
|
330 //---< inputs >--- |
|
331 : |
|
332 // : [inc] "a" (inc) // read-only. |
|
333 //---< clobbered >--- |
|
334 : "cc", "r2", "r3", "memory" |
|
335 ); |
|
336 } else { |
|
337 __asm__ __volatile__ ( |
|
338 " LLGF %[old],%[mem] \n\t" // get old value |
|
339 // LAY not supported by inline assembler |
|
340 // "0: LAY %[upd],-1(,%[old]) \n\t" // calc result |
|
341 "0: LR %[upd],%[old] \n\t" // calc result |
|
342 " AHI %[upd],-1 \n\t" |
|
343 " CS %[old],%[upd],%[mem] \n\t" // try to xchg res with mem |
|
344 " JNE 0b \n\t" // no success? -> retry |
|
345 //---< outputs >--- |
|
346 : [old] "=&a" (old) // write-only, old counter value |
|
347 , [upd] "=&d" (upd) // write-only, updated counter value |
|
348 , [mem] "+Q" (*dest) // read/write, memory to be updated atomically |
|
349 //---< inputs >--- |
|
350 : |
|
351 //---< clobbered >--- |
|
352 : "cc", "memory" |
|
353 ); |
|
354 } |
|
355 } |
|
356 |
|
357 inline void Atomic::dec_ptr(volatile intptr_t* dest) { |
|
358 unsigned long old, upd; |
|
359 |
|
360 if (VM_Version::has_LoadAndALUAtomicV1()) { |
|
361 __asm__ __volatile__ ( |
|
362 " LGHI 2,-1 \n\t" // load increment |
|
363 " LA 3,%[mem] \n\t" // force data address into ARG2 |
|
364 // " LAAG %[upd],%[inc],%[mem] \n\t" // increment and get old value |
|
365 // " LAAG 2,2,0(3) \n\t" // actually coded instruction |
|
366 " .byte 0xeb \n\t" // LAA main opcode |
|
367 " .byte 0x22 \n\t" // R1,R3 |
|
368 " .byte 0x30 \n\t" // R2,disp1 |
|
369 " .byte 0x00 \n\t" // disp2,disp3 |
|
370 " .byte 0x00 \n\t" // disp4,disp5 |
|
371 " .byte 0xe8 \n\t" // LAA minor opcode |
|
372 " AGHI 2,-1 \n\t" // calc new value in register |
|
373 " LR %[upd],2 \n\t" // move to result register |
|
374 //---< outputs >--- |
|
375 : [upd] "=&d" (upd) // write-only, updated counter value |
|
376 , [mem] "+Q" (*dest) // read/write, memory to be updated atomically |
|
377 //---< inputs >--- |
|
378 : |
|
379 // : [inc] "a" (inc) // read-only. |
|
380 //---< clobbered >--- |
|
381 : "cc", "r2", "r3", "memory" |
|
382 ); |
|
383 } else { |
|
384 __asm__ __volatile__ ( |
|
385 " LG %[old],%[mem] \n\t" // get old value |
|
386 // LAY not supported by inline assembler |
|
387 // "0: LAY %[upd],-1(,%[old]) \n\t" // calc result |
|
388 "0: LGR %[upd],%[old] \n\t" // calc result |
|
389 " AGHI %[upd],-1 \n\t" |
|
390 " CSG %[old],%[upd],%[mem] \n\t" // try to xchg res with mem |
|
391 " JNE 0b \n\t" // no success? -> retry |
|
392 //---< outputs >--- |
|
393 : [old] "=&a" (old) // write-only, old counter value |
|
394 , [upd] "=&d" (upd) // write-only, updated counter value |
|
395 , [mem] "+Q" (*dest) // read/write, memory to be updated atomically |
|
396 //---< inputs >--- |
|
397 : |
|
398 //---< clobbered >--- |
|
399 : "cc", "memory" |
|
400 ); |
|
401 } |
|
402 } |
|
403 |
|
404 inline void Atomic::dec_ptr(volatile void* dest) { |
|
405 dec_ptr((volatile intptr_t*)dest); |
|
406 } |
|
407 |
|
408 //------------- |
195 //------------- |
409 // Atomic::xchg |
196 // Atomic::xchg |
410 //------------- |
197 //------------- |
411 // These methods force the value in memory to be replaced by the new value passed |
198 // These methods force the value in memory to be replaced by the new value passed |
412 // in as argument. |
199 // in as argument. |