mirror of
https://github.com/DoctorWkt/unix-jun72.git
synced 2026-02-02 06:51:49 +00:00
210 lines
6.6 KiB
C
210 lines
6.6 KiB
C
/* cpu.c - this holds the main loop for the emulator, plus generic
|
|
* functions to deal with exceptional instructions and events
|
|
*
|
|
* $Revision: 1.25 $
|
|
* $Date: 2002/06/10 11:41:40 $
|
|
*/
|
|
#include "defines.h"
|
|
#include <unistd.h>
|
|
|
|
u_int8_t *ispace, *dspace; /* Instruction and Data spaces */
|
|
u_int16_t dwrite_base=2; /* Lowest addr where dspace writes can occur */
|
|
|
|
u_int16_t regs[8]; /* general registers */
|
|
u_int16_t ir; /* current instruction register */
|
|
u_int16_t *adptr; /* used in memory access macros */
|
|
u_int16_t ea_addr; /* stored address for dest modifying insts */
|
|
|
|
int CC_N=0; /* The processor status word is represented */
|
|
int CC_Z=0; /* by these four values. On some */
|
|
int CC_V=0; /* architectures, you may get a performance */
|
|
int CC_C=0; /* increase by using shorts or bytes */
|
|
|
|
u_int16_t dstword; /* These globals are used in the effective */
|
|
u_int16_t srcword; /* address calculations, mainly to save */
|
|
u_int16_t tmpword; /* parameter passing overheads in */
|
|
u_int8_t dstbyte; /* function calls */
|
|
u_int8_t srcbyte;
|
|
u_int8_t tmpbyte;
|
|
struct our_siglist *Sighead=NULL; /* List of pending signals */
|
|
struct our_siglist *Sigtail=NULL; /* List of pending signals */
|
|
void (*sigrunner)(void)= NULL; /* F'n that will run the signal */
|
|
|
|
#ifdef DEBUG
|
|
extern char *iname[1024];
|
|
extern char *iname0[64]; /* Name of each instruction */
|
|
extern char *iname1[64];
|
|
char *name;
|
|
#endif
|
|
|
|
|
|
/* Run until told to stop. */
|
|
void run() {
|
|
#ifdef DEBUG
|
|
int i;
|
|
|
|
if (trap_debug) {
|
|
TrapDebug((dbg_file, "Just starting to run pid %d\n",(int)getpid()));
|
|
TrapDebug((dbg_file, "Regs are "));
|
|
for (i=0;i<=PC;i++) TrapDebug((dbg_file, "%06o ",regs[i]));
|
|
TrapDebug((dbg_file, "\n"));
|
|
}
|
|
#endif
|
|
|
|
while (1) {
|
|
|
|
/* Fetch and execute the instruction. */
|
|
|
|
#ifdef DEBUG
|
|
lli_word(regs[PC], ir);
|
|
if (inst_debug) {
|
|
i= ir >> 6;
|
|
switch (i) {
|
|
case 0: name= iname0[ir & 077]; break;
|
|
case 2: name= iname1[ir & 077]; break;
|
|
default: name= iname[i];
|
|
}
|
|
TrapDebug((dbg_file, "%06o %06o %4s ", regs[7], ir, name));
|
|
TrapDebug((dbg_file, "%06o %06o %06o %06o %06o %06o %06o ",
|
|
regs[0], regs[1], regs[2], regs[3],
|
|
regs[4], regs[5], regs[6]));
|
|
TrapDebug((dbg_file, "NZVC1 %d%d%d%d\n",CC_N,CC_Z,CC_V,CC_C));
|
|
}
|
|
regs[PC] += 2; itab[ir >> 6] ();
|
|
if ((Sighead!=NULL) && (sigrunner!=NULL)) (void) (*sigrunner)();
|
|
#else
|
|
/* When not debugging, we can manually unroll this inner loop */
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
lli_word(regs[PC], ir); regs[PC] += 2; itab[ir >> 6] ();
|
|
if ((Sighead!=NULL) && (sigrunner!=NULL)) (void) (*sigrunner)();
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* sim_init() - Initialize the cpu registers. */
|
|
void sim_init() {
|
|
int x;
|
|
|
|
for (x = 0; x < 8; ++x) { regs[x] = 0; }
|
|
ir = 0; CLR_CC_ALL();
|
|
}
|
|
|
|
void bus_error(int signo)
|
|
{
|
|
TrapDebug((dbg_file, "Apout - pid %d bus error at PC 0%06o\n",
|
|
(int)getpid(), regs[PC]));
|
|
TrapDebug((dbg_file, "%06o ", ir));
|
|
TrapDebug((dbg_file, "%o %o %o %o %o %o %o %o ",
|
|
regs[0], regs[1], regs[2], regs[3],
|
|
regs[4], regs[5], regs[6], regs[7]));
|
|
TrapDebug((dbg_file, "NZVC2 are %d%d%d%d\n",CC_N,CC_Z,CC_V,CC_C));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
void seg_fault() {
|
|
TrapDebug((dbg_file, "Apout - pid %d segmentation fault at PC 0%06o\n",
|
|
(int)getpid(), regs[PC]));
|
|
TrapDebug((dbg_file, "%06o ", ir));
|
|
TrapDebug((dbg_file, "%o %o %o %o %o %o %o %o ",
|
|
regs[0], regs[1], regs[2], regs[3],
|
|
regs[4], regs[5], regs[6], regs[7]));
|
|
TrapDebug((dbg_file, "NZVC3 are %d%d%d%d\n",CC_N,CC_Z,CC_V,CC_C));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
void waiti() {
|
|
TrapDebug((stderr, "Apout - pid %d waiti instruction at PC 0%o\n",
|
|
(int)getpid(), regs[PC]));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
void halt() {
|
|
TrapDebug((stderr, "Apout - pid %d halt instruction at PC 0%o\n",
|
|
(int)getpid(), regs[PC]));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
void iot() {
|
|
TrapDebug((stderr, "Apout - pid %d iot instruction at PC 0%o\n",
|
|
(int)getpid(), regs[PC]));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
void emt() {
|
|
TrapDebug((stderr, "Apout - pid %d emt instruction at PC 0%o\n",
|
|
(int)getpid(), regs[PC]));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
void bpt() {
|
|
TrapDebug((stderr, "Apout - pid %d bpt instruction at PC 0%o\n",
|
|
(int)getpid(), regs[PC]));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
void illegal() {
|
|
TrapDebug((stderr, "Apout - pid %d illegal instruction %o at PC 0%o\n",
|
|
(int)getpid(),ir, regs[PC]));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
void not_impl() {
|
|
TrapDebug((stderr, "Apout - pid %d unimplemented instruction at PC 0%o\n",
|
|
(int)getpid(), regs[PC]));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
void mark() {
|
|
TrapDebug((stderr, "Apout - pid %d mark instruction at PC 0%o\n",
|
|
(int)getpid(), regs[PC]));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
void mfpd() {
|
|
TrapDebug((stderr, "Apout - pid %d mfpd instruction at PC 0%o\n",
|
|
(int)getpid(), regs[PC]));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
void mtpd() {
|
|
TrapDebug((stderr, "Apout - pid %d mtpd instruction at PC 0%o\n",
|
|
(int)getpid(), regs[PC]));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
void trap() {
|
|
TrapDebug((stderr, "Apout - pid %d trap instruction at PC 0%o\n",
|
|
(int)getpid(), regs[PC]));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
void bad_FP_reg() {
|
|
TrapDebug((stderr, "Apout - pid %d bad FP register used at PC 0%o\n",
|
|
(int)getpid(), regs[PC]));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* This is the generic function which catches
|
|
* a signal, and appends it to the queue.
|
|
*/
|
|
void sigcatcher(int sig)
|
|
{
|
|
struct our_siglist *this;
|
|
|
|
this= (struct our_siglist *)malloc(sizeof(struct our_siglist));
|
|
if (this==NULL) return;
|
|
|
|
TrapDebug((dbg_file, "Caught signal %d\n",sig));
|
|
|
|
this->sig=sig; this->next=NULL;
|
|
if (Sighead==NULL) { Sighead=Sigtail=this; }
|
|
else { Sigtail->next= this; Sigtail=this; }
|
|
}
|