On 30/05/25 1:37 am, Peter Bergner wrote: > On 5/29/25 5:35 AM, Segher Boessenkool wrote: >> >>> +#define _AMO_LD_INCREMENT(NAME, TYPE, OPCODE, FC) \ >>> +static __inline__ TYPE >>> \ >>> +NAME (TYPE *_PTR) \ >>> +{ \ >>> + TYPE _RET; >>> \ >>> + __asm__ volatile (OPCODE " %[ret],%P[addr],%[code]\n" >>> \ >>> + : [addr] "+Q" (_PTR[0]), [ret] "=r" (_RET) \ >>> + : "Q" (*(TYPE (*)[2]) _PTR), [code] "n" (FC)); \ >>> + return _RET; >>> \ >>> +} >> >> I don't understand the [2]. Should it be [1]? These instructions >> can use the value at mem+s (as the ISA names things) as input, but not >> mem+2*s. > > I think 2 is correct here. This 2 isn't an index like the 0 in _PTR[0], > but it's a size. This specific use is trying to say we're reading from > memory and we're reading 2 locations, mem(EA,s) and mem(EA+s,s). > Maybe we could use separate mentions of _PTR[0] and _PTR[1] instead??? > We don't actually use that "operand" in the instruction, it's just there > to tell the compiler that those memory locations are read.
IIUC, (*(TYPE (*)[2]) _PTR) says that _PTR points to an array of 2 integers. Can the constraint 'Q' be used to denote two memory locations? In any case, for _AMO_LD_DECREMENT, we should specify the two locations separately (as _PTR[0] and _PTR[-1]). Otherwise, how would the compiler know which 2 memory locations the expression "(*(TYPE (*)[2]) _PTR)" is referring to? Regards, Surya