OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [trunk/] [sim/] [cpu.c] - Diff between revs 25 and 168

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 25 Rev 168
/*
/*
 * cpu.c -- CPU simulation
 * cpu.c -- CPU simulation
 */
 */
 
 
 
 
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <setjmp.h>
#include <setjmp.h>
 
 
#include "common.h"
#include "common.h"
#include "console.h"
#include "console.h"
#include "error.h"
#include "error.h"
#include "except.h"
#include "except.h"
#include "instr.h"
#include "instr.h"
#include "cpu.h"
#include "cpu.h"
#include "mmu.h"
#include "mmu.h"
#include "timer.h"
#include "timer.h"
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
#define RR(n)           r[n]
#define RR(n)           r[n]
#define WR(n,d)         ((void) ((n) != 0 ? r[n] = (d) : (d)))
#define WR(n,d)         ((void) ((n) != 0 ? r[n] = (d) : (d)))
 
 
#define V               (psw & PSW_V)
#define V               (psw & PSW_V)
#define UM              (psw & PSW_UM)
#define UM              (psw & PSW_UM)
#define PUM             (psw & PSW_PUM)
#define PUM             (psw & PSW_PUM)
#define OUM             (psw & PSW_OUM)
#define OUM             (psw & PSW_OUM)
#define IE              (psw & PSW_IE)
#define IE              (psw & PSW_IE)
#define PIE             (psw & PSW_PIE)
#define PIE             (psw & PSW_PIE)
#define OIE             (psw & PSW_OIE)
#define OIE             (psw & PSW_OIE)
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
static Bool debugIRQ = false;   /* set to true if debugging IRQs */
static Bool debugIRQ = false;   /* set to true if debugging IRQs */
 
 
static Word pc;                 /* program counter */
static Word pc;                 /* program counter */
static Word psw;                /* processor status word */
static Word psw;                /* processor status word */
static Word r[32];              /* general purpose registers */
static Word r[32];              /* general purpose registers */
 
 
static unsigned irqPending;     /* one bit for each pending IRQ */
static unsigned irqPending;     /* one bit for each pending IRQ */
 
 
static Bool breakSet;           /* breakpoint set if true */
static Bool breakSet;           /* breakpoint set if true */
static Word breakAddr;          /* if breakSet, this is where */
static Word breakAddr;          /* if breakSet, this is where */
 
 
static Word total;              /* counts total number of instrs */
static Word total;              /* counts total number of instrs */
 
 
static Bool run;                /* CPU runs continuously if true */
static Bool run;                /* CPU runs continuously if true */
 
 
static Word startAddr;          /* start of ROM (or start of RAM, */
static Word startAddr;          /* start of ROM (or start of RAM, */
                                /* in case a program was loaded) */
                                /* in case a program was loaded) */
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
static void handleInterrupts(void) {
static void handleInterrupts(void) {
  unsigned irqMask;
  unsigned irqMask;
  unsigned irqSeen;
  unsigned irqSeen;
  int priority;
  int priority;
 
 
  /* handle exceptions and interrupts */
  /* handle exceptions and interrupts */
  if (irqPending == 0) {
  if (irqPending == 0) {
    /* no exception or interrupt pending */
    /* no exception or interrupt pending */
    return;
    return;
  }
  }
  /* at least one exception or interrupt is pending */
  /* at least one exception or interrupt is pending */
  irqMask = ~PSW_IRQ_MASK | (psw & PSW_IRQ_MASK);
  irqMask = ~PSW_IRQ_MASK | (psw & PSW_IRQ_MASK);
  if (debugIRQ) {
  if (debugIRQ) {
    cPrintf("**** IRQ  = 0x%08X ****\n", irqPending);
    cPrintf("**** IRQ  = 0x%08X ****\n", irqPending);
    cPrintf("**** MASK = 0x%08X ****\n", irqMask);
    cPrintf("**** MASK = 0x%08X ****\n", irqMask);
  }
  }
  irqSeen = irqPending & irqMask;
  irqSeen = irqPending & irqMask;
  if (irqSeen == 0) {
  if (irqSeen == 0) {
    /* none that gets through */
    /* none that gets through */
    return;
    return;
  }
  }
  /* determine the one with the highest priority */
  /* determine the one with the highest priority */
  for (priority = 31; priority >= 0; priority--) {
  for (priority = 31; priority >= 0; priority--) {
    if ((irqSeen & ((unsigned) 1 << priority)) != 0) {
    if ((irqSeen & ((unsigned) 1 << priority)) != 0) {
      /* highest priority among visible ones found */
      /* highest priority among visible ones found */
      break;
      break;
    }
    }
  }
  }
  /* acknowledge exception, or interrupt if enabled */
  /* acknowledge exception, or interrupt if enabled */
  if (priority >= 16 || IE != 0) {
  if (priority >= 16 || IE != 0) {
    if (priority >= 16) {
    if (priority >= 16) {
      /* clear corresponding bit in irqPending vector */
      /* clear corresponding bit in irqPending vector */
      /* only done for exceptions, since interrupts are level-sensitive */
      /* only done for exceptions, since interrupts are level-sensitive */
      irqPending &= ~((unsigned) 1 << priority);
      irqPending &= ~((unsigned) 1 << priority);
    }
    }
    /* copy and reset interrupt enable bit in PSW */
    /* copy and reset interrupt enable bit in PSW */
    if (PIE != 0) {
    if (PIE != 0) {
      psw |= PSW_OIE;
      psw |= PSW_OIE;
    } else {
    } else {
      psw &= ~PSW_OIE;
      psw &= ~PSW_OIE;
    }
    }
    if (IE != 0) {
    if (IE != 0) {
      psw |= PSW_PIE;
      psw |= PSW_PIE;
    } else {
    } else {
      psw &= ~PSW_PIE;
      psw &= ~PSW_PIE;
    }
    }
    psw &= ~PSW_IE;
    psw &= ~PSW_IE;
    /* copy and reset user mode enable bit in PSW */
    /* copy and reset user mode enable bit in PSW */
    if (PUM != 0) {
    if (PUM != 0) {
      psw |= PSW_OUM;
      psw |= PSW_OUM;
    } else {
    } else {
      psw &= ~PSW_OUM;
      psw &= ~PSW_OUM;
    }
    }
    if (UM != 0) {
    if (UM != 0) {
      psw |= PSW_PUM;
      psw |= PSW_PUM;
    } else {
    } else {
      psw &= ~PSW_PUM;
      psw &= ~PSW_PUM;
    }
    }
    psw &= ~PSW_UM;
    psw &= ~PSW_UM;
    /* reflect priority in PSW */
    /* reflect priority in PSW */
    psw &= ~PSW_PRIO_MASK;
    psw &= ~PSW_PRIO_MASK;
    psw |= priority << PSW_PRIO_SHFT;
    psw |= priority << PSW_PRIO_SHFT;
    /* save interrupt return address and start service routine */
    /* save interrupt return address and start service routine */
    WR(30, pc);
    WR(30, pc);
    if (V == 0) {
    if (V == 0) {
      /* exceptions and interrupts are vectored to ROM */
      /* exceptions and interrupts are vectored to ROM */
      pc = 0xC0000000 | ROM_BASE;
      pc = 0xC0000000 | ROM_BASE;
    } else {
    } else {
      /* exceptions and interrupts are vectored to RAM */
      /* exceptions and interrupts are vectored to RAM */
      pc = 0xC0000000;
      pc = 0xC0000000;
    }
    }
    if (priority == EXC_TLB_MISS &&
    if (priority == EXC_TLB_MISS &&
        (mmuGetBadAddr() & 0x80000000) == 0) {
        (mmuGetBadAddr() & 0x80000000) == 0) {
      /* user TLB miss exception */
      /* user TLB miss exception */
      pc |= 0x00000008;
      pc |= 0x00000008;
    } else {
    } else {
      /* any other exception or interrupt */
      /* any other exception or interrupt */
      pc |= 0x00000004;
      pc |= 0x00000004;
    }
    }
  }
  }
}
}
 
 
 
 
static void execNextInstruction(void) {
static void execNextInstruction(void) {
  Word instr;
  Word instr;
  Word next;
  Word next;
  int op, reg1, reg2, reg3;
  int op, reg1, reg2, reg3;
  Half immed;
  Half immed;
  Word offset;
  Word offset;
  int scnt;
  int scnt;
  Word smsk;
  Word smsk;
  Word aux;
  Word aux;
 
 
  /* count the instruction */
  /* count the instruction */
  total++;
  total++;
  /* fetch the instruction */
  /* fetch the instruction */
  instr = mmuReadWord(pc, UM);
  instr = mmuReadWord(pc, UM);
  /* decode the instruction */
  /* decode the instruction */
  op = (instr >> 26) & 0x3F;
  op = (instr >> 26) & 0x3F;
  reg1 = (instr >> 21) & 0x1F;
  reg1 = (instr >> 21) & 0x1F;
  reg2 = (instr >> 16) & 0x1F;
  reg2 = (instr >> 16) & 0x1F;
  reg3 = (instr >> 11) & 0x1F;
  reg3 = (instr >> 11) & 0x1F;
  immed = instr & 0x0000FFFF;
  immed = instr & 0x0000FFFF;
  offset = instr & 0x03FFFFFF;
  offset = instr & 0x03FFFFFF;
  next = pc + 4;
  next = pc + 4;
  /* execute the instruction */
  /* execute the instruction */
  switch (op) {
  switch (op) {
    case OP_ADD:
    case OP_ADD:
      WR(reg3, (signed int) RR(reg1) + (signed int) RR(reg2));
      WR(reg3, (signed int) RR(reg1) + (signed int) RR(reg2));
      break;
      break;
    case OP_ADDI:
    case OP_ADDI:
      WR(reg2, (signed int) RR(reg1) + (signed int) SEXT16(immed));
      WR(reg2, (signed int) RR(reg1) + (signed int) SEXT16(immed));
      break;
      break;
    case OP_SUB:
    case OP_SUB:
      WR(reg3, (signed int) RR(reg1) - (signed int) RR(reg2));
      WR(reg3, (signed int) RR(reg1) - (signed int) RR(reg2));
      break;
      break;
    case OP_SUBI:
    case OP_SUBI:
      WR(reg2, (signed int) RR(reg1) - (signed int) SEXT16(immed));
      WR(reg2, (signed int) RR(reg1) - (signed int) SEXT16(immed));
      break;
      break;
    case OP_MUL:
    case OP_MUL:
      WR(reg3, (signed int) RR(reg1) * (signed int) RR(reg2));
      WR(reg3, (signed int) RR(reg1) * (signed int) RR(reg2));
      break;
      break;
    case OP_MULI:
    case OP_MULI:
      WR(reg2, (signed int) RR(reg1) * (signed int) SEXT16(immed));
      WR(reg2, (signed int) RR(reg1) * (signed int) SEXT16(immed));
      break;
      break;
    case OP_MULU:
    case OP_MULU:
      WR(reg3, RR(reg1) * RR(reg2));
      WR(reg3, RR(reg1) * RR(reg2));
      break;
      break;
    case OP_MULUI:
    case OP_MULUI:
      WR(reg2, RR(reg1) * ZEXT16(immed));
      WR(reg2, RR(reg1) * ZEXT16(immed));
      break;
      break;
    case OP_DIV:
    case OP_DIV:
      if (RR(reg2) == 0) {
      if (RR(reg2) == 0) {
        throwException(EXC_DIVIDE);
        throwException(EXC_DIVIDE);
      }
      }
      WR(reg3, (signed int) RR(reg1) / (signed int) RR(reg2));
      WR(reg3, (signed int) RR(reg1) / (signed int) RR(reg2));
      break;
      break;
    case OP_DIVI:
    case OP_DIVI:
      if (SEXT16(immed) == 0) {
      if (SEXT16(immed) == 0) {
        throwException(EXC_DIVIDE);
        throwException(EXC_DIVIDE);
      }
      }
      WR(reg2, (signed int) RR(reg1) / (signed int) SEXT16(immed));
      WR(reg2, (signed int) RR(reg1) / (signed int) SEXT16(immed));
      break;
      break;
    case OP_DIVU:
    case OP_DIVU:
      if (RR(reg2) == 0) {
      if (RR(reg2) == 0) {
        throwException(EXC_DIVIDE);
        throwException(EXC_DIVIDE);
      }
      }
      WR(reg3, RR(reg1) / RR(reg2));
      WR(reg3, RR(reg1) / RR(reg2));
      break;
      break;
    case OP_DIVUI:
    case OP_DIVUI:
      if (SEXT16(immed) == 0) {
      if (SEXT16(immed) == 0) {
        throwException(EXC_DIVIDE);
        throwException(EXC_DIVIDE);
      }
      }
      WR(reg2, RR(reg1) / ZEXT16(immed));
      WR(reg2, RR(reg1) / ZEXT16(immed));
      break;
      break;
    case OP_REM:
    case OP_REM:
      if (RR(reg2) == 0) {
      if (RR(reg2) == 0) {
        throwException(EXC_DIVIDE);
        throwException(EXC_DIVIDE);
      }
      }
      WR(reg3, (signed int) RR(reg1) % (signed int) RR(reg2));
      WR(reg3, (signed int) RR(reg1) % (signed int) RR(reg2));
      break;
      break;
    case OP_REMI:
    case OP_REMI:
      if (SEXT16(immed) == 0) {
      if (SEXT16(immed) == 0) {
        throwException(EXC_DIVIDE);
        throwException(EXC_DIVIDE);
      }
      }
      WR(reg2, (signed int) RR(reg1) % (signed int) SEXT16(immed));
      WR(reg2, (signed int) RR(reg1) % (signed int) SEXT16(immed));
      break;
      break;
    case OP_REMU:
    case OP_REMU:
      if (RR(reg2) == 0) {
      if (RR(reg2) == 0) {
        throwException(EXC_DIVIDE);
        throwException(EXC_DIVIDE);
      }
      }
      WR(reg3, RR(reg1) % RR(reg2));
      WR(reg3, RR(reg1) % RR(reg2));
      break;
      break;
    case OP_REMUI:
    case OP_REMUI:
      if (SEXT16(immed) == 0) {
      if (SEXT16(immed) == 0) {
        throwException(EXC_DIVIDE);
        throwException(EXC_DIVIDE);
      }
      }
      WR(reg2, RR(reg1) % ZEXT16(immed));
      WR(reg2, RR(reg1) % ZEXT16(immed));
      break;
      break;
    case OP_AND:
    case OP_AND:
      WR(reg3, RR(reg1) & RR(reg2));
      WR(reg3, RR(reg1) & RR(reg2));
      break;
      break;
    case OP_ANDI:
    case OP_ANDI:
      WR(reg2, RR(reg1) & ZEXT16(immed));
      WR(reg2, RR(reg1) & ZEXT16(immed));
      break;
      break;
    case OP_OR:
    case OP_OR:
      WR(reg3, RR(reg1) | RR(reg2));
      WR(reg3, RR(reg1) | RR(reg2));
      break;
      break;
    case OP_ORI:
    case OP_ORI:
      WR(reg2, RR(reg1) | ZEXT16(immed));
      WR(reg2, RR(reg1) | ZEXT16(immed));
      break;
      break;
    case OP_XOR:
    case OP_XOR:
      WR(reg3, RR(reg1) ^ RR(reg2));
      WR(reg3, RR(reg1) ^ RR(reg2));
      break;
      break;
    case OP_XORI:
    case OP_XORI:
      WR(reg2, RR(reg1) ^ ZEXT16(immed));
      WR(reg2, RR(reg1) ^ ZEXT16(immed));
      break;
      break;
    case OP_XNOR:
    case OP_XNOR:
      WR(reg3, ~(RR(reg1) ^ RR(reg2)));
      WR(reg3, ~(RR(reg1) ^ RR(reg2)));
      break;
      break;
    case OP_XNORI:
    case OP_XNORI:
      WR(reg2, ~(RR(reg1) ^ ZEXT16(immed)));
      WR(reg2, ~(RR(reg1) ^ ZEXT16(immed)));
      break;
      break;
    case OP_SLL:
    case OP_SLL:
      scnt = RR(reg2) & 0x1F;
      scnt = RR(reg2) & 0x1F;
      WR(reg3, RR(reg1) << scnt);
      WR(reg3, RR(reg1) << scnt);
      break;
      break;
    case OP_SLLI:
    case OP_SLLI:
      scnt = immed & 0x1F;
      scnt = immed & 0x1F;
      WR(reg2, RR(reg1) << scnt);
      WR(reg2, RR(reg1) << scnt);
      break;
      break;
    case OP_SLR:
    case OP_SLR:
      scnt = RR(reg2) & 0x1F;
      scnt = RR(reg2) & 0x1F;
      WR(reg3, RR(reg1) >> scnt);
      WR(reg3, RR(reg1) >> scnt);
      break;
      break;
    case OP_SLRI:
    case OP_SLRI:
      scnt = immed & 0x1F;
      scnt = immed & 0x1F;
      WR(reg2, RR(reg1) >> scnt);
      WR(reg2, RR(reg1) >> scnt);
      break;
      break;
    case OP_SAR:
    case OP_SAR:
      scnt = RR(reg2) & 0x1F;
      scnt = RR(reg2) & 0x1F;
      smsk = (RR(reg1) & 0x80000000 ? ~(((Word) 0xFFFFFFFF) >> scnt) : 0);
      smsk = (RR(reg1) & 0x80000000 ? ~(((Word) 0xFFFFFFFF) >> scnt) : 0);
      WR(reg3, smsk | (RR(reg1) >> scnt));
      WR(reg3, smsk | (RR(reg1) >> scnt));
      break;
      break;
    case OP_SARI:
    case OP_SARI:
      scnt = immed & 0x1F;
      scnt = immed & 0x1F;
      smsk = (RR(reg1) & 0x80000000 ? ~(((Word) 0xFFFFFFFF) >> scnt) : 0);
      smsk = (RR(reg1) & 0x80000000 ? ~(((Word) 0xFFFFFFFF) >> scnt) : 0);
      WR(reg2, smsk | (RR(reg1) >> scnt));
      WR(reg2, smsk | (RR(reg1) >> scnt));
      break;
      break;
    case OP_LDHI:
    case OP_LDHI:
      WR(reg2, ZEXT16(immed) << 16);
      WR(reg2, ZEXT16(immed) << 16);
      break;
      break;
    case OP_BEQ:
    case OP_BEQ:
      if (RR(reg1) == RR(reg2)) {
      if (RR(reg1) == RR(reg2)) {
        next += SEXT16(immed) << 2;
        next += SEXT16(immed) << 2;
      }
      }
      break;
      break;
    case OP_BNE:
    case OP_BNE:
      if (RR(reg1) != RR(reg2)) {
      if (RR(reg1) != RR(reg2)) {
        next += SEXT16(immed) << 2;
        next += SEXT16(immed) << 2;
      }
      }
      break;
      break;
    case OP_BLE:
    case OP_BLE:
      if ((signed int) RR(reg1) <= (signed int) RR(reg2)) {
      if ((signed int) RR(reg1) <= (signed int) RR(reg2)) {
        next += SEXT16(immed) << 2;
        next += SEXT16(immed) << 2;
      }
      }
      break;
      break;
    case OP_BLEU:
    case OP_BLEU:
      if (RR(reg1) <= RR(reg2)) {
      if (RR(reg1) <= RR(reg2)) {
        next += SEXT16(immed) << 2;
        next += SEXT16(immed) << 2;
      }
      }
      break;
      break;
    case OP_BLT:
    case OP_BLT:
      if ((signed int) RR(reg1) < (signed int) RR(reg2)) {
      if ((signed int) RR(reg1) < (signed int) RR(reg2)) {
        next += SEXT16(immed) << 2;
        next += SEXT16(immed) << 2;
      }
      }
      break;
      break;
    case OP_BLTU:
    case OP_BLTU:
      if (RR(reg1) < RR(reg2)) {
      if (RR(reg1) < RR(reg2)) {
        next += SEXT16(immed) << 2;
        next += SEXT16(immed) << 2;
      }
      }
      break;
      break;
    case OP_BGE:
    case OP_BGE:
      if ((signed int) RR(reg1) >= (signed int) RR(reg2)) {
      if ((signed int) RR(reg1) >= (signed int) RR(reg2)) {
        next += SEXT16(immed) << 2;
        next += SEXT16(immed) << 2;
      }
      }
      break;
      break;
    case OP_BGEU:
    case OP_BGEU:
      if (RR(reg1) >= RR(reg2)) {
      if (RR(reg1) >= RR(reg2)) {
        next += SEXT16(immed) << 2;
        next += SEXT16(immed) << 2;
      }
      }
      break;
      break;
    case OP_BGT:
    case OP_BGT:
      if ((signed int) RR(reg1) > (signed int) RR(reg2)) {
      if ((signed int) RR(reg1) > (signed int) RR(reg2)) {
        next += SEXT16(immed) << 2;
        next += SEXT16(immed) << 2;
      }
      }
      break;
      break;
    case OP_BGTU:
    case OP_BGTU:
      if (RR(reg1) > RR(reg2)) {
      if (RR(reg1) > RR(reg2)) {
        next += SEXT16(immed) << 2;
        next += SEXT16(immed) << 2;
      }
      }
      break;
      break;
    case OP_J:
    case OP_J:
      next += SEXT26(offset) << 2;
      next += SEXT26(offset) << 2;
      break;
      break;
    case OP_JR:
    case OP_JR:
      next = RR(reg1);
      next = RR(reg1);
      break;
      break;
    case OP_JAL:
    case OP_JAL:
      WR(31, next);
      WR(31, next);
      next += SEXT26(offset) << 2;
      next += SEXT26(offset) << 2;
      break;
      break;
    case OP_JALR:
    case OP_JALR:
      aux = RR(reg1);
      aux = RR(reg1);
      WR(31, next);
      WR(31, next);
      next = aux;
      next = aux;
      break;
      break;
    case OP_TRAP:
    case OP_TRAP:
      throwException(EXC_TRAP);
      throwException(EXC_TRAP);
      break;
      break;
    case OP_RFX:
    case OP_RFX:
      if (UM != 0) {
      if (UM != 0) {
        throwException(EXC_PRV_INSTRCT);
        throwException(EXC_PRV_INSTRCT);
      }
      }
      if (PIE != 0) {
      if (PIE != 0) {
        psw |= PSW_IE;
        psw |= PSW_IE;
      } else {
      } else {
        psw &= ~PSW_IE;
        psw &= ~PSW_IE;
      }
      }
      if (OIE != 0) {
      if (OIE != 0) {
        psw |= PSW_PIE;
        psw |= PSW_PIE;
      } else {
      } else {
        psw &= ~PSW_PIE;
        psw &= ~PSW_PIE;
      }
      }
      if (PUM != 0) {
      if (PUM != 0) {
        psw |= PSW_UM;
        psw |= PSW_UM;
      } else {
      } else {
        psw &= ~PSW_UM;
        psw &= ~PSW_UM;
      }
      }
      if (OUM != 0) {
      if (OUM != 0) {
        psw |= PSW_PUM;
        psw |= PSW_PUM;
      } else {
      } else {
        psw &= ~PSW_PUM;
        psw &= ~PSW_PUM;
      }
      }
      next = RR(30);
      next = RR(30);
      break;
      break;
    case OP_LDW:
    case OP_LDW:
      WR(reg2, mmuReadWord(RR(reg1) + SEXT16(immed), UM));
      WR(reg2, mmuReadWord(RR(reg1) + SEXT16(immed), UM));
      break;
      break;
    case OP_LDH:
    case OP_LDH:
      WR(reg2, (signed int) (signed short)
      WR(reg2, (signed int) (signed short)
               mmuReadHalf(RR(reg1) + SEXT16(immed), UM));
               mmuReadHalf(RR(reg1) + SEXT16(immed), UM));
      break;
      break;
    case OP_LDHU:
    case OP_LDHU:
      WR(reg2, mmuReadHalf(RR(reg1) + SEXT16(immed), UM));
      WR(reg2, mmuReadHalf(RR(reg1) + SEXT16(immed), UM));
      break;
      break;
    case OP_LDB:
    case OP_LDB:
      WR(reg2, (signed int) (signed char)
      WR(reg2, (signed int) (signed char)
               mmuReadByte(RR(reg1) + SEXT16(immed), UM));
               mmuReadByte(RR(reg1) + SEXT16(immed), UM));
      break;
      break;
    case OP_LDBU:
    case OP_LDBU:
      WR(reg2, mmuReadByte(RR(reg1) + SEXT16(immed), UM));
      WR(reg2, mmuReadByte(RR(reg1) + SEXT16(immed), UM));
      break;
      break;
    case OP_STW:
    case OP_STW:
      mmuWriteWord(RR(reg1) + SEXT16(immed), RR(reg2), UM);
      mmuWriteWord(RR(reg1) + SEXT16(immed), RR(reg2), UM);
      break;
      break;
    case OP_STH:
    case OP_STH:
      mmuWriteHalf(RR(reg1) + SEXT16(immed), RR(reg2), UM);
      mmuWriteHalf(RR(reg1) + SEXT16(immed), RR(reg2), UM);
      break;
      break;
    case OP_STB:
    case OP_STB:
      mmuWriteByte(RR(reg1) + SEXT16(immed), RR(reg2), UM);
      mmuWriteByte(RR(reg1) + SEXT16(immed), RR(reg2), UM);
      break;
      break;
    case OP_MVFS:
    case OP_MVFS:
      switch (immed) {
      switch (immed) {
        case 0:
        case 0:
          WR(reg2, psw);
          WR(reg2, psw);
          break;
          break;
        case 1:
        case 1:
          WR(reg2, mmuGetIndex());
          WR(reg2, mmuGetIndex());
          break;
          break;
        case 2:
        case 2:
          WR(reg2, mmuGetEntryHi());
          WR(reg2, mmuGetEntryHi());
          break;
          break;
        case 3:
        case 3:
          WR(reg2, mmuGetEntryLo());
          WR(reg2, mmuGetEntryLo());
          break;
          break;
        case 4:
        case 4:
          WR(reg2, mmuGetBadAddr());
          WR(reg2, mmuGetBadAddr());
          break;
          break;
 
        case 5:
 
          WR(reg2, mmuGetBadAccs());
 
          break;
        default:
        default:
          throwException(EXC_ILL_INSTRCT);
          throwException(EXC_ILL_INSTRCT);
          break;
          break;
      }
      }
      break;
      break;
    case OP_MVTS:
    case OP_MVTS:
      if (UM != 0) {
      if (UM != 0) {
        throwException(EXC_PRV_INSTRCT);
        throwException(EXC_PRV_INSTRCT);
      }
      }
      switch (immed) {
      switch (immed) {
        case 0:
        case 0:
          psw = RR(reg2);
          psw = RR(reg2);
          break;
          break;
        case 1:
        case 1:
          mmuSetIndex(RR(reg2));
          mmuSetIndex(RR(reg2));
          break;
          break;
        case 2:
        case 2:
          mmuSetEntryHi(RR(reg2));
          mmuSetEntryHi(RR(reg2));
          break;
          break;
        case 3:
        case 3:
          mmuSetEntryLo(RR(reg2));
          mmuSetEntryLo(RR(reg2));
          break;
          break;
        case 4:
        case 4:
          mmuSetBadAddr(RR(reg2));
          mmuSetBadAddr(RR(reg2));
          break;
          break;
 
        case 5:
 
          mmuSetBadAccs(RR(reg2));
 
          break;
        default:
        default:
          throwException(EXC_ILL_INSTRCT);
          throwException(EXC_ILL_INSTRCT);
          break;
          break;
      }
      }
      break;
      break;
    case OP_TBS:
    case OP_TBS:
      if (UM != 0) {
      if (UM != 0) {
        throwException(EXC_PRV_INSTRCT);
        throwException(EXC_PRV_INSTRCT);
      }
      }
      mmuTbs();
      mmuTbs();
      break;
      break;
    case OP_TBWR:
    case OP_TBWR:
      if (UM != 0) {
      if (UM != 0) {
        throwException(EXC_PRV_INSTRCT);
        throwException(EXC_PRV_INSTRCT);
      }
      }
      mmuTbwr();
      mmuTbwr();
      break;
      break;
    case OP_TBRI:
    case OP_TBRI:
      if (UM != 0) {
      if (UM != 0) {
        throwException(EXC_PRV_INSTRCT);
        throwException(EXC_PRV_INSTRCT);
      }
      }
      mmuTbri();
      mmuTbri();
      break;
      break;
    case OP_TBWI:
    case OP_TBWI:
      if (UM != 0) {
      if (UM != 0) {
        throwException(EXC_PRV_INSTRCT);
        throwException(EXC_PRV_INSTRCT);
      }
      }
      mmuTbwi();
      mmuTbwi();
      break;
      break;
    default:
    default:
      throwException(EXC_ILL_INSTRCT);
      throwException(EXC_ILL_INSTRCT);
      break;
      break;
  }
  }
  /* update PC */
  /* update PC */
  pc = next;
  pc = next;
}
}
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
Word cpuGetPC(void) {
Word cpuGetPC(void) {
  return pc;
  return pc;
}
}
 
 
 
 
void cpuSetPC(Word addr) {
void cpuSetPC(Word addr) {
  pc = addr;
  pc = addr;
}
}
 
 
 
 
Word cpuGetReg(int regnum) {
Word cpuGetReg(int regnum) {
  return RR(regnum & 0x1F);
  return RR(regnum & 0x1F);
}
}
 
 
 
 
void cpuSetReg(int regnum, Word value) {
void cpuSetReg(int regnum, Word value) {
  WR(regnum & 0x1F, value);
  WR(regnum & 0x1F, value);
}
}
 
 
 
 
Word cpuGetPSW(void) {
Word cpuGetPSW(void) {
  return psw;
  return psw;
}
}
 
 
 
 
void cpuSetPSW(Word value) {
void cpuSetPSW(Word value) {
  psw = value;
  psw = value;
}
}
 
 
 
 
Word cpuGetIRQ(void) {
Word cpuGetIRQ(void) {
  return irqPending;
  return irqPending;
}
}
 
 
 
 
Bool cpuTestBreak(void) {
Bool cpuTestBreak(void) {
  return breakSet;
  return breakSet;
}
}
 
 
 
 
Word cpuGetBreak(void) {
Word cpuGetBreak(void) {
  return breakAddr;
  return breakAddr;
}
}
 
 
 
 
void cpuSetBreak(Word addr) {
void cpuSetBreak(Word addr) {
  breakAddr = addr;
  breakAddr = addr;
  breakSet = true;
  breakSet = true;
}
}
 
 
 
 
void cpuResetBreak(void) {
void cpuResetBreak(void) {
  breakSet = false;
  breakSet = false;
}
}
 
 
 
 
Word cpuGetTotal(void) {
Word cpuGetTotal(void) {
  return total;
  return total;
}
}
 
 
 
 
void cpuStep(void) {
void cpuStep(void) {
  jmp_buf myEnvironment;
  jmp_buf myEnvironment;
  int exception;
  int exception;
 
 
  exception = setjmp(myEnvironment);
  exception = setjmp(myEnvironment);
  if (exception == 0) {
  if (exception == 0) {
    /* initialization */
    /* initialization */
    pushEnvironment(&myEnvironment);
    pushEnvironment(&myEnvironment);
    timerTick();
    timerTick();
    execNextInstruction();
    execNextInstruction();
    handleInterrupts();
    handleInterrupts();
  } else {
  } else {
    /* an exception was thrown */
    /* an exception was thrown */
    cpuSetInterrupt(exception);
    cpuSetInterrupt(exception);
    handleInterrupts();
    handleInterrupts();
  }
  }
  popEnvironment();
  popEnvironment();
}
}
 
 
 
 
void cpuRun(void) {
void cpuRun(void) {
  jmp_buf myEnvironment;
  jmp_buf myEnvironment;
  int exception;
  int exception;
 
 
  run = true;
  run = true;
  exception = setjmp(myEnvironment);
  exception = setjmp(myEnvironment);
  if (exception == 0) {
  if (exception == 0) {
    /* initialization */
    /* initialization */
    pushEnvironment(&myEnvironment);
    pushEnvironment(&myEnvironment);
  } else {
  } else {
    /* an exception was thrown */
    /* an exception was thrown */
    cpuSetInterrupt(exception);
    cpuSetInterrupt(exception);
    handleInterrupts();
    handleInterrupts();
    if (breakSet && pc == breakAddr) {
    if (breakSet && pc == breakAddr) {
      run = false;
      run = false;
    }
    }
  }
  }
  while (run) {
  while (run) {
    timerTick();
    timerTick();
    execNextInstruction();
    execNextInstruction();
    handleInterrupts();
    handleInterrupts();
    if (breakSet && pc == breakAddr) {
    if (breakSet && pc == breakAddr) {
      run = false;
      run = false;
    }
    }
  }
  }
  popEnvironment();
  popEnvironment();
}
}
 
 
 
 
void cpuHalt(void) {
void cpuHalt(void) {
  run = false;
  run = false;
}
}
 
 
 
 
void cpuSetInterrupt(int priority) {
void cpuSetInterrupt(int priority) {
  irqPending |= ((unsigned) 1 << priority);
  irqPending |= ((unsigned) 1 << priority);
}
}
 
 
 
 
void cpuResetInterrupt(int priority) {
void cpuResetInterrupt(int priority) {
  irqPending &= ~((unsigned) 1 << priority);
  irqPending &= ~((unsigned) 1 << priority);
}
}
 
 
 
 
void cpuReset(void) {
void cpuReset(void) {
  int i;
  int i;
 
 
  cPrintf("Resetting CPU...\n");
  cPrintf("Resetting CPU...\n");
  /* most registers are in a random state */
  /* most registers are in a random state */
  for (i = 1; i < 32; i++) {
  for (i = 1; i < 32; i++) {
    r[i] = rand();
    r[i] = rand();
  }
  }
  /* but not all */
  /* but not all */
  pc = startAddr;
  pc = startAddr;
  r[0] = 0;
  r[0] = 0;
  psw = 0;
  psw = 0;
  /* reset simulator control variables */
  /* reset simulator control variables */
  irqPending = 0;
  irqPending = 0;
  total = 0;
  total = 0;
}
}
 
 
 
 
void cpuInit(Word initialPC) {
void cpuInit(Word initialPC) {
  startAddr = initialPC;
  startAddr = initialPC;
  cpuReset();
  cpuReset();
}
}
 
 
 
 
void cpuExit(void) {
void cpuExit(void) {
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.