spl

systems programming language
git clone http://frotz.net/git/spl.git
Log | Files | Refs | README | LICENSE

cpu-sr32.c (3044B)


      1 // Copyright 2025, Brian Swetland <swetland@frotz.net>
      2 // Licensed under the Apache License, Version 2.0.
      3 
      4 #include <stdio.h>
      5 #include <unistd.h>
      6 
      7 #include <emulator-sr32.h>
      8 
      9 #define WITH_TRACE 1
     10 
     11 void sr32core(CpuState *s) {
     12 	int32_t a, b, n;
     13 	uint32_t pc = s->pc;
     14 	for (;;) {
     15 	int32_t ins = mem_rd32(pc);
     16 #if WITH_TRACE
     17 	if (s->flags & F_TRACE_FETCH) {
     18 		fprintf(stderr,"%08x %08x\n", pc, ins);
     19 	}
     20 #endif
     21 	pc += 4;
     22 	switch ((ins >> 3) & 7) {
     23 	case 0b000:
     24 	case 0b001:
     25 	case 0b010:
     26 	case 0b011: // I/R
     27 		a = s->r[(ins >> 11) & 31];
     28 		b = ins >> 16;
     29 		if (ins & 0b010000) b = s->r[b & 31];
     30 		switch (ins & 15) {
     31 		case 0x0: n = a + b; break;
     32 		case 0x1: n = a - b; break;
     33 		case 0x2: n = a & b; break;
     34 		case 0x3: n = a | b; break;
     35 		case 0x4: n = a ^ b; break;
     36 		case 0x5: n = a << (b & 31); break;
     37 		case 0x6: n = ((uint32_t)a) >> (b & 31); break;
     38 		case 0x7: n = a >> (b & 31); break;
     39 		case 0x8: n = (a < b) ? 1 : 0; break;
     40 		case 0x9: n = (((uint32_t)a) < ((uint32_t)b)) ? 1 : 0; break;
     41 		case 0xa: n = a * b; break;
     42 		case 0xb: n = a / b; break;
     43 		case 0xf: n = pc; pc = a + b; break;
     44 		default: goto undef;
     45 		}
     46 		b = (ins >> 6) & 31;
     47 		if (b) {
     48 			s->r[b] = n;
     49 #if WITH_TRACE
     50 			if (s->flags & F_TRACE_REGS) {
     51 				fprintf(stderr,"%08x -> X%d\n", n, b);
     52 			}
     53 #endif
     54 		}
     55 		break;
     56 	case 0b100: // L
     57 		a = s->r[(ins >> 11) & 31] + (ins >> 16);
     58 		switch (ins & 7) {
     59 		case 0: n = mem_rd32(a); break;
     60 		case 1: n = mem_rd16(a); if (n & 0x8000) n |= 0xFFFF0000; break;
     61 		case 2: n = mem_rd8(a); if (n & 0x80) n |= 0xFFFFFF00; break;
     62 		case 3: n = io_rd32(s, a); break;
     63 		case 4: n = ins & 0xFFFF0000; break;
     64 		case 5: n = mem_rd16(a); break;
     65 		case 6: n = mem_rd8(a); break;
     66 		case 7: n = pc + (ins & 0xFFFF0000); break;
     67 		}
     68 		b = (ins >> 6) & 31;
     69 		if (b) {
     70 			s->r[b] = n;
     71 #if WITH_TRACE
     72 			if (s->flags & F_TRACE_REGS) {
     73 				fprintf(stderr,"%08x -> X%d\n", n, b);
     74 			}
     75 #endif
     76 		}
     77 		break;
     78 	case 0b101: // S
     79 		a = s->r[(ins >> 11) & 31] + (ins >> 16);
     80 		b = s->r[(ins >> 6) & 31];
     81 		switch (ins & 7) {
     82 		case 0: mem_wr32(a, b); break;
     83 		case 1: mem_wr16(a, b); break;
     84 		case 2: mem_wr8(a, b); break;
     85 		case 3:	io_wr32(s, a, b); break;
     86 		default: goto undef;
     87 		}
     88 		break;
     89 	case 0b110: // B
     90 		a = s->r[(ins >> 11) & 31];
     91 		b = s->r[(ins >> 6) & 31];
     92 		switch (ins & 7) {
     93 		case 0: n = (a == b); break;
     94 		case 1: n = (a != b); break;
     95 		case 2: n = (a < b); break;
     96 		case 3: n = (((uint32_t)a) < ((uint32_t)b)); break;
     97 		case 4: n = (a >= b); break;
     98 		case 5: n = (((uint32_t)a) >= ((uint32_t)b)); break;
     99 		default: goto undef;
    100 		}
    101 		if (n) pc = pc + (ins >> 16);
    102 		break;
    103 	case 0b111: // J
    104 		switch (ins & 7) {
    105 		case 0:
    106 			a = ins >> 11;
    107 			b = (ins >> 6) & 31;
    108 			if (b) s->r[b] = pc;
    109 			pc = pc + a;
    110 			break;
    111 		case 1: s->pc = pc; do_syscall(s, ins >> 11); break;
    112 		//case 1: s->xpc = pc; pc = s->vec_syscall; break;
    113 		//case 2: s->xpc = pc; pc = s->vec_break; break;
    114 		//case 3: pc = s->xpc;
    115 		default: /* undefined instruction */
    116 undef:
    117 		s->pc = pc;
    118 		do_undef(s, ins);
    119 		return;
    120 		//s->xpc = pc; pc = s->vec_undef;
    121 		}
    122 		break;
    123 	}
    124 	}
    125 }
    126