diff --git a/dispatch.h b/dispatch.h index 22f8aaa..9f6605a 100644 --- a/dispatch.h +++ b/dispatch.h @@ -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)] = &⌖ \ + /* printf("V-MR opcode %05o (%s), ix=%0d\n", opcode, name, MRPRIMEIX(opcode)); */ \ + if ((opcode & 01700) != 01500) { \ + gvp->disp_vmr[MRPRIMEIX(opcode | 02000)] = &⌖ \ + /* 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) diff --git a/em.c b/em.c index e78276c..bd07f62 100644 --- a/em.c +++ b/em.c @@ -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;