Permalink
Browse files

Convert beta_cpu into a C++ class.

  • Loading branch information...
1 parent cb53e5d commit 2420b45aed6cee978a8e034294f36927afc85cd2 @nelhage committed Nov 9, 2010
Showing with 114 additions and 108 deletions.
  1. +1 −1 bclock.cpp
  2. +2 −2 bconsole.cpp
  3. +56 −65 bcpu.cpp
  4. +37 −29 bcpu.h
  5. +2 −2 bemu.cpp
  6. +13 −5 bt.cpp
  7. +3 −4 bt_helper.S
View
@@ -7,7 +7,7 @@
extern beta_cpu CPU;
static void clock_tick(int signal) {
- set_interrupt(&CPU, INT_CLK);
+ CPU.set_interrupt(INT_CLK);
}
void start_clock(void) {
View
@@ -47,7 +47,7 @@ void* console_process(void *arg UNUSED) {
if(err == 0)
kbd_char = -1;
- set_interrupt(&CPU, INT_KBD);
+ CPU.set_interrupt(INT_KBD);
pthread_cond_wait(&console_cond, &console_mutex);
}
@@ -112,7 +112,7 @@ int beta_rdchr() {
LockMutex locked(console_mutex);
c = kbd_char;
kbd_char = 0;
- clear_interrupt(&CPU, INT_KBD);
+ CPU.clear_interrupt(INT_KBD);
pthread_cond_signal(&console_cond);
}
return c;
View
121 bcpu.cpp
@@ -1,57 +1,52 @@
#include "bemu.h"
-inline void write_reg(beta_cpu *cpu, beta_reg reg, uint32_t val)
-{
- cpu->regs[reg] = val;
-}
-
-void bcpu_process_interrupt(beta_cpu *cpu) {
+void beta_cpu::process_interrupt() {
byteptr isr = 0;
- if(cpu->pending_interrupts & INT_CLK) {
- clear_interrupt(cpu, INT_CLK);
+ if(pending_interrupts & INT_CLK) {
+ clear_interrupt(INT_CLK);
isr = ISR_CLK;
- } else if(cpu->pending_interrupts & INT_KBD) {
+ } else if(pending_interrupts & INT_KBD) {
isr = ISR_KBD;
}
if(isr) {
- cpu->regs[XP] = cpu->PC + 4;
- cpu->PC = isr;
+ regs[XP] = PC + 4;
+ PC = isr;
}
}
-void bcpu_execute_one(beta_cpu *cpu, bdecode *decode) {
+void beta_cpu::execute_one(bdecode *decode) {
uint32_t old_pc;
- cpu->PC += 4;
- cpu->inst_count++;
+ PC += 4;
+ inst_count++;
/*
* Enforce R31 is always 0
*/
- cpu->regs[31] = 0;
+ regs[31] = 0;
- cpu->opcode_counts[decode->opcode]++;
+ opcode_counts[decode->opcode]++;
switch(decode->opcode) {
#define ARITH(NAME, OP) \
case OP_ ## NAME: \
- write_reg(cpu, decode->rc, \
- cpu->regs[decode->ra] OP cpu->regs[decode->rb]); \
+ write_reg(decode->rc, \
+ regs[decode->ra] OP regs[decode->rb]); \
break; \
case OP_ ## NAME ## C: \
- write_reg(cpu, decode->rc, \
- cpu->regs[decode->ra] OP decode->imm); \
+ write_reg(decode->rc, \
+ regs[decode->ra] OP decode->imm); \
break;
/* signed arithmetic op */
#define ARITHS(NAME, OP) \
case OP_ ## NAME: \
- write_reg(cpu, decode->rc, \
- ((int32_t)cpu->regs[decode->ra]) \
- OP ((int32_t)cpu->regs[decode->rb])); \
+ write_reg(decode->rc, \
+ ((int32_t)regs[decode->ra]) \
+ OP ((int32_t)regs[decode->rb])); \
break; \
case OP_ ## NAME ## C: \
- write_reg(cpu, decode->rc, \
- ((int32_t)cpu->regs[decode->ra]) OP decode->imm); \
+ write_reg(decode->rc, \
+ ((int32_t)regs[decode->ra]) OP decode->imm); \
break;
ARITH(ADD, +)
@@ -76,57 +71,55 @@ void bcpu_execute_one(beta_cpu *cpu, bdecode *decode) {
* JMP and friends cannot raise the privilege level by
* setting the supervisor bit
*/
-#define JMP(newpc) ((newpc) & (0x7FFFFFFC | (cpu->PC & 0x80000000)))
+#define JMP(newpc) ((newpc) & (0x7FFFFFFC | (PC & 0x80000000)))
case OP_JMP:
- old_pc = cpu->PC;
- cpu->PC = JMP(cpu->regs[decode->ra]);
- write_reg(cpu, decode->rc, old_pc);
+ old_pc = PC;
+ PC = JMP(regs[decode->ra]);
+ write_reg(decode->rc, old_pc);
break;
case OP_BT:
- old_pc = cpu->PC;
- if(cpu->regs[decode->ra]) {
- cpu->PC = JMP(cpu->PC + WORD2BYTEADDR(decode->imm));
+ old_pc = PC;
+ if(regs[decode->ra]) {
+ PC = JMP(PC + WORD2BYTEADDR(decode->imm));
}
- write_reg(cpu, decode->rc, old_pc);
+ write_reg(decode->rc, old_pc);
break;
case OP_BF:
- old_pc = cpu->PC;
- if(!cpu->regs[decode->ra]) {
- cpu->PC = JMP(cpu->PC + WORD2BYTEADDR(decode->imm));
+ old_pc = PC;
+ if(!regs[decode->ra]) {
+ PC = JMP(PC + WORD2BYTEADDR(decode->imm));
}
- write_reg(cpu, decode->rc, old_pc);
+ write_reg(decode->rc, old_pc);
break;
#undef JMP
case OP_LD:
- LOG("LD from byte %08x", cpu->regs[decode->ra] + decode->imm);
- write_reg(cpu, decode->rc,
- beta_read_mem32(cpu, cpu->regs[decode->ra] + decode->imm));
+ LOG("LD from byte %08x", regs[decode->ra] + decode->imm);
+ write_reg(decode->rc, read_mem32(regs[decode->ra] + decode->imm));
break;
case OP_ST:
- LOG("ST to byte %08x", cpu->regs[decode->ra] + decode->imm);
- beta_write_mem32(cpu, cpu->regs[decode->ra] + decode->imm, cpu->regs[decode->rc]);
+ LOG("ST to byte %08x", regs[decode->ra] + decode->imm);
+ write_mem32(regs[decode->ra] + decode->imm, regs[decode->rc]);
break;
case OP_LDR:
- write_reg(cpu, decode->rc,
- beta_read_mem32(cpu, cpu->PC + WORD2BYTEADDR(decode->imm)));
+ write_reg(decode->rc, read_mem32(PC + WORD2BYTEADDR(decode->imm)));
break;
case OP_CALLOUT:
- if(cpu->PC & PC_SUPERVISOR) {
+ if(PC & PC_SUPERVISOR) {
switch(decode->imm) {
case CALL_HALT:
- cpu->halt = 1;
+ halt = 1;
break;
case CALL_RDCHR:
- cpu->regs[0] = beta_rdchr();
+ regs[0] = beta_rdchr();
break;
case CALL_WRCHR:
- beta_wrchr(cpu->regs[0]);
+ beta_wrchr(regs[0]);
break;
default:
/* Treat an unknown callout as a NOP */
@@ -136,41 +129,39 @@ void bcpu_execute_one(beta_cpu *cpu, bdecode *decode) {
}
/* Fall through to ILLOP in user mode */
default:
- cpu->regs[XP] = cpu->PC;
- cpu->PC = ISR_ILLOP;
+ regs[XP] = PC;
+ PC = ISR_ILLOP;
break;
}
- if(cpu->pending_interrupts && !(cpu->PC & PC_SUPERVISOR)) {
- bcpu_process_interrupt(cpu);
+ if(pending_interrupts && !(PC & PC_SUPERVISOR)) {
+ process_interrupt();
}
}
-void bcpu_reset(beta_cpu *cpu)
+void beta_cpu::reset()
{
- cpu->PC = ISR_RESET;
- cpu->regs[31] = 0;
- cpu->inst_count = 0;
- memset(cpu->opcode_counts, 0, sizeof cpu->opcode_counts);
- cpu->halt = 0;
+ PC = ISR_RESET;
+ regs[31] = 0;
+ inst_count = 0;
+ memset(opcode_counts, 0, sizeof opcode_counts);
+ halt = 0;
}
/*
* Advance the \Beta CPU one cycle
*/
-void bcpu_step_one(beta_cpu *cpu)
+void beta_cpu::step_one()
{
bdecode decode;
uint32_t op;
- op = beta_read_mem32(cpu, cpu->PC);
+ op = read_mem32(PC);
decode_op(op, &decode);
- LOG("[PC=%08x bits=%08x] %s", cpu->PC, op, pp_decode(&decode));
+ LOG("[PC=%08x bits=%08x] %s", PC, op, pp_decode(&decode));
LOG("ra=%08x, rb=%08x, rc=%08x",
- cpu->regs[decode.ra],
- cpu->regs[decode.rb],
- cpu->regs[decode.rc]);
+ regs[decode.ra], regs[decode.rb], regs[decode.rc]);
- bcpu_execute_one(cpu, &decode);
+ execute_one(&decode);
}
View
66 bcpu.h
@@ -16,13 +16,21 @@
#define INT_KBD 0x0002
#define INT_MOUSE 0x0004
-#define set_interrupt(cpu, i) ({(cpu)->pending_interrupts |= (i);})
-#define clear_interrupt(cpu, i) ({(cpu)->pending_interrupts &= ~(i);})
+/*
+ * We address memory by words, internally, but the beta uses
+ * byte-addressing, even though it only supports aligned access
+ */
+#define BYTE2WORDADDR(addr) ((addr) >> 2)
+#define WORD2BYTEADDR(addr) ((addr) << 2)
+/* Typedefs to hopefully make it clear which we're using */
+typedef uint32_t byteptr;
+typedef uint32_t wordptr;
#define XP 30
-typedef struct {
+class beta_cpu {
+ public:
/* This layout is hard-coded into bt.S */
uint32_t regs[32];
uint32_t PC;
@@ -33,39 +41,39 @@ typedef struct {
uint32_t pending_interrupts;
uint32_t inst_count;
uint32_t opcode_counts[256];
-} beta_cpu;
-/*
- * We address memory by words, internally, but the beta uses
- * byte-addressing, even though it only supports aligned access
- */
-#define BYTE2WORDADDR(addr) ((addr) >> 2)
-#define WORD2BYTEADDR(addr) ((addr) << 2)
+ void process_interrupt();
+ void reset();
+ void execute_one(bdecode *decode);
+ void step_one();
-/* Typedefs to hopefully make it clear which we're using */
-typedef uint32_t byteptr;
-typedef uint32_t wordptr;
+ inline uint32_t read_mem32(byteptr addr) {
+ if((addr & ~PC_SUPERVISOR) >= memsize) {
+ panic("Illegal memory reference %08x", addr);
+ }
+ return memory[BYTE2WORDADDR(addr & ~PC_SUPERVISOR)];
+ }
-extern "C" void bcpu_process_interrupt(beta_cpu *cpu);
-void bcpu_execute_one(beta_cpu *cpu, bdecode *decode);
-void bcpu_reset(beta_cpu *cpu);
-void bcpu_step_one(beta_cpu *cpu);
+ inline void write_mem32(byteptr addr, uint32_t val) {
+ if((addr & ~PC_SUPERVISOR) >= memsize) {
+ panic("Illegal memory write %08x", addr);
+ }
+ memory[BYTE2WORDADDR(addr & ~PC_SUPERVISOR)] = val;
+ }
-static uint32_t beta_read_mem32(beta_cpu *cpu, byteptr addr) __attribute__((always_inline));
-static void beta_write_mem32(beta_cpu *cpu, byteptr addr, uint32_t val) __attribute__((always_inline));
+ inline void set_interrupt(int i) {
+ pending_interrupts |= i;
+ }
-static inline uint32_t beta_read_mem32(beta_cpu *cpu, byteptr addr) {
- if((addr & ~PC_SUPERVISOR) >= cpu->memsize) {
- panic("Illegal memory reference %08x", addr);
+ inline void clear_interrupt(int i) {
+ pending_interrupts &= ~i;
}
- return cpu->memory[BYTE2WORDADDR(addr & ~PC_SUPERVISOR)];
-}
-static inline void beta_write_mem32(beta_cpu *cpu, byteptr addr, uint32_t val) {
- if((addr & ~PC_SUPERVISOR) >= cpu->memsize) {
- panic("Illegal memory write %08x", addr);
+ private:
+ inline void write_reg(beta_reg reg, uint32_t val)
+ {
+ regs[reg] = val;
}
- cpu->memory[BYTE2WORDADDR(addr & ~PC_SUPERVISOR)] = val;
-}
+};
#endif
View
@@ -176,7 +176,7 @@ int main(int argc, char **argv)
close(fd);
- bcpu_reset(&CPU);
+ CPU.reset();
signal(SIGINT, handle_sigint);
if(cpu_options.enable_clock) {
@@ -188,7 +188,7 @@ int main(int argc, char **argv)
gettimeofday(&start, NULL);
if(cpu_options.emulate) {
while(!CPU.halt) {
- bcpu_step_one(&CPU);
+ CPU.step_one();
}
} else {
bt_run(&CPU);
View
18 bt.cpp
@@ -191,7 +191,7 @@ void bt_segv(int signo UNUSED, siginfo_t *info, void *ctx) {
beta_cpu *cpu = (beta_cpu*)uctx->uc_mcontext.gregs[REG_EBP];
bdecode decode;
byteptr addr;
- decode_op(beta_read_mem32(cpu, f->pc), &decode);
+ decode_op(cpu->read_mem32(f->pc), &decode);
switch (decode.opcode) {
case OP_LD:
case OP_ST:
@@ -549,9 +549,17 @@ inline void bt_translate_prologue(ccbuff *pbuf, byteptr pc) {
*pbuf = buf;
}
-static void __attribute__((used, regparm(1))) bt_step_one(beta_cpu *cpu) {
- bcpu_step_one(cpu);
-}
+extern "C" {
+ static void bt_step_one(beta_cpu *cpu) __attribute__((used, regparm(1)));
+ static void bt_step_one(beta_cpu *cpu) {
+ cpu->step_one();
+ }
+
+ void bt_process_interrupt(beta_cpu *cpu) __attribute__((used, regparm(1)));
+ void bt_process_interrupt(beta_cpu *cpu) {
+ cpu->process_interrupt();
+ }
+};
inline void bt_translate_interp(ccbuff *pbuf, byteptr pc) {
// Align %esp on a 16-byte boundary to placate OS X
@@ -776,7 +784,7 @@ void bt_translate_and_run(beta_cpu *cpu, uint32_t exact, ccbuff chainptr) {
frag.start_pc = pc;
frag.tail = false;
for(i = 0; i < MAX_FRAG_SIZE; i++) {
- inst = beta_read_mem32(cpu, pc);
+ inst = cpu->read_mem32(pc);
decode_op(inst, &frag.insts[i]);
if(bt_ends_frag(&frag.insts[i])) {
frag.tail = true;
Oops, something went wrong.

0 comments on commit 2420b45

Please sign in to comment.