diff options
Diffstat (limited to 'ebs.c')
-rw-r--r-- | ebs.c | 196 |
1 files changed, 196 insertions, 0 deletions
@@ -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; +} |