I secondo il suggerimento di utilizzare LCC. L'ho usato in questo progetto RISC homebrew a 16 bit: http://fpgacpu.org/xsoc/cc.html.
Non penso che dovrebbe fare molta differenza se si costruisce la variante a 8 bit e si usano 3 add-with-carry per incrementare l'IP, o la variante a 24 bit e fare tutto in hardware. Puoi nascondere la differenza nel tuo assemblatore.
Se si guarda il mio articolo qui sopra, o una CPU ancora più semplice qui: http://fpgacpu.org/papers/soc-gr0040-paper.pdf vedrai che non hai davvero bisogno di molti operatori/istruzioni per coprire il Repeaterire intero C. In effetti esiste una utility lcc (ops) per stampare l'operatore minimo impostato per una data macchina.
Per ulteriori informazioni si veda il mio articolo sul porting LCC per una nuova macchina qui: http://www.fpgacpu.org/usenet/lcc.html
Una volta avevo portato LCC, ho scritto un assemblatore, ed è sintetizzato una grande repertorio delle istruzioni da quelli di base.Per esempio, la mia macchina ha avuto carico-byte senza segno, ma non carico byte-firmato, così ho emesso questa sequenza:
lbs rd,imm(rs) ->
lbu rd,imm(rs)
lea r1,0x80
xor rd,r1
sub rd,r1
Quindi penso che si può ottenere con questo min copertina di operazioni:
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
Ancora più semplice è non avere registri (o registri di sfocatura equivalenti con memoria - tutti i registri hanno un indirizzo di memoria).
Impostare un registro per SP e scrivere la funzione prolog/epilog handler nel compilatore e non sarà necessario preoccuparsi delle istruzioni di stack. C'è solo il codice per memorizzare ciascuno dei registri di salvataggio del callee, regolare l'SP in base alla dimensione del frame e così via.
Interruzioni (e ritorno da interrupt) sono semplici. Tutto ciò che devi fare è forzare un'istruzione Jump-and-Link nel registro delle istruzioni. Se si sceglie il modello di bit affinché sia qualcosa come 0 e si inseriscano gli indirizzi giusti nel registro sorgente rs (specialmente se è r0), può essere fatto con un ingresso di reset flip-flop o un extra 0 e cancello. Io uso un trucco simile nel secondo foglio sopra.
Progetto interessante. Vedo che è in corso un concorso TTL/7400 e stavo pensando a quanto una macchina potesse essere semplice e sarebbe stato ingannevole aggiungere alla macchina una SRAM asincrona da 32 KB o 128 KB per contenere codice e dati.
In ogni caso, felice hacking!
p.s.
1) Sarà necessario decidere la dimensione di ciascun tipo di integrale. Puoi certamente creare char, short, int, long, long long, ecc. Della stessa dimensione, una parola 24b, se lo desideri, anche se non sarà conforme in intervalli di rappresentazione min.
2) E anche se mi sono concentrato su lcc qui, mi stavi chiedendo del C++. Per prima cosa raccomando di persuadere C. Una volta che hai capito le cose per C, inclusi gli operatori *, /,% nel software, ecc., Dovrebbe essere più trattabile passare al C++ completo, sia in LLVM che in GCC. La differenza tra C e C++ è "solo" i vtables extra e le tabelle RTTI e le sequenze di codice (interamente compilate dal ripetitore di operatore intero C primitivo) richieste per gestire chiamate di funzioni virtuali, puntatore alla dereferenziazione di membri, stringhe dinamiche, costruttori statici, eccezione gestione, ecc.
Questa potrebbe essere una domanda ingenua, ma perché è necessario implementare tutte le funzionalità di C++? Non puoi semplicemente scrivere una nuova architettura di destinazione LLVM e Clang compilerà C++ senza problemi? –
@Dan Cecile Questo è esattamente quello che sto per fare. Ma si può vedere che scrivere backend LLVM per CPU a 8 bit con spazio di memoria a 24 bit potrebbe essere un po 'non banale. – BarsMonster
Quindi hai 4 parti; capire come implementare il [linguaggio assembly LLVM] (http://llvm.org/docs/LangRef.html) funziona con il tuo hardware, copiando e adattando un [target LLVM esistente] (https://github.com/earl/llvm-mirror/tree/master/lib/Target) per lavorare con il tuo hardware, cercando di capire come ottenere Clang a [generare un bytecode LLVM a 8 bit] (http://clang.llvm.org/doxygen/classclang_1_1TargetInfo.html) ([le dimensioni del puntatore sono configurabili] (http://clang-developers.42468.n3.nabble.com/Re-targeting-clang-to-a-newewarchitecture-tp761920p762813.html)), quindi modificare l'hardware in essere più adatto. –