Of all the 32-bit and 64-bit CPUs produced every year, most of them use the ARM architecture.
The ARM architecture, like the DLX architecture and the RISC-V architecture and other load/store architectures,
has only 3 kinds of instructions -- (1) instructions that have no effect on memory ("register-register instructions"), (2) instructions that LOAD from external memory into register(s) (and do practically nothing else), and (3) instructions that STORE a value from register(s) into external memory (and do practically nothing else). ( (2) and (3) are "register-memory instructions" ).
Is a memory-memory "operation" implemented as two register-memory
instructions (one for read and the other for write)?
Yes and no.
Computers built with the most common 32-bit or 64-bit CPUs have no memory-memory instructions.
Some read-modify-write-memory operations are very useful in building non-blocking algorithms on systems with more than one processor connected to the same memory.
Some less-common CPU architectures, such as the 32-bit x86 and 64-bit x86-64 architectures, do have memory-memory instructions. In particular, some can perform read-modify-write-memory in a single instruction, such as compare-and-swap.
ARM processors intended for use in multi-processor systems can perform read-modify-write-memory operation, but not as a single instruction -- they split them up into multiple instructions such as load-linked/store conditional, where any one instruction either LOADs or STOREs, not both.
instructions (one for read and the other for write)? Isn't this
inefficient than moving data directly between two places in the same
memory without going via a register?
Yes, this inefficiency is part of the von Neumann bottleneck.
Commodity DRAM only allows one address at a time to be selected,
so even those less-common CPUs that have memory-to-memory operations in a single instruction are forced to implement those instructions as multiple memory cycles -- one memory cycle for the read, and and second memory cycle for the write.
In a small loop where instructions are being read from the instruction cache, a single instruction to do both doesn't run any faster than the 2 separate instructions that would be required on a ARM processor.
Simply copying data from one place to another is extremely common,
so several techniques have been developed for speeding it up, bypassing some or all of the von Nuemann bottleneck:
- some DMA hardware directly copies data from one chip to a different chip in a single memory cycle, typically reading from main memory and writing to some peripheral, or reading from some peripheral and writing into main memory. This requires sending different addresses and different READ/WRITE Enable signals to the two chips.
- Displaying stuff on screen has historically used a variety of hardware speed-ups -- character ROMs, tiled rendering, hardware sprites, blitter hardware for speeding up bit blit operations, dual-ported video DRAM, etc. Some of these techniques involve reading data from one chip and sending it directly to a different chip during a single memory cycle.
- Some Computational RAM chips can copy large blocks of data from one location to another inside the memory chip, much faster than reading that data (from one address) out of the chip, then writing that data (to a different address) back into the chip.