summaryrefslogtreecommitdiffstats
path: root/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'main.cpp')
-rw-r--r--main.cpp169
1 files changed, 169 insertions, 0 deletions
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..7254b1e
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,169 @@
+#include <iostream> /* src, dest, instr, padding */
+#include "main.hpp"
+using namespace std;
+using namespace ov;
+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 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);
+ if (val)
+ ov->pc |= 1 << addr;
+ } /* we fall through */
+ if (addr >= (unsigned int) 1 << ov->ras)
+ ov->opts[addr-ov->rs] = val;
+ if (addr >= ov->pas && addr-ov->pas < IOLEN) {
+ if (ov->opts[BUFIN] && addr-ov->pas == INA && val == 0) { /* machine read */
+ if (!ov->inbuf.empty()) { /* and wants more. oh, it looks like we */
+ ov->io[IN] = ov->inbuf.front(); /* have more. we pop the */
+ ov->inbuf.pop(); /* queue, set the input available bit and */
+ ov->io[INA] = 1; /* return, so actual set will not be */
+ return; /* applied, because input is ready. */
+ } /* if we have no input, we just store the zero */
+ } /* we do similar things for output. whenever the machine is ready to */
+ if (ov->opts[BUFOUT] && addr-ov->pas == OUTA && val == 1) { /* output, it */
+ ov->outbuf.push(ov->io[OUT]); /* sets OUTA bit. we push the OUT */
+ ov->io[OUT] = 0; /* value into the output queue and clear OUTA bit */
+ return; /* and therefore indicating the host has read the output. */
+ }
+ ov->io[addr-ov->pas] = val;
+ } /* we fall through, but only if !BUF__ */
+ storage[addr] = val;
+ }
+ template<typename value_type, typename index_type>
+ Ram<value_type, index_type>::Ram (Ov * ov) {
+ this->ov = ov;
+ storage.reserve(ov->rs+ov->pas);
+ for (unsigned int i = 0; i <= ov->rs+ov->pas; i++)
+ poke(i, 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.reserve(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.";
+ }
+ } 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 (;
+ case COPY:
+ for (int i = 0; i < pas; i++)
+ b[i] = ram[pm(pc).s+i];
+ for (int i = 0; i < pas; i++)
+ ram[pm(pc).d+i] = b[i];
+ break;
+ case NAND:
+ ram[pm(pc).d] = !(ram[pm(pc).s] & ram[pm(pc).d]);
+ break;
+ }
+ }
+ bool Ov::out () { /* output from machine. throw NotAvailable when there's nothing */
+ if (opts[BUFOUT]) {
+ if (outbuf.empty())
+ throw NotAvailable;
+ bool o = outbuf.front();
+ outbuf.pop(); /* unconveniently, pop returns nothing */
+ return o;
+ }
+ if (!(io[OUTA]))
+ throw NotAvailable;
+ io[OUTA] = 0;
+ return io[OUT];
+ } /* if BUFOUT is set in opts, this is read from the buffer instead */
+ char Ov::outc () { /* output a byte from machine or throw NotAvailable if not enough bits */
+ if (!opts[BUFOUT])
+ throw BufferingRequired;
+ if (outbuf.size() < 8)
+ throw NotAvailable;
+ char r;
+ 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();
+ }
+ return r;
+ } /* buffering must be enabled for this to work. */
+ void Ov::in (bool i) { /* input to machine. thrw NotAvailable when program hasn't read */
+ if (opts[BUFOUT]) { /* for BUFOUT input we ONLY insert into the queue if machine */
+ if (io[INA]) /* "EWOULDBLOCK", in case it can read we put directly to io. */
+ inbuf.push(i);
+ io[IN] = i;
+ io[INA] = 1;
+ return;
+ }
+ if (io[INA]) /* bit is set, so program in VM must first clear the bit. */
+ throw NotAvailable;
+ io[IN] = i;
+ io[INA] = 1;
+ } /* if BUFIN is set in opts, this is put to the buffer instead */
+ void Ov::inc (char i) { // input a byte to the machine
+ if (!opts[BUFIN])
+ throw BufferingRequired;
+ if (inbuf.size() < 8)
+ throw NotAvailable;
+ for (int x = 7; x >= 0; x--) {
+ in(i & 1 << x);
+ }
+ } // buffering must be enabled for this to work.
+ struct instr Ov::deserialize (const char * c) { // treats i as array of is size
+ struct instr r;
+ for (int i = 0; i < ras; i++)
+ if (c[i/8] & 1 << (i%8-8))
+ r.s |= 1 << i;
+ for (int i = 0; i < ras; i++) {
+ int j = i+ras;
+ if (c[j/8] & 1 << (j%8-8))
+ r.d |= 1 << i;
+ }
+ r.i = c[is-1] & 1 << 6;
+ r.p = c[is-1] & 1 << 7;
+ return r;
+ }
+ void Ov::deserialize (istream & v = cin, unsigned int o = 0) {
+ string c((istreambuf_iterator<char>(v)), istreambuf_iterator<char>()); // eof
+ unsigned int s = c.size();
+ if (s % 2)
+ throw NotAligned;
+ for (unsigned int i = 0; i < s; i += is) {
+ pm[o+i/s] = deserialize(c.c_str()+i);
+ }
+ }
+}
+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;
+ Ov ov;
+ ov.deserialize();
+ return 0;
+}