Aun entre los mismos ARM Cortex MX vas a encontrar diferencias que pueden ser sutiles, ya que no todos soporta el mismo set de instrucciones. Además va más aya de crear un estándar ya que cada uno tiene distintas opiniones de como hacer las cosas, así como por cuestiones de Propiedad Intelectual.
Pero para ponerlo en otras palabras.
RISC proviene de Reduced Instruction Set Computer y RISC de Reduced Instruction Set Computer.
Von Neumann y Hardvard esta más de lado de donde colocas los datos y donde colocas las instrucciones.
En el caso de Von Neumann tanto las instrucciones como los datos comparte un mismo bus, en el caso de Hardvard datos e instrucciones tiene su propio bus.
Entonces con esto podrías realizar la clasificación:
Por ejemplo los PIC16 cuentan con un número reducido de instrucciones, entonces es RISC y también el bus de datos está separado del bus de instrucciones lo cual lo hace tener una arquitectura Hardvard.
ARM, tiene un conjunto reducido de instrucciones (RISC), pero puedes encontrar tanto Von Neumann como Hardvard, por ejemplo ARM7 es Von Neumann pero AMR9 es Hardvard.
El procesador que usamos en nuestras PC son CISC + Von Neumann.
El porque las instrucciones son distintas es por lo que se conoce como ISA o Instruction Set Architecture y a esto es lo que comúnmente conocemos como ARM, MIPS, x86, i386, PIC16, etc. y dependiendo de su complejidad es que se clasifican en CISC o RISC.
El ISA, es por así decirlo una capa de abstracción entre el hardware y el programador. Tu como programador no necesitas conocer como trabaja internamente el procesador, y los nemotécnicos son los que son traducidos a instrucciones que el MCU entiende y esas instrucciones las puedes ver cuando decompilas un binario.
xc16
Por orden de aparición: Dirección de la instrucción, opcode, instrucción ASM
0000096a <_main>:
96a: 04 00 fa lnk #0x4
96c: 00 0f 78 mov.w w0, [w14]
96e: 11 07 98 mov.w w1, [w14+2]
970: 24 89 28 mov.w #0x8892, w4
972: 84 1f 78 mov.w w4, [w15++]
974: 42 fc 07 rcall 0x1fa <__printf_s>
976: 8f 87 e9 dec2.w w15, w15
978: 00 02 eb clr.w w4
97a: 04 00 78 mov.w w4, w0
97c: 00 80 fa ulnk
97e: 00 00 06 return
gcc (x86_64)
000000000040052d <main>:
40052d: 55 push %rbp
40052e: 48 89 e5 mov %rsp,%rbp
400531: 48 83 ec 10 sub $0x10,%rsp
400535: 89 7d fc mov %edi,-0x4(%rbp)
400538: 48 89 75 f0 mov %rsi,-0x10(%rbp)
40053c: bf e4 05 40 00 mov $0x4005e4,%edi
400541: b8 00 00 00 00 mov $0x0,%eax
400546: e8 c5 fe ff ff callq 400410 <printf@plt>
40054b: b8 00 00 00 00 mov $0x0,%eax
400550: c9 leaveq
400551: c3 retq
400552: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
400559: 00 00 00
40055c: 0f 1f 40 00 nopl 0x0(%rax)
De lo anterior puedes inferir que también se tiene que añadir otra clasificación a los ISA que tiene que ver con el tamaño de la instrucción en términos si es fija o variable. El tamaño de la instrucción en los pic24 es fijo a 24 bits, tanto en los ARM como los x86 son de tamaño variable. Y otra clasificación es si es big endian o little endian.
Una forma muy práctica de ver esto último es tras añadir una variable tipo int
Con GCC en la PC
40053c: c7 45 fc c1 10 01 cc movl $0xcc0110c1,-0x4(%rbp)
Se observa que es Little Endian (c1 10 01 cc)
C fue creado para evitarle al programado lidiar con muchos de estos detalles y crear un lenguaje portable entre arquitecturas, al igual que los Sistemas Operativos fuero creados para administrar los recursos de las computadoras de forma transparente al programador y al usuario final.