summaryrefslogtreecommitdiffstats
path: root/ebs.c
diff options
context:
space:
mode:
Diffstat (limited to 'ebs.c')
-rw-r--r--ebs.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/ebs.c b/ebs.c
new file mode 100644
index 0000000..975136d
--- /dev/null
+++ b/ebs.c
@@ -0,0 +1,196 @@
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <string.h>
+#define RAM_VELIKOST 16
+#ifndef NO_HOOKS
+#define HOOK e->
+#else
+#define HOOK
+#endif
+
+typedef uint16_t naslov;
+
+/**
+ * držalo za enobitni stroj
+ */
+
+struct ebs {
+ unsigned char ram[RAM_VELIKOST-2+2]; /**< ne vsebuje programskega števca, ampak vsebuje magic bite */
+ unsigned char * pm;
+ unsigned pm_velikost;
+ uint16_t pc;
+#ifndef NO_HOOKS
+ bool (* peek)(struct ebs *, naslov);
+ void (* poke)(struct ebs *, naslov, bool);
+ struct inštrukcija (* inštrukcija)(struct ebs *, naslov);
+#endif
+ void * userdata;
+ unsigned char vhod_medp;
+ unsigned char vhod_medp_indeks;
+ unsigned char izhod_medp;
+ unsigned char izhod_medp_indeks;
+ void (* vhod_prazen)(struct ebs *);
+ void (* izhod_poln)(struct ebs *);
+};
+
+enum operacija {
+ copy_ram = 0,
+ copy_pm = 1,
+ nand = 2,
+ xor = 3
+};
+
+char * operacija_str[] = {"copyRAM", "copyPM", "nand", "xor"};
+
+struct inštrukcija {
+ unsigned vir;
+ unsigned destinacija;
+ enum operacija operacija;
+ unsigned char * dobesedno;
+};
+
+/**
+ * bralec rama
+ *
+ * @param [in] držalo
+ * @param a [in] naslov
+ * @return vrednost v ramu na tem naslovu
+ */
+
+static bool peek (struct ebs * e, naslov a) {
+ assert(a < RAM_VELIKOST*8+15);
+ if (a < 16)
+ return e->pc & (1 << (15-a));
+ return e->ram[a/8-2] & (1 << (a % 8));
+}
+
+/**
+ * pisalec rama
+ *
+ * @param e [in] držalo
+ * @param a [in] naslov
+ * @param v [in] vrednost
+ */
+
+static void poke (struct ebs * e, naslov a, bool v) {
+ assert(a < RAM_VELIKOST*8+15);
+ if (a < 16) {
+ if (v)
+ e->pc |= (1 << (15-a));
+ else
+ e->pc &= ~(1 << (15-a));
+ return;
+ }
+ if (v)
+ e->ram[a/8-2] |= (1 << (a % 8));
+ else
+ e->ram[a/8-2] &= ~(1 << (a % 8));
+}
+
+static struct inštrukcija inštrukcija (struct ebs * e, naslov a) {
+ struct inštrukcija r = { 0 };
+ if (!(a*2 < e->pm_velikost))
+ return r;
+ r.vir = (e->pm[a*2] & ~1) >> 1;
+ r.destinacija = ((e->pm[a*2] & 1) << 6) | ((e->pm[a*2+1] & 0xfc) >> 2);
+ r.operacija = e->pm[a*2+1] & 3;
+ r.dobesedno = e->pm+a*2;
+ return r;
+}
+
+static void vhod_prazen (struct ebs * e __attribute__((unused))) {
+ return;
+}
+
+static void izhod_poln (struct ebs * e) {
+ putchar(e->izhod_medp);
+ fflush(stdout);
+ e->izhod_medp_indeks = 0;
+}
+
+void ebs_init (struct ebs * e) {
+ memset(e, '\0', sizeof *e);
+ e->peek = peek;
+ e->poke = poke;
+ e->inštrukcija = inštrukcija;
+ e->vhod_medp_indeks = 8;
+ e->izhod_medp_indeks = 0;
+ e->vhod_prazen = vhod_prazen;
+ e->izhod_poln = izhod_poln;
+}
+
+/**
+ * stanje izvajanja
+ */
+
+enum stanje {
+ nadaljuj,
+ konec,
+ čaka_vhod,
+ čaka_izhod
+};
+
+/**
+ * požene eno inštrukcijo
+ *
+ * @param e [in] držalo
+ * @return
+ */
+
+enum stanje ebs_delo (struct ebs * e) {
+ uint16_t prejšnji_pc = e->pc;
+ if (!HOOK peek(e, 16+1) && e->vhod_medp_indeks < 8) {
+ HOOK poke(e, 16+1, 1);
+ HOOK poke(e, 16+0, e->vhod_medp & (1 << (7-e->vhod_medp_indeks++)));
+ }
+ if (HOOK peek(e, 16+3) && e->izhod_medp_indeks < 8) {
+ HOOK poke(e, 16+3, 0);
+ if (HOOK peek(e, 16+2))
+ e->izhod_medp |= (1 << (7-e->izhod_medp_indeks++));
+ else
+ e->izhod_medp &= ~(1 << (7-e->izhod_medp_indeks++));
+
+ }
+ if (e->izhod_medp_indeks > 7)
+ e->izhod_poln(e);
+ struct inštrukcija š = HOOK inštrukcija(e, e->pc++);
+ switch (š.operacija) {
+ case nand:
+ HOOK poke(e, š.destinacija, !(HOOK peek(e, š.destinacija) && HOOK peek(e, š.vir)));
+ break;
+ case xor:
+ HOOK poke(e, š.destinacija, HOOK peek(e, š.destinacija) != HOOK peek(e, š.vir));
+ break;
+ case copy_ram:
+ ;
+ unsigned char buffer[16];
+ for (int i = 0; i < 16; i++)
+ buffer[i] = HOOK peek(e, š.vir+i);
+ for (int i = 0; i < 16; i++)
+ HOOK poke(e, š.destinacija+i, buffer[i]);
+ break;
+ case copy_pm:
+ ;
+ struct inštrukcija vir = HOOK inštrukcija(e, š.vir);
+ for (int i = 0; i < 16; i++)
+ HOOK poke(e, š.destinacija+i, vir.dobesedno ? vir.dobesedno[i/8] & (1 << (7-i%8)) : 0);
+ break;
+ }
+ /* fprintf(stderr, "0x%04x\t%s\t0x%02x\t0x%02x\t0x%02x%02x ", e->pc-1, operacija_str[š.operacija], š.vir, š.destinacija, š.dobesedno[0], š.dobesedno[1]);
+ for (int i = 0; i < 32; i++) {
+ if (peek(e, i))
+ fprintf(stderr, "1");
+ else
+ fprintf(stderr, "0");
+ if (i == 15)
+ fprintf(stderr, " ");
+ }
+ fprintf(stderr, "\n"); */
+ if (e->pc == prejšnji_pc)
+ return konec;
+ return nadaljuj;
+}