1
0
mirror of https://github.com/prirun/p50em.git synced 2026-03-09 03:49:25 +00:00

large changes to dispatch.h to support 2 tables +

separate R/S-mode mem ref dispatch table to avoid R-mode check in V-mode inst
This commit is contained in:
Jim
2007-10-04 00:00:00 -04:00
parent c845fdce12
commit c463fce90d
2 changed files with 413 additions and 262 deletions

View File

@@ -1,13 +1,14 @@
/* include file to initialize the CPU dispatch tables */
/* macro MRGEN takes as a Prime opcode number and sets up the disp_mr
dispatch table. The Prime opcode number for 4-bit opcode (in
instruction bits 3-6) 1101 is 015, and Prime writes it as 01500 in
older manuals. If the X bit is used as an opcode extension (only
for opcode 01500 - non-indexable instructions), the opcode becomes
03500. If bits 7-11 are 11000 (for V-mode; bits 7-12 = 110000 in
R-mode), the instruction is long form and has 2 extended opcode
bits in bits 13-14. The Prime equivalent would be 03500 - 03503.
/* macros MRGEN_(VR) take as a Prime opcode number and set up the
disp_(vr)mr V and R-mode dispatch tables. The Prime opcode number
for 4-bit opcode (in instruction bits 3-6) 1101 is 015, and Prime
writes it as 01500 in older manuals. If the X bit is used as an
opcode extension (only for opcode 01500 - non-indexable
instructions), the opcode becomes 03500. If bits 7-11 are 11000
(for V-mode; bits 7-12 = 110000 in R-mode), the instruction is long
form and has 2 extended opcode bits in bits 13-14. The Prime
equivalent would be 03500 - 03503.
To summarize, the mem ref opcode index is a 7-bit value, 0-127:
- bit 10 = bit 2 of instruction (X)
@@ -23,8 +24,8 @@
#define VMRINSTIX(inst) ((((inst) >> 8) & 0x7C) | ((((inst) & 0x03E0) == 0x0300) ? (((inst) >> 2) & 3) : 0))
/* change R-mode MR instruction to opcode index (mask is 1 bit longer
for R-mode long instructions */
/* change R-mode MR instruction to opcode index
(mask is 1 bit longer for R-mode long instructions) */
#define RMRINSTIX(inst) ((((inst) >> 8) & 0x7C) | ((((inst) & 0x03F0) == 0x0300) ? (((inst) >> 2) & 3) : 0))
@@ -36,76 +37,203 @@
#define MRPRIMEIX(primeop) (((primeop) >> 4) | ((primeop) & 3))
#define MRGEN(opcode, name, target) \
gvp->disp_mr[MRPRIMEIX(opcode)] = &⌖ \
/* printf("MR opcode %05o (%s), ix=%0d\n", opcode, name, MRPRIMEIX(opcode)); */ \
/* set an entry in the R-mode memory reference opcode dispatch table */
#define MRGEN_R(opcode, name, target) \
gvp->disp_rmr[MRPRIMEIX(opcode)] = &⌖ \
/* printf("R-MR opcode %05o (%s), ix=%0d\n", opcode, name, MRPRIMEIX(opcode)); */ \
if ((opcode & 01700) != 01500) { \
gvp->disp_mr[MRPRIMEIX(opcode | 02000)] = &⌖ \
/* printf("MR opcode %05o (%s), ix=%0d\n", opcode | 02000, name, MRPRIMEIX(opcode | 02000)); */ \
gvp->disp_rmr[MRPRIMEIX(opcode | 02000)] = &⌖ \
/* printf("R-MR opcode %05o (%s), ix=%0d\n", opcode | 02000, name, MRPRIMEIX(opcode | 02000)); */ \
}
/* initialize table to "bad memory reference instruction" */
/* set an entry in the V-mode memory reference opcode dispatch table */
for (i=0; i < 128; i++)
gvp->disp_mr[i] = &&d_badmr;
#define MRGEN_V(opcode, name, target) \
gvp->disp_vmr[MRPRIMEIX(opcode)] = &&target; \
/* printf("V-MR opcode %05o (%s), ix=%0d\n", opcode, name, MRPRIMEIX(opcode)); */ \
if ((opcode & 01700) != 01500) { \
gvp->disp_vmr[MRPRIMEIX(opcode | 02000)] = &&target; \
/* printf("V-MR opcode %05o (%s), ix=%0d\n", opcode | 02000, name, MRPRIMEIX(opcode | 02000)); */ \
}
MRGEN(00100, "JMP", d_jmp);
MRGEN(00101, "EAL", d_ealeaa);
MRGEN(00102, "XEC", d_xec);
MRGEN(00103, "ENTR", d_entr);
MRGEN(00200, "LDA", d_ldadld);
MRGEN(00201, "FLD", d_fld);
MRGEN(00202, "DFLD", d_dfld);
MRGEN(00203, "LDL", d_ldljeq);
MRGEN(00300, "ANA", d_ana);
MRGEN(00301, "STLR", d_stlr);
MRGEN(00302, "ORA", d_ora);
MRGEN(00303, "ANL", d_anljne);
MRGEN(00400, "STA", d_stadst);
MRGEN(00401, "FST", d_fst);
MRGEN(00402, "DFST", d_dfst);
MRGEN(00403, "STL", d_stljle);
MRGEN(00500, "ERA", d_era);
MRGEN(00501, "LDLR", d_ldlr);
MRGEN(00502, "QFxx", d_qfxxuii);
MRGEN(00503, "ERL", d_erljgt);
MRGEN(00600, "ADD", d_adddad);
MRGEN(00601, "FAD", d_fad);
MRGEN(00602, "DFAD", d_dfad);
MRGEN(00603, "ADL", d_adljlt);
MRGEN(00700, "SUB", d_subdsb);
MRGEN(00701, "FSB", d_fsb);
MRGEN(00702, "DFSB", d_dfsb);
MRGEN(00703, "SBL", d_sbljge);
MRGEN(01000, "JST", d_jst);
MRGEN(01002, "PCL", d_pclcrep);
MRGEN(01100, "CAS", d_cas);
MRGEN(01101, "FCS", d_fcs);
MRGEN(01102, "DFCS", d_dfcs);
MRGEN(01103, "CLS", d_cls);
MRGEN(01200, "IRS", d_irs);
MRGEN(01202, "EAXB", d_eaxb);
MRGEN(01300, "IMA", d_ima);
MRGEN(01302, "EALB", d_ealb);
MRGEN(01400, "JSY", d_jsy);
MRGEN(01401, "EIO", d_eio);
MRGEN(01402, "JSXB", d_jsxb);
MRGEN(01500, "STX", d_stx);
MRGEN(01501, "FLX", d_flx);
MRGEN(01502, "DFLX", d_dflxjdx);
MRGEN(01503, "QFLX", d_qflxjix);
MRGEN(01600, "MPY", d_mpy);
MRGEN(01601, "FMP", d_fmp);
MRGEN(01602, "DFMP", d_dfmp);
MRGEN(01603, "MPL", d_mpl);
MRGEN(01700, "DIV", d_div);
MRGEN(01701, "FDV", d_fdv);
MRGEN(01702, "DFDV", d_dfdv);
MRGEN(01703, "DVL", d_dvl);
MRGEN(03500, "LDX", d_ldx);
MRGEN(03501, "LDY", d_ldy);
MRGEN(03502, "STY", d_sty);
MRGEN(03503, "JSX", d_jsx);
/* initialize tables to "bad memory reference instruction" */
for (i=0; i < 128; i++) {
gvp->disp_rmr[i] = &&d_badmr;
gvp->disp_vmr[i] = &&d_badmr;
}
MRGEN_R(00100, "JMP", d_jmp);
MRGEN_V(00100, "JMP", d_jmp);
MRGEN_R(00101, "EAA", d_eaa);
MRGEN_V(00101, "EAL", d_eal);
MRGEN_R(00102, "XEC", d_xec);
MRGEN_V(00102, "XEC", d_xec);
MRGEN_R(00103, "ENTR", d_entr);
MRGEN_V(00103, "ENTR?", d_uii);
MRGEN_R(00200, "LDA/DLD", d_ldadld);
MRGEN_V(00200, "LDA", d_lda);
MRGEN_R(00201, "FLD", d_fld);
MRGEN_V(00201, "FLD", d_fld);
MRGEN_R(00202, "DFLD", d_dfld);
MRGEN_V(00202, "DFLD", d_dfld);
MRGEN_R(00203, "JEQ", d_jeq);
MRGEN_V(00203, "LDL", d_ldl);
MRGEN_R(00300, "ANA", d_ana);
MRGEN_V(00300, "ANA", d_ana);
MRGEN_R(00301, "STLR?", d_uii);
MRGEN_V(00301, "STLR", d_stlr);
MRGEN_R(00302, "ORA", d_ora);
MRGEN_V(00302, "ORA", d_ora);
MRGEN_R(00303, "JNE", d_jne);
MRGEN_V(00303, "ANL", d_anl);
MRGEN_R(00400, "STA/DST", d_stadst);
MRGEN_V(00400, "STA", d_sta);
MRGEN_R(00401, "FST", d_fst);
MRGEN_V(00401, "FST", d_fst);
MRGEN_R(00402, "DFST", d_dfst);
MRGEN_V(00402, "DFST", d_dfst);
MRGEN_R(00403, "JLE", d_jle);
MRGEN_V(00403, "STL", d_stl);
MRGEN_R(00500, "ERA", d_era);
MRGEN_V(00500, "ERA", d_era);
MRGEN_R(00501, "LDLR?", d_uii);
MRGEN_V(00501, "LDLR", d_ldlr);
MRGEN_R(00502, "QFxx", d_qfxxuii);
MRGEN_V(00502, "QFxx", d_qfxxuii);
MRGEN_R(00503, "JGT", d_jgt);
MRGEN_V(00503, "ERL", d_erl);
MRGEN_R(00600, "ADD/DAD", d_adddad);
MRGEN_V(00600, "ADD", d_add);
MRGEN_R(00601, "FAD", d_fad);
MRGEN_V(00601, "FAD", d_fad);
MRGEN_R(00602, "DFAD", d_dfad);
MRGEN_V(00602, "DFAD", d_dfad);
MRGEN_R(00603, "JLT", d_jlt);
MRGEN_V(00603, "ADL", d_adl);
MRGEN_R(00700, "SUB/DSB", d_subdsb);
MRGEN_V(00700, "SUB", d_sub);
MRGEN_R(00701, "FSB", d_fsb);
MRGEN_V(00701, "FSB", d_fsb);
MRGEN_R(00702, "DFSB", d_dfsb);
MRGEN_V(00702, "DFSB", d_dfsb);
MRGEN_R(00703, "JGE", d_jge);
MRGEN_V(00703, "SBL", d_sbl);
MRGEN_R(01000, "JST", d_jst);
MRGEN_V(01000, "JST", d_jst);
MRGEN_R(01002, "CREP", d_crep);
MRGEN_V(01002, "PCL", d_pcl);
MRGEN_R(01100, "CAS", d_cas);
MRGEN_V(01100, "CAS", d_cas);
MRGEN_R(01101, "FCS", d_fcs);
MRGEN_V(01101, "FCS", d_fcs);
MRGEN_R(01102, "DFCS", d_dfcs);
MRGEN_V(01102, "DFCS", d_dfcs);
MRGEN_R(01103, "CLS?", d_uii);
MRGEN_V(01103, "CLS", d_cls);
MRGEN_R(01200, "IRS", d_irs);
MRGEN_V(01200, "IRS", d_irs);
MRGEN_R(01202, "EAXB?", d_uii);
MRGEN_V(01202, "EAXB", d_eaxb);
MRGEN_R(01300, "IMA", d_ima);
MRGEN_V(01300, "IMA", d_ima);
MRGEN_R(01302, "EALB?", d_uii);
MRGEN_V(01302, "EALB", d_ealb);
MRGEN_R(01400, "JSY?", d_uii);
MRGEN_V(01400, "JSY", d_jsy);
MRGEN_R(01401, "EIO?", d_uii);
MRGEN_V(01401, "EIO", d_eio);
MRGEN_R(01402, "JSXB?", d_uii);
MRGEN_V(01402, "JSXB", d_jsxb);
MRGEN_R(01500, "STX", d_stx);
MRGEN_V(01500, "STX", d_stx);
MRGEN_R(01501, "FLX", d_flx);
MRGEN_V(01501, "FLX", d_flx);
MRGEN_R(01502, "JDX", d_jdx);
MRGEN_V(01502, "DFLX", d_dflx);
MRGEN_R(01503, "JIX", d_jix);
MRGEN_V(01503, "QFLX", d_qflx);
MRGEN_R(01600, "MPY", d_mpy_r);
MRGEN_V(01600, "MPY", d_mpy);
MRGEN_R(01601, "FMP", d_fmp);
MRGEN_V(01601, "FMP", d_fmp);
MRGEN_R(01602, "DFMP", d_dfmp);
MRGEN_V(01602, "DFMP", d_dfmp);
MRGEN_R(01603, "MPL?", d_uii);
MRGEN_V(01603, "MPL", d_mpl);
MRGEN_R(01700, "DIV", d_div);
MRGEN_V(01700, "DIV", d_div);
MRGEN_R(01701, "FDV", d_fdv);
MRGEN_V(01701, "FDV", d_fdv);
MRGEN_R(01702, "DFDV", d_dfdv);
MRGEN_V(01702, "DFDV", d_dfdv);
MRGEN_R(01703, "DVL?", d_uii);
MRGEN_V(01703, "DVL", d_dvl);
MRGEN_R(03500, "LDX", d_ldx);
MRGEN_V(03500, "LDX", d_ldx);
MRGEN_R(03501, "LDY?", d_uii);
MRGEN_V(03501, "LDY", d_ldy);
MRGEN_R(03502, "STY?", d_uii);
MRGEN_V(03502, "STY", d_sty);
MRGEN_R(03503, "JSX", d_jsx);
MRGEN_V(03503, "JSX", d_jsx);
#define GENIX(inst) ((inst>>4) & 06000) | (inst & 01777)

397
em.c
View File

@@ -428,7 +428,7 @@ typedef struct {
order fault bit of vpn is never set. The ring and extension bits
are used to store the 3-bit access field from the STLB for the
current ring (remember that all brp entries are invalidated by
PCL and PRTN when the ring might change).
PCL and PRTN when the ring changes).
Storing the access bits in the vpn allows use of of the brp
cache for write accesses as well as read accesses. */
@@ -482,7 +482,8 @@ typedef struct {
int supercalls; /* supercache hits */
int supermisses;
void *disp_mr[128]; /* V/R memory ref dispatch table */
void *disp_rmr[128]; /* R-mode memory ref dispatch table */
void *disp_vmr[128]; /* V-mode memory ref dispatch table */
/* traceflags is the variable used to test tracing of each instruction
traceuser is the user number to trace, 0 meaning any user
@@ -4510,8 +4511,10 @@ For disk boots, the last 3 digits can be:\n\
fetch:
#if 0
if (gvp->instcount > 32727500)
gvp->savetraceflags = ~0;
if (gvp->instcount > 2681900)
gvp->savetraceflags = TB_FLOW;
if (gvp->instcount > 3000000)
gvp->savetraceflags = 0;
#endif
#if 0
@@ -4776,7 +4779,7 @@ xec:
if ((crs[KEYS] & 016000) == 014000) { /* 64V mode */
ea = ea64v(inst, earp);
TRACE(T_FLOW, " EA: %o/%o %s\n",ea>>16, ea & 0xFFFF, searchloadmap(ea,' '));
goto *(gvp->disp_mr[VMRINSTIX(inst)]);
goto *(gvp->disp_vmr[VMRINSTIX(inst)]);
} else if ((crs[KEYS] & 0016000) == 010000) { /* E32I */
goto imode;
@@ -4788,17 +4791,17 @@ xec:
} else if (crs[KEYS] & 004000) { /* 32R/64R */
ea = ea32r64r(earp, inst);
TRACE(T_FLOW, " EA: %o/%o %s\n",ea>>16, ea & 0xFFFF, searchloadmap(ea,' '));
goto *(gvp->disp_mr[RMRINSTIX(inst)]);
goto *(gvp->disp_rmr[RMRINSTIX(inst)]);
} else if (crs[KEYS] & 002000) {
ea = ea32s(inst);
TRACE(T_FLOW, " EA: %o/%o %s\n",ea>>16, ea & 0xFFFF, searchloadmap(ea,' '));
goto *(gvp->disp_mr[SMRINSTIX(inst)]);
goto *(gvp->disp_rmr[SMRINSTIX(inst)]);
} else if ((crs[KEYS] & 016000) == 0) {
ea = ea16s(inst);
TRACE(T_FLOW, " EA: %o/%o %s\n",ea>>16, ea & 0xFFFF, searchloadmap(ea,' '));
goto *(gvp->disp_mr[SMRINSTIX(inst)]);
goto *(gvp->disp_rmr[SMRINSTIX(inst)]);
} else {
printf("Bad CPU mode in EA calculation, keys = %o\n", crs[KEYS]);
@@ -8928,12 +8931,17 @@ imodepcl:
fatal("I-mode fall-through?");
d_lda: /* 00200 (V-mode) */
crs[A] = get16t(ea);
TRACE(T_FLOW, " LDA ='%o/%d %03o %03o\n", crs[A], *(short *)(crs+A), crs[A]>>8, crs[A] & 0xFF);
goto fetch;
/* NOTE: don't use get32 for DLD/DST, because it doesn't handle register
address traps */
d_ldadld: /* 00200 */
d_ldadld: /* 00200 (R-mode) */
crs[A] = get16t(ea);
if ((crs[KEYS] & 050000) != 040000) { /* not R-mode or not DP */
if (!(crs[KEYS] & 040000)) { /* not DP */
TRACE(T_FLOW, " LDA ='%o/%d %03o %03o\n", crs[A], *(short *)(crs+A), crs[A]>>8, crs[A] & 0xFF);
} else {
TRACE(T_FLOW, " DLD\n");
@@ -8941,7 +8949,12 @@ d_ldadld: /* 00200 */
}
goto fetch;
d_stadst: /* 00400 */
d_sta: /* 00400 (V-mode) */
TRACE(T_FLOW, " STA\n");
put16t(crs[A],ea);
goto fetch;
d_stadst: /* 00400 (R-mode) */
put16t(crs[A],ea);
if ((crs[KEYS] & 050000) != 040000) {
TRACE(T_FLOW, " STA\n");
@@ -8968,66 +8981,73 @@ d_era: /* 00500 */
crs[A] ^= m;
goto fetch;
d_adddad: /* 00600 */
crs[KEYS] &= ~0120300; /* clear C, L, LT, EQ */
d_add: /* 00600 (V-mode) */
m = get16t(ea);
TRACE(T_FLOW, " ADD ='%o/%d\n", m, *(short *)&m);
add16(crs+A, m, 0, ea);
goto fetch;
d_adddad: /* 00600 (R-mode) */
if (!(crs[KEYS] & 040000)) /* dbl mode? */
goto d_add;
TRACE(T_FLOW, " DAD\n");
crs[KEYS] &= ~0120300; /* clear C, L, LT, EQ */
utempa = crs[A];
m = get16t(ea);
if ((crs[KEYS] & 050000) != 040000) { /* V/I mode or SP */
TRACE(T_FLOW, " ADD ='%o/%d\n", m, *(short *)&m);
add16(crs+A, m, 0, ea);
} else { /* R-mode and DP */
TRACE(T_FLOW, " DAD\n");
crs[B] += get16t(INCVA(ea,1));
utempl = crs[A];
if (crs[B] & 0x8000) {
utempl++;
crs[B] &= 0x7fff;
}
utempl += m;
crs[A] = utempl;
if (utempl & 0x10000) /* set L-bit if carry */
crs[KEYS] |= 020000;
/* NOTE: this EQ test prevents reusing the ADD code :( */
if (*(int *)(crs+L) == 0) /* set EQ? */
SETEQ;
if (((~utempa ^ m) & (utempa ^ crs[A])) & 0x8000) {
if (*(int *)(crs+L) >= 0)
SETLT;
mathexception('i', FC_INT_OFLOW, 0);
} else if (*(int *)(crs+L) < 0)
SETLT;
crs[B] += get16t(INCVA(ea,1));
utempl = crs[A];
if (crs[B] & 0x8000) {
utempl++;
crs[B] &= 0x7fff;
}
utempl += m;
crs[A] = utempl;
if (utempl & 0x10000) /* set L-bit if carry */
crs[KEYS] |= 020000;
/* NOTE: this EQ test prevents reusing the ADD code :( */
if (*(int *)(crs+L) == 0) /* set EQ? */
SETEQ;
if (((~utempa ^ m) & (utempa ^ crs[A])) & 0x8000) {
if (*(int *)(crs+L) >= 0)
SETLT;
mathexception('i', FC_INT_OFLOW, 0);
} else if (*(int *)(crs+L) < 0)
SETLT;
goto fetch;
d_sub: /* 00700 (V-mode) */
m = get16t(ea);
utempa = crs[A];
TRACE(T_FLOW, " SUB ='%o/%d\n", m, *(short *)&m);
add16(crs+A, ~m, 1, ea);
goto fetch;
d_subdsb: /* 00700 */
if (!(crs[KEYS] & 040000))
goto d_sub;
TRACE(T_FLOW, " DSB\n");
crs[KEYS] &= ~0120300; /* clear C, L, and CC */
utempa = crs[A];
m = get16t(ea);
if ((crs[KEYS] & 050000) != 040000) {
TRACE(T_FLOW, " SUB ='%o/%d\n", m, *(short *)&m);
add16(crs+A, ~m, 1, ea);
} else {
TRACE(T_FLOW, " DSB\n");
crs[B] -= get16t(INCVA(ea,1));
utempl = crs[A];
if (crs[B] & 0x8000) {
utempl += 0xFFFF;
crs[B] &= 0x7fff;
}
utempl += (unsigned short) ~m;
utempl += 1;
crs[A] = utempl; /* truncate results */
if (utempl & 0x10000) /* set L-bit if carry */
crs[KEYS] |= 020000;
if (*(int *)(crs+L) == 0) /* set EQ? */
SETEQ;
if (((utempa ^ m) & (utempa ^ crs[A])) & 0x8000) {
if (*(int *)(crs+L) >= 0)
SETLT;
mathexception('i', FC_INT_OFLOW, 0);
} else if (*(int *)(crs+L) < 0)
SETLT;
crs[B] -= get16t(INCVA(ea,1));
utempl = crs[A];
if (crs[B] & 0x8000) {
utempl += 0xFFFF;
crs[B] &= 0x7fff;
}
utempl += (unsigned short) ~m;
utempl += 1;
crs[A] = utempl; /* truncate results */
if (utempl & 0x10000) /* set L-bit if carry */
crs[KEYS] |= 020000;
if (*(int *)(crs+L) == 0) /* set EQ? */
SETEQ;
if (((utempa ^ m) & (utempa ^ crs[A])) & 0x8000) {
if (*(int *)(crs+L) >= 0)
SETLT;
mathexception('i', FC_INT_OFLOW, 0);
} else if (*(int *)(crs+L) < 0)
SETLT;
goto fetch;
d_ora: /* 00302 */
@@ -9059,13 +9079,13 @@ d_cas: /* 01100 */
stopwatch_push(&sw_cas);
m = get16t(ea);
TRACE(T_FLOW, " CAS ='%o/%d\n", m, *(short *)&m);
#if 0
if (crs[A] == m) {
INCRP;
} else if (*(short *)(crs+A) < *(short *)&m) {
RPL += 2;
}
#else
#if 1
/* this crap is to set L & CC like subtract would, even though
most programs never tested these after CAS. add16 can't be
used because docs say CAS leaves C-bit unchanged... :( */
crs[KEYS] &= ~020300; /* clear L, and CC */
utempa = crs[A];
utempl = crs[A];
@@ -9082,11 +9102,13 @@ d_cas: /* 01100 */
} else if (*(short *)(crs+A) < 0)
SETLT;
crs[A] = utempa; /* restore A reg */
if (crs[A] == m)
INCRP;
else if (*(short *)(crs+A) < *(short *)&m)
RPL += 2;
#endif
if (crs[A] == m) {
INCRP;
} else if (*(short *)(crs+A) < *(short *)&m) {
RPL += 2;
}
stopwatch_pop(&sw_cas);
goto fetch;
@@ -9123,39 +9145,39 @@ d_stx: /* 01500 */
put16t(crs[X],ea);
goto fetch;
/* MPY can't overflow in V-mode, but in R-mode (31 bits),
-32768*-32768 can overflow and yields 0x8000/0x0000 */
/* MPY can't overflow in V-mode */
d_mpy: /* 01600 */
d_mpy: /* 01600 (V-mode) */
m = get16t(ea);
TRACE(T_FLOW, " MPY ='%o/%d\n", m, *(short *)&m);
*(int *)(crs+L) = *(short *)(crs+A) * *(short *)&m;
CLEARC;
goto fetch;
/* in R-mode (31 bits), -32768*-32768 can overflow and yields
0x8000/0x0000 */
d_mpy_r: /* 01600 (R-mode) */
m = get16t(ea);
TRACE(T_FLOW, " MPY ='%o/%d\n", m, *(short *)&m);
templ = *(short *)(crs+A) * *(short *)&m;
CLEARC;
if (crs[KEYS] & 010000) { /* V/I mode */
*(int *)(crs+L) = templ;
} else { /* R/S mode */
utempa = crs[A];
crs[A] = (templ >> 15);
crs[B] = templ & 077777;
if (utempa == 0x8000 && m == 0x8000)
mathexception('i', FC_INT_OFLOW, 0);
}
utempa = crs[A];
crs[A] = (templ >> 15);
crs[B] = templ & 077777;
if (utempa == 0x8000 && m == 0x8000)
mathexception('i', FC_INT_OFLOW, 0);
goto fetch;
d_mpl: /* 01603 */
d_mpl: /* 01603 (V-mode) */
templ = get32(ea);
TRACE(T_FLOW, " MPL ='%o/%d\n", templ, *(int *)&templ);
*(long long *)(crs+L) = (long long)(*(int *)(crs+L)) * (long long)templ;
CLEARC;
goto fetch;
/* DIAG CPU.FAULT uses this instruction in R-mode to triggger a
UII fault, so this instruction (unlike most) checks the keys.
This is a general problem with all instructions: they don't
ensure the instruction is legal in the current mode */
if ((crs[KEYS] & 010000)) { /* V/I mode */
templ = get32(ea);
TRACE(T_FLOW, " MPL ='%o/%d\n", templ, *(int *)&templ);
*(long long *)(crs+L) = (long long)(*(int *)(crs+L)) * (long long)templ;
CLEARC;
} else
fault(UIIFAULT, RPL, RP);
d_uii:
fault(UIIFAULT, RPL, RP);
goto fetch;
d_div: /* 01700 */
@@ -9203,95 +9225,96 @@ d_ldx: /* 03500 */
crs[X] = get16t(ea);
goto fetch;
d_ealeaa: /* 00101 */
if (crs[KEYS] & 010000) { /* V/I mode */
TRACE(T_FLOW, " EAL\n");
*(ea_t *)(crs+L) = ea;
} else {
TRACE(T_FLOW, " EAA\n");
crs[A] = ea;
}
d_eal: /* 00101 (V-mode) */
TRACE(T_FLOW, " EAL\n");
*(ea_t *)(crs+L) = ea;
goto fetch;
d_ldljeq: /* 00203 */
if (crs[KEYS] & 010000) { /* V/I mode */
*(unsigned int *)(crs+L) = get32(ea);
TRACE(T_FLOW, " LDL ='%o/%d\n", *(unsigned int *)(crs+A), *(int *)(crs+A));
} else {
TRACE(T_FLOW, " JEQ\n");
if (*(short *)(crs+A) == 0)
RPL = ea;
}
d_eaa: /* 00101 (R-mode) */
TRACE(T_FLOW, " EAA\n");
crs[A] = ea;
goto fetch;
d_sbljge: /* 00703 */
if (crs[KEYS] & 010000) { /* V/I mode */
utempl = get32(ea);
TRACE(T_FLOW, " SBL ='%o/%d\n", utempl, *(int *)&utempl);
add32(crsl+GR2, ~utempl, 1, ea);
} else {
TRACE(T_FLOW, " JGE\n");
if (*(short *)(crs+A) >= 0)
RPL = ea;
}
d_ldl: /* 00203 (V-mode) */
*(unsigned int *)(crs+L) = get32(ea);
TRACE(T_FLOW, " LDL ='%o/%d\n", *(unsigned int *)(crs+A), *(int *)(crs+A));
goto fetch;
d_pclcrep: /* 01002 */
d_jeq: /* 00203 (R-mode) */
TRACE(T_FLOW, " JEQ\n");
if (*(short *)(crs+A) == 0)
RPL = ea;
goto fetch;
d_sbl: /* 00703 (V-mode) */
utempl = get32(ea);
TRACE(T_FLOW, " SBL ='%o/%d\n", utempl, *(int *)&utempl);
add32(crsl+GR2, ~utempl, 1, ea);
goto fetch;
d_jge: /* 00703 (R-mode) */
TRACE(T_FLOW, " JGE\n");
if (*(short *)(crs+A) >= 0)
RPL = ea;
goto fetch;
d_pcl: /* 01002 (V-mode) */
/* NOTE: real PCL code is in I-mode section! */
if (crs[KEYS] & 010000) /* V/I mode */
goto imodepcl;
goto imodepcl;
d_crep: /* 01002 (R-mode) */
TRACE(T_FLOW, " CREP\n");
put16t(RPL,crs[S]++);
RPL = ea;
goto fetch;
d_erljgt: /* 00503 */
if (crs[KEYS] & 010000) { /* V/I mode */
utempl = get32(ea);
TRACE(T_FLOW, " ERL ='%o/%d '%o/'%o %d/%d\n", utempl, *(int *)&utempl, utempl>>16, utempl&0xFFFF, utempl>>16, utempl&0xFFFF);
*(unsigned int *)(crs+L) ^= utempl;
} else {
TRACE(T_FLOW, " JGT\n");
if (*(short *)(crs+A) > 0)
RPL = ea;
}
d_erl: /* 00503 (V-mode) */
utempl = get32(ea);
TRACE(T_FLOW, " ERL ='%o/%d '%o/'%o %d/%d\n", utempl, *(int *)&utempl, utempl>>16, utempl&0xFFFF, utempl>>16, utempl&0xFFFF);
*(unsigned int *)(crs+L) ^= utempl;
goto fetch;
d_stljle: /* 00403 */
if (crs[KEYS] & 010000) { /* V/I mode */
TRACE(T_FLOW, " STL\n");
put32(*(unsigned int *)(crs+L),ea);
} else {
TRACE(T_FLOW, " JLE\n");
if (*(short *)(crs+A) <= 0)
RPL = ea;
}
d_jgt: /* 00503 (R-mode) */
TRACE(T_FLOW, " JGT\n");
if (*(short *)(crs+A) > 0)
RPL = ea;
goto fetch;
d_adljlt: /* 00603 */
if (crs[KEYS] & 010000) { /* V/I mode */
utempl = get32(ea);
TRACE(T_FLOW, " ADL ='%o/%d\n", utempl, *(int *)&utempl);
add32(crsl+GR2, utempl, 0, ea);
} else {
TRACE(T_FLOW, " JLT\n");
if (*(short *)(crs+A) < 0)
RPL = ea;
}
d_stl: /* 00403 (V-mode) */
TRACE(T_FLOW, " STL\n");
put32(*(unsigned int *)(crs+L),ea);
goto fetch;
d_anljne: /* 00303 */
if (crs[KEYS] & 010000) { /* V/I mode */
utempl = get32(ea);
TRACE(T_FLOW, " ANL ='%o\n", utempl);
*(unsigned int *)(crs+L) &= utempl;
} else {
TRACE(T_FLOW, " JNE\n");
if (*(short *)(crs+A) != 0)
RPL = ea;
}
d_jle: /* 00403 (R-mode) */
TRACE(T_FLOW, " JLE\n");
if (*(short *)(crs+A) <= 0)
RPL = ea;
goto fetch;
d_adl: /* 00603 (V-mode) */
utempl = get32(ea);
TRACE(T_FLOW, " ADL ='%o/%d\n", utempl, *(int *)&utempl);
add32(crsl+GR2, utempl, 0, ea);
goto fetch;
d_jlt: /* 00603 (R-mode) */
TRACE(T_FLOW, " JLT\n");
if (*(short *)(crs+A) < 0)
RPL = ea;
goto fetch;
d_anl: /* 00303 (V-mode) */
utempl = get32(ea);
TRACE(T_FLOW, " ANL ='%o\n", utempl);
*(unsigned int *)(crs+L) &= utempl;
goto fetch;
d_jne: /* 00303 (R-mode) */
TRACE(T_FLOW, " JNE\n");
if (*(short *)(crs+A) != 0)
RPL = ea;
goto fetch;
d_eaxb: /* 01202 */
@@ -9299,16 +9322,16 @@ d_eaxb: /* 01202 */
*(ea_t *)(crs+XB) = ea;
goto fetch;
d_dflxjdx: /* 01502 */
if (crs[KEYS] & 010000) { /* V/I mode */
TRACE(T_FLOW, " DFLX\n");
crs[X] = get16(ea) * 4;
} else {
TRACE(T_FLOW, " JDX\n");
crs[X]--;
if (crs[X] != 0)
RPL = ea;
}
d_dflx: /* 01502 (V-mode) */
TRACE(T_FLOW, " DFLX\n");
crs[X] = get16(ea) * 4;
goto fetch;
d_jdx: /* 01502 (R-mode) */
TRACE(T_FLOW, " JDX\n");
crs[X]--;
if (crs[X] != 0)
RPL = ea;
goto fetch;
d_sty: /* 03502 */
@@ -9316,16 +9339,16 @@ d_sty: /* 03502 */
put16(crs[Y],ea);
goto fetch;
d_qflxjix: /* 01503 */
if (crs[KEYS] & 010000) { /* V/I mode */
TRACE(T_FLOW, " QFLX\n");
crs[X] = get16(ea) * 8;
} else {
TRACE(T_FLOW, " JIX\n");
crs[X]++;
if (crs[X] != 0)
RPL = ea;
}
d_qflx: /* 01503 (V-mode) */
TRACE(T_FLOW, " QFLX\n");
crs[X] = get16(ea) * 8;
goto fetch;
d_jix: /* 01503 (R-mode) */
TRACE(T_FLOW, " JIX\n");
crs[X]++;
if (crs[X] != 0)
RPL = ea;
goto fetch;
d_flx: /* 01501 */
@@ -9577,7 +9600,7 @@ d_dfst: /* 0402 */
TRACE(T_FLOW, " Stored %f '%o %o %o %o\n", tempd1, crs[FLTH], crs[FLTL], crs[FLTD], crs[FEXP]);
goto fetch;
d_ealb: /* 01302 */
d_ealb: /* 01302 */
TRACE(T_FLOW, " EALB\n");
*(ea_t *)(crs+LB) = ea;
goto fetch;