En segundo lugar, sugiero usar LCC. Lo usé en este proyecto casero RISC de 16 bits: http://fpgacpu.org/xsoc/cc.html.
No creo que deba hacer mucha diferencia si construye la variante de 8 bits y usa 3 add-with-carries para incrementar IP, o la variante de 24 bits y lo hace todo en hardware. Puede ocultar la diferencia en su ensamblador.
Si miras mi artículo anterior, o una CPU aún más simple aquí: http://fpgacpu.org/papers/soc-gr0040-paper.pdf verás que realmente no necesitas tantos operadores/instrucciones para cubrir el entero del repertorio C. De hecho, hay una utilidad lcc (ops) para imprimir el operador mínimo establecido para una máquina determinada.
Para obtener más información, véase mi artículo en portar LCC a una nueva máquina aquí: http://www.fpgacpu.org/usenet/lcc.html
Una vez que había portado LCC, escribí un ensamblador y se sintetizó un repertorio más amplio de instrucciones de los básicos.Por ejemplo, mi máquina tenía la carga de bytes sin signo, pero no firmado carga de bytes, por lo que emite esta secuencia:
lbs rd,imm(rs) ->
lbu rd,imm(rs)
lea r1,0x80
xor rd,r1
sub rd,r1
Así que creo que se puede llegar a funcionar con esta cubierta min de operaciones:
registers
load register with constant
load rd = *rs
store *rs1 = rs2
+ - (w/ w/o carry) // actually can to + with - and^
>> 1 // << 1 is just +
&^ // (synthesize ~ from ^, | from & and ^)
jump-and-link rd,rs // rd = pc, pc = rs
skip-z/nz/n/nn rs // skip next insn on rs==0, !=0, <0, >=0
Aún más simple es no tener registros (o de forma equivalente, desenfocar los registros con la memoria, todos los registros tienen una dirección de memoria).
Separe un registro para SP y escriba la función prolog/epilog handler en el compilador y no tendrá que preocuparse por las instrucciones de la pila. Solo hay un código para almacenar cada uno de los registros de guardado de llamadas, ajustar el SP por el tamaño del marco, y así sucesivamente.
Las interrupciones (y el retorno de las interrupciones) son sencillas. Todo lo que necesita hacer es forzar una instrucción de salto y enlace en el registro de instrucciones. Si elige el patrón de bits para que sea algo así como 0 y coloque las direcciones correctas en el registro de origen rs (especialmente si es r0), se puede hacer con una entrada de restablecimiento de flip-flop o una fuerza adicional para 0 y puerta. Utilizo un truco similar en el segundo documento anterior.
Proyecto interesante. Veo que un concurso TTL/7400 está en marcha y yo estaba pensando en cuán simple podría ser una máquina para salirse con la suya y sería una trampa incorporar una SRAM asíncrona de 32 KB o 128 KB a la máquina para contener el código y los datos.
De todos modos, feliz piratería!
p.s.
1) Querrá decidir qué tan grande es cada tipo integral. Ciertamente puede hacer char, short, int, long, long long, etc. del mismo tamaño, una palabra 24b, si lo desea, aunque no será compatible en rangos de representación mínima.
2) Y aunque me centré en lcc aquí, preguntabas por C++. Recomiendo persuadir C primero. Una vez que tenga las cosas resueltas para C, incluidos *, /,% operadores en software, etc., debería ser más manejable pasar a C++ completo, ya sea en LLVM o GCC. La diferencia entre C y C++ es "solo" las tablas y secuencias de códigos RTTI adicionales (completamente desarrolladas en el primitivo operador de repertorio entero C) requeridas para manejar llamadas a funciones virtuales, puntero a la desreferencia de miembros, moldes dinámicos, constructores estáticos, excepción manejo, etc.
Esto puede ser una pregunta ingenua, pero ¿por qué tiene que implementar todas las características de C++? ¿No puede simplemente escribir una nueva arquitectura de destino LLVM y Clang compilará C++ sin problemas? –
@Dan Cecile Eso es exactamente lo que voy a hacer. Pero puede ver que escribir backend LLVM para CPU de 8 bits con espacio de memoria de 24 bits podría ser un poco no trivial. – BarsMonster
Entonces tiene 4 partes; averiguar cómo implementar el [lenguaje ensamblador LLVM] (http://llvm.org/docs/LangRef.html) funciona con su hardware, copiando y adaptando un [destino LLVM existente] (https://github.com/earl/llvm-mirror/tree/master/lib/Target) para trabajar con su hardware, descubriendo cómo obtener Clang para [generar bytecode LLVM de 8 bits] (http://clang.llvm.org/doxygen/classclang_1_1TargetInfo.html) ([los tamaños del puntero son configurables] (http://clang-developers.42468.n3.nabble.com/Re-targeting-clang-to-a-new-architecture-tp761920p762813.html)), luego cambia el hardware a ser más adecuado. –