summaryrefslogtreecommitdiffstats
path: root/main.cpp
diff options
context:
space:
mode:
authorAnton Luka Šijanec <anton@sijanec.eu>2022-02-04 12:33:36 +0100
committerAnton Luka Šijanec <anton@sijanec.eu>2022-02-04 12:33:36 +0100
commit5839159141b9cfb8d66f0baa456bff1bec6cce44 (patch)
tree37460231c28a9bad4f4000c339621fc1c191f9cd /main.cpp
parentza zunanje delo (diff)
downloadov-5839159141b9cfb8d66f0baa456bff1bec6cce44.tar
ov-5839159141b9cfb8d66f0baa456bff1bec6cce44.tar.gz
ov-5839159141b9cfb8d66f0baa456bff1bec6cce44.tar.bz2
ov-5839159141b9cfb8d66f0baa456bff1bec6cce44.tar.lz
ov-5839159141b9cfb8d66f0baa456bff1bec6cce44.tar.xz
ov-5839159141b9cfb8d66f0baa456bff1bec6cce44.tar.zst
ov-5839159141b9cfb8d66f0baa456bff1bec6cce44.zip
Diffstat (limited to 'main.cpp')
-rw-r--r--main.cpp207
1 files changed, 130 insertions, 77 deletions
diff --git a/main.cpp b/main.cpp
index b0c805f..74b9fad 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,4 +1,3 @@
-#include <iostream>
#include "main.hpp"
using namespace std;
using namespace ov;
@@ -6,26 +5,27 @@ namespace ov {
template<typename value_type, typename index_type>
value_type Ram<value_type, index_type>::peek (index_type addr) {
if (addr < ov->pas)
- return ov->pc & 1 << addr;
- if (addr >= (unsigned int) 1 << ov->ras)
- return ov->opts[addr-(1 << ov->ras)];
- if (addr-ov->pas < IOLEN)
- return ov->io[addr-ov->rs];
+ return ov->pc & 1 << (ov->pas-1-addr);
+ if (addr-ov->pas < IOLEN) {
+ return ov->io[addr-ov->pas];
+ }
+ if (addr >= (unsigned int) 1 << ov->ras())
+ return ov->opts[addr-(1 << ov->ras())];
return storage[addr];
}
template<typename value_type, typename index_type>
void Ram<value_type, index_type>::poke (index_type addr, value_type val) {
if (addr < ov->pas) {
- ov->pc &= ~(1 << addr);
+ ov->pc &= ~(1 << (ov->pas-1-addr));
if (val)
- ov->pc |= 1 << addr;
+ ov->pc |= 1 << (ov->pas-1-addr);
} /* we fall through */
- if (addr >= ov->rs) {
- ov->opts[addr-ov->rs] = val;
- if (val && addr-ov->rs == BUFINCLR)
+ if (addr >= ov->rs()) {
+ ov->opts[addr-ov->rs()] = val;
+ if (val && addr-ov->rs() == BUFINCLR)
while (!ov->inbuf.empty())
ov->inbuf.pop();
- if (val && addr-ov->rs == BUFOUTCLR)
+ if (val && addr-ov->rs() == BUFOUTCLR)
while (!ov->outbuf.empty())
ov->outbuf.pop();
}
@@ -50,48 +50,30 @@ namespace ov {
template<typename value_type, typename index_type>
Ram<value_type, index_type>::Ram (Ov * ov) {
this->ov = ov;
- storage.resize(ov->rs+ov->pas, 0);
- }
- template<typename value_type, typename index_type> // inventor did not say about
- Program<value_type, index_type>::Program (Ov * ov) { // initializing program memory, so I
- this->ov = ov; // do not do that. but by "spec", ram
- storage.resize(ov->ps); // is set to zero and code starts at
- } // pc == 0, unless of course set with
- struct NotImplemented : public exception { // Ov::pc.
- const char * what () const throw () {
- return "Not implemented.";
- }
- } NotImplemented;
- struct NotAvailable : public exception {
- const char * what () const throw () {
- return "I/O is currently not available. You can try again.";
- }
- } NotAvailable;
- struct BufferingRequired : public exception {
- const char * what () const throw () {
- return "I/O buffering must be enabled for this function, but it's not.";
+ storage.resize(ov->rs()+ov->pas, false);
+ for (unsigned int i = 0; i > ov->rs()+ov->pas; i++) {
+ storage[i] = false;
}
- } BufferingRequired;
- struct NotAligned : public exception {
- const char * what () const throw () {
- return "Byte count can't be deserialized without remainder.";
- }
- } NotAligned;
+ }
void Ov::step () { // ko se izvaja inštrukcija, kaže števec programa na naslednjo.
bool b[pas]; // buffer. you have to first read all and then write for COPY
- switch (pm(pc++).i) { // predstavljaj si, da so oklepaji okoli pc++ oglati (;
+ struct instr š = p.peek(pc++);
+ if (pc >= ps())
+ pc = 0;
+ switch (š.i) {
case COPY:
- /* if (pm(pc++).p) // reading from progmem
+ if (š.p) // reading from progmem
for (int i = 0; i < pas; i++)
- b[i] = [pm[pc].serialized];
- else */
+ b[i] = 1 << (7-š.s%pas%8)&serialize(p.peek(š.s/pas))
+ .c_str()[š.s%pas/8];
+ else
for (int i = 0; i < pas; i++)
- b[i] = ram[pm(pc).s+i];
+ b[i] = r.peek(š.s+i);
for (int i = 0; i < pas; i++)
- ram[pm(pc).d+i] = b[i];
+ r.poke(š.d+i, b[i]);
break;
case NAND:
- ram[pm(pc).d] = !(ram[pm(pc).s] & ram[pm(pc).d]);
+ r.poke(š.d, !(r.peek(š.s) & r.peek(š.d)));
break;
}
}
@@ -113,10 +95,9 @@ namespace ov {
throw BufferingRequired;
if (outbuf.size() < 8)
throw NotAvailable;
- char r;
+ char r = '\0';
for (int i = 0; i < 8; i++) { // bitwise endianness is big
bool b = outbuf.front();
- r &= ~(1 << (8-i));
if (b)
r |= 1 << (8-i);
outbuf.pop();
@@ -146,12 +127,13 @@ namespace ov {
} // buffering must be enabled for this to work.
struct instr Ov::deserialize (const char * c) { // treats c as array of is size
struct instr r;
- for (int i = 0; i < ras; i++)
- if (c[i/8] & 1 << (i%8-8))
+ for (unsigned int i = 0; i < ras(); i++) {
+ if (c[i/8] & 1 << (7-i%8))
r.s |= 1 << i;
- for (int i = 0; i < ras; i++) {
- int j = i+ras;
- if (c[j/8] & 1 << (j%8-8))
+ }
+ for (unsigned int i = 0; i < ras(); i++) {
+ unsigned int j = i+ras();
+ if (c[j/8] & 1 << (7-j%8))
r.d |= 1 << i;
}
r.i = c[is-1] & 1 << 6;
@@ -161,54 +143,125 @@ namespace ov {
string Ov::serialize (struct instr * š, unsigned int n) {
char r[sizeof(š)*n];
for (unsigned int i = 0; i < n; i++) {
- for (int j = 0; j < ras; j++) {
- r[i*is+j/8] &= ~(1 << ((ras-1)-j));
- if (š[i].s & 1 << ((ras-1)-j))
- r[i*is+j/8] |= 1 << ((ras-1)-j);
+ for (unsigned int j = 0; j < ras(); j++) {
+ r[i*is+j/8] &= ~(1 << ((ras()-1)-j));
+ if (š[i].s & 1 << ((ras()-1)-j))
+ r[i*is+j/8] |= 1 << ((ras()-1)-j);
}
- for (int j = 0; j < ras; j++) {
- int k = j+ras;
- r[i*is+k/8] &= ~(1 << ((ras-1)-j));
- if (š[i].d & 1 << ((ras-1)-j))
- r[i*is+k/8] |= 1 << ((ras-1)-j);
+ for (unsigned int j = 0; j < ras(); j++) {
+ unsigned int k = j+ras();
+ r[i*is+k/8] &= ~(1 << ((ras()-1)-j));
+ if (š[i].d & 1 << ((ras()-1)-j))
+ r[i*is+k/8] |= 1 << ((ras()-1)-j);
}
- r[i*is+(2*ras)/8] &= 1 << (ras-2);
+ r[i*is+(2*ras())/8] &= 1 << (ras()-2);
if (š[i].i)
- r[i*is+(2*ras)/8] |= 1 << (ras-2);
- r[i*is+(2*ras)/8] &= 1 << (ras-1);
+ r[i*is+(2*ras())/8] |= 1 << (ras()-2);
+ r[i*is+(2*ras())/8] &= 1 << (ras()-1);
if (š[i].p)
- r[i*is+(2*ras)/8] |= 1 << (ras-1);
+ r[i*is+(2*ras())/8] |= 1 << (ras()-1);
}
return string(r); // ugly hack, C/C++ in 2022 still can't return arrays from function
} // serialize(&pstor.storage[0], pstor.storage.size) is valid, because pm has no special MMU
+ string Ov::serialize (struct instr š) {
+ return serialize(&š, 1);
+ }
void Ov::deserialize (istream & v = cin, unsigned int o = 0) {
string c((istreambuf_iterator<char>(v)), istreambuf_iterator<char>()); // eof
+ deserialize(c, o);
+ }
+ void Ov::deserialize (string c, unsigned int o = 0) {
unsigned int s = c.size();
if ((o+s) % is)
throw NotAligned;
for (unsigned int i = 0; i < s; i += is)
- pm[o+i/s] = deserialize(c.c_str()+i);
+ p.poke(o+i/s, deserialize(c.c_str()+i));
}
- void Ov::pd (ostream & o) {
- o << "pc: " << pc << "\t" << "opts:" << (opts[BUFOUT] ? " BUFOUT" : "")
- << (opts[BUFIN] ? " BUFIN" : "") << endl;
+ void Ov::pd (ostream & o = clog) {
+ o << "pc: " << pc << "\topts:" << (opts[BUFOUT] ? " BUFOUT" : "")
+ << (opts[BUFIN] ? " BUFIN" : "") << "\tinstruction: " <<
+ (p.peek(pc).i == COPY ? "COPY from " : "NAND from ") << p.peek(pc).s <<
+ "\tto " << p.peek(pc).d << "\twith meta bit " << p.peek(pc).p << endl;
o << "ram:";
- for (unsigned int i = 0; i < rs; i++) {
+ for (unsigned int i = 0; i < rs(); i++) {
if (i % 8 == 0)
o << " ";
- o << "" << ram[i];
-#pragma message typeof(ram[i])
+ o << (r.peek(i) ? "1" : "0");
}
o << endl;
}
+ vector<struct instr> assembler (string v) {
+ map<string, struct def> defs;
+ vector<struct instr>;
+ int hiaddr = 0;
+ int i = 0;
+ while (i < v.length) {
+ if (i && v[i-1] == '\n' && !v.find("%define ", i)) {
+ i += strlen("%define ");
+ int ž = s.find('(', i);
+ string dn("");
+ if (ž == string::npos) {
+ if ((ž = s.find(' ', i)) == string::npos)
+ if ((ž = s.find('\n', i)) == string::npos)
+ throw EndlessArgument;
+ dn = s.substr(i, ž);
+ } else {
+ dn = s.substr(i, s.find('(', ž));
+ int k = s.find(')', ž);
+ if (k == string::npos)
+ throw EndlessArgument;
+ string args = s.substr(ž+1, k);
+ while ((k = s.find(',', ž)) != string::npos) {
+ defs[dn].args.push_back(s.substr(ž, k));
+ ž = k+1;
+ }
+ i = s.find(')', ž);
+ defs[dn].args.push_back(s.substr(ž, i));
+ }
+ i++;
+ while (s[s.find('\n', i)-1] == '\\') {
+ defs[dn].body.append(s.substr(i, s.find('\n', i)));
+ i = s.find('\n', i)+1;
+ }
+ defs[dn].body.append(s.substr(i, s.find('\n', i)));
+ i = s.find('\n', i)+1;
+ }
+ if (i && v[i-1] == '\n' && !v.find("%macro ", i)) {
+ i += strlen("%macro ");
+ if ((ž = s.find(' ', i)) == string::npos)
+ throw EndlessArgument;
+ string dn = s.substr(i, ž++);
+ n = atoi(s.substring(++i));
+ for (int j = 0; j < n; j++)
+ defs[dn].args.push_back("%" << n+1);
+ if ((i = s.find('\n', i)) == string::npos)
+ throw EndlessBlock;
+ i++;
+ while (s.find("%endmacro", i)) {
+ n = s.find('\n', i)+1;
+ if (n == str::npos)
+ throw EndmacroMissing;
+ defs[dn].body.append(s.substr(i, n));
+ }
+ }
+ }
+ }
}
-int main (void /* int argc, char ** argv */) {
- clog << "OV stands for OB (One Bit) VM (Virtual Machine)." << endl
- << "Stanard input is ready to accept a binary." << endl;
+int main (int argc, char ** argv) {
+ clog << "OV stands for OB (One Bit) VM (Virtual Machine)." << endl;
Ov ov;
- ov.deserialize();
+ ov.pd();
+ if (argc < 2 || !argv[1]) {
+ clog << "Stanard input is ready to accept a binary." << endl
+ << "You can also specify the binary filename in argv[1]" << endl;
+ ov.deserialize();
+ } else {
+ ifstream exe = ifstream(argv[1]);
+ ov.pd();
+ ov.deserialize(exe);
+ }
while (1) {
- ov.pd(cout);
+ ov.pd();
ov.step();
}
return 0;