- Avoid macro name conflic REG_NONE changed to REG_NOREG - Avoid a t_offset truncation assigning to a uint16 in drm_attach.
696 lines
22 KiB
C
696 lines
22 KiB
C
/*
|
|
|
|
Copyright (c) 2015-2017, John Forecast
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
copy of this software and associated documentation files (the "Software"),
|
|
to deal in the Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
JOHN FORECAST BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of John Forecast shall not
|
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from John Forecast.
|
|
|
|
*/
|
|
|
|
/* cdc1700_dis.c: CDC1700 disassembler
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "cdc1700_defs.h"
|
|
|
|
extern uint16 Areg, Mreg, Preg, Qreg, RelBase;
|
|
extern uint16 LoadFromMem(uint16);
|
|
extern uint8 P[];
|
|
extern DEVICE cpu_dev;
|
|
extern UNIT cpu_unit;
|
|
extern t_stat disEffectiveAddr(uint16, uint16, uint16 *, uint16 *);
|
|
extern uint16 doADDinternal(uint16, uint16);
|
|
|
|
const char *opName[] = {
|
|
"???", "JMP", "MUI", "DVI", "STQ", "RTJ", "STA", "SPA",
|
|
"ADD", "SUB", "AND", "EOR", "LDA", "RAO", "LDQ", "ADQ"
|
|
};
|
|
|
|
const char *idxName[] = {
|
|
"", ",I", ",Q", ",B"
|
|
};
|
|
|
|
const char *spcName[] = {
|
|
"SLS", "???", "INP", "OUT", "EIN", "IIN", "SPB", "CPB",
|
|
"???", "INA", "ENA", "NOP", "ENQ", "INQ", "EXI", "???"
|
|
};
|
|
|
|
const char *skpName[] = {
|
|
"SAZ", "SAN", "SAP", "SAM", "SQZ", "SQN", "SQP", "SQM",
|
|
"SWS", "SWN", "SOV", "SNO", "SPE", "SNP", "SPF", "SNF"
|
|
};
|
|
|
|
const char *interName[] = {
|
|
"SET", "TRM", "TRQ", "TRB", "TRA", "AAM", "AAQ", "AAB",
|
|
"CLR", "TCM", "TCQ", "TCB", "TCA", "EAM", "EAQ", "EAB",
|
|
"SET", "TRM", "TRQ", "TRB", "TRA", "LAM", "LAQ", "LAB",
|
|
"NOOP", NULL, NULL, NULL, NULL, "CAM", "CAQ", "CAB"
|
|
};
|
|
|
|
const char *destName[] = {
|
|
"", "M", "Q", "Q,M", "A", "A,M", "A,Q", "A,Q,M"
|
|
};
|
|
|
|
const char *shiftName[] = {
|
|
NULL, "QRS", "ARS", "LRS", NULL, "QLS", "ALS", "LLS"
|
|
};
|
|
|
|
/*
|
|
* Enhanced instruction set mnemonics
|
|
*/
|
|
char enhRegChar[] = {
|
|
' ', '1', '2', '3', '4', 'Q', 'A', 'I'
|
|
};
|
|
|
|
const char *enhIdxName[] = {
|
|
"", ",1", ",2", ",3", ",4", ",Q", ",A", ",I"
|
|
};
|
|
|
|
char enhSkipType[] = {
|
|
'Z', 'N', 'P', 'M'
|
|
};
|
|
|
|
char enhSkipReg[] = {
|
|
'4', '1', '2', '3'
|
|
};
|
|
|
|
const char *enhMiscName0[] = {
|
|
"???", "LMM", "LRG", "SRG", "SIO", "SPS", "DMI", "CBP",
|
|
"GPE", "GPO", "ASC", "APM", "PM0", "PM1"
|
|
};
|
|
#define ENH_MAXMISC0 0xD
|
|
|
|
const char *enhMiscName1[] = {
|
|
"LUB", "LLB", "EMS", "WPR", "RPR", "ECC"
|
|
};
|
|
#define ENH_MAXMISC1 0x5
|
|
|
|
const char *enhFldName[] = {
|
|
"???", "???", "SFZ", "SFN", "LFA", "SFA", "CLF", "SEF"
|
|
};
|
|
|
|
/*
|
|
* Generate a single line of text for an instruction. Format is:
|
|
*
|
|
* c xxxx yyyy zzzz <instr> <targ>
|
|
*
|
|
* or if enhanced instruction set is enabled
|
|
*
|
|
* c xxxx yyyy zzzz aaaa <instr> <targ>
|
|
*
|
|
* where:
|
|
*
|
|
* |P Normal/Protected location
|
|
* xxxx Memory address of instruction in hex
|
|
* yyyy First word of instruction in hex
|
|
* zzzz Second word of instruction in hex, replaced by spaces if
|
|
* not present
|
|
* aaaa Third word of instruction in hex, replaced by spaces if
|
|
* not present
|
|
* <instr> Disassmbled instruction
|
|
* <targ> Optional target address and contents
|
|
*
|
|
* Returns:
|
|
* # of words consumed by the instruction
|
|
*/
|
|
|
|
int disassem(char *buf, uint16 addr, t_bool dbg, t_bool targ, t_bool exec)
|
|
{
|
|
int consumed = 1;
|
|
char prot = ISPROTECTED(addr) ? 'P' : ' ';
|
|
char optional[8], optional2[8], temp[8], decoded[64], enhInstr[8];
|
|
const char *mode, *spc, *shift, *inter, *dest;
|
|
uint16 instr = LoadFromMem(addr);
|
|
uint16 instr2, enhMode;
|
|
uint16 delta = instr & OPC_ADDRMASK;
|
|
uint8 more = 0, isconst = 0, enhRB;
|
|
uint16 t;
|
|
t_bool enhValid = FALSE, enhChar = FALSE;
|
|
|
|
strcpy(optional, " ");
|
|
strcpy(optional2, " ");
|
|
strcpy(decoded, "UNDEF");
|
|
|
|
if ((instr & OPC_MASK) != 0) {
|
|
if ((instr & MOD_RE) == 0)
|
|
mode = delta == 0 ? "+ " : "- ";
|
|
else mode = "* ";
|
|
|
|
switch (instr & OPC_MASK) {
|
|
case OPC_ADQ:
|
|
case OPC_LDQ:
|
|
case OPC_LDA:
|
|
case OPC_EOR:
|
|
case OPC_AND:
|
|
case OPC_SUB:
|
|
case OPC_ADD:
|
|
case OPC_DVI:
|
|
case OPC_MUI:
|
|
if (ISCONSTANT(instr))
|
|
isconst = 1;
|
|
break;
|
|
}
|
|
|
|
if (delta == 0) {
|
|
consumed++;
|
|
sprintf(optional, "%04X", LoadFromMem(addr + 1));
|
|
sprintf(temp, "$%04X", LoadFromMem(addr + 1));
|
|
} else sprintf(temp, "$%02X", delta);
|
|
|
|
sprintf(decoded, "%s%s%s%s%s%s%s",
|
|
opName[(instr & OPC_MASK) >> 12],
|
|
mode,
|
|
isconst ? "=" : "",
|
|
(instr & MOD_IN) != 0 ? "(" : "",
|
|
temp,
|
|
(instr & MOD_IN) != 0 ? ")" : "",
|
|
idxName[(instr & (MOD_I1 | MOD_I2)) >> 8]);
|
|
} else {
|
|
spc = spcName[(instr & OPC_SPECIALMASK) >> 8];
|
|
|
|
switch (instr & OPC_SPECIALMASK) {
|
|
case OPC_IIN:
|
|
case OPC_EIN:
|
|
case OPC_SPB:
|
|
case OPC_CPB:
|
|
switch (INSTR_SET) {
|
|
case INSTR_ORIGINAL:
|
|
/*
|
|
* Character addressing enable/disable is only available as
|
|
* an extension to the original set.
|
|
*/
|
|
switch (instr) {
|
|
case OPC_ECA:
|
|
sprintf(decoded, "%s", "ECA");
|
|
break;
|
|
|
|
case OPC_DCA:
|
|
sprintf(decoded, "%s", "DCA");
|
|
break;
|
|
|
|
default:
|
|
sprintf(decoded, "%s", spc);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case INSTR_BASIC:
|
|
if (delta == 0) {
|
|
sprintf(decoded, "%s", spc);
|
|
} else {
|
|
sprintf(decoded, "%s", "NOP [ Possible enhanced instruction");
|
|
}
|
|
break;
|
|
|
|
case INSTR_ENHANCED:
|
|
if (delta != 0) {
|
|
switch (instr & OPC_SPECIALMASK) {
|
|
case OPC_IIN:
|
|
if (((instr & OPC_FLDF3A) != OPC_FLDRSV1) &&
|
|
((instr & OPC_FLDF3A) != OPC_FLDRSV2)) {
|
|
instr2 = LoadFromMem(addr + 1);
|
|
delta = instr2 & OPC_ADDRMASK;
|
|
|
|
if (((instr2 & OPC_FLDSTR) - (instr2 & OPC_FLDLTH)) >= 0) {
|
|
consumed++;
|
|
|
|
if ((instr & MOD_ENHRE) == 0)
|
|
mode = delta == 0 ? "+ " : "- ";
|
|
else mode = "* ";
|
|
|
|
sprintf(optional, "%04X", instr2);
|
|
if (delta == 0) {
|
|
consumed++;
|
|
sprintf(optional2, "%04X", LoadFromMem(addr + 2));
|
|
sprintf(temp, "$%04X", LoadFromMem(addr + 2));
|
|
} else sprintf(temp, "$%02X", delta);
|
|
|
|
sprintf(decoded, "%s%s%s%s%s,%d,%d%s",
|
|
enhFldName[instr & OPC_FLDF3A],
|
|
mode,
|
|
(instr & MOD_ENHIN) != 0 ? "(" : "",
|
|
temp,
|
|
(instr & MOD_ENHIN) != 0 ? ")" : "",
|
|
(instr2 & OPC_FLDSTR) >> 12,
|
|
((instr2 & OPC_FLDLTH) >> 8) + 1,
|
|
enhIdxName[(instr & MOD_ENHRA) >> 3]);
|
|
break;
|
|
}
|
|
}
|
|
strcpy(decoded, "UNDEF");
|
|
targ = FALSE;
|
|
break;
|
|
|
|
case OPC_EIN:
|
|
instr2 = LoadFromMem(addr + 1);
|
|
enhMode = (instr2 & OPC_ENHF5) >> 8;
|
|
enhRB = instr & MOD_ENHRB;
|
|
|
|
switch (instr2 & OPC_ENHF4) {
|
|
case OPC_STOSJMP:
|
|
if (enhMode == 0) {
|
|
enhValid = TRUE;
|
|
if (enhRB == REG_NOREG)
|
|
strcpy(enhInstr, "SJE");
|
|
else sprintf(enhInstr, "SJ%c", enhRegChar[enhRB]);
|
|
}
|
|
break;
|
|
|
|
case OPC_STOADD:
|
|
if ((enhMode == 0) && (enhRB != REG_NOREG)) {
|
|
enhValid = TRUE;
|
|
sprintf(enhInstr, "AR%c", enhRegChar[enhRB]);
|
|
}
|
|
break;
|
|
|
|
case OPC_STOSUB:
|
|
if ((enhMode == 0) && (enhRB != REG_NOREG)) {
|
|
enhValid = TRUE;
|
|
sprintf(enhInstr, "SB%c", enhRegChar[enhRB]);
|
|
}
|
|
break;
|
|
|
|
case OPC_STOAND:
|
|
if (enhRB != REG_NOREG)
|
|
switch (enhMode) {
|
|
case WORD_REG:
|
|
enhValid = TRUE;
|
|
sprintf(enhInstr, "AN%c", enhRegChar[enhRB]);
|
|
break;
|
|
|
|
case WORD_MEM:
|
|
enhValid = TRUE;
|
|
sprintf(enhInstr, "AM%c", enhRegChar[enhRB]);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case OPC_STOLOADST:
|
|
switch (enhMode) {
|
|
case WORD_REG:
|
|
if (enhRB != REG_NOREG) {
|
|
enhValid = TRUE;
|
|
sprintf(enhInstr, "LR%c", enhRegChar[enhRB]);
|
|
}
|
|
break;
|
|
|
|
case WORD_MEM:
|
|
if (enhRB != REG_NOREG) {
|
|
enhValid = TRUE;
|
|
sprintf(enhInstr, "SR%c", enhRegChar[enhRB]);
|
|
}
|
|
break;
|
|
|
|
case CHAR_REG:
|
|
if (enhRB != REG_NOREG) {
|
|
enhValid = TRUE;
|
|
enhChar = TRUE;
|
|
strcpy(enhInstr, "LCA");
|
|
}
|
|
break;
|
|
|
|
case CHAR_MEM:
|
|
if (enhRB != REG_NOREG) {
|
|
enhValid = TRUE;
|
|
enhChar = TRUE;
|
|
strcpy(enhInstr, "SCA");
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case OPC_STOOR:
|
|
if (enhRB != REG_NOREG)
|
|
switch (enhMode) {
|
|
case WORD_REG:
|
|
enhValid = TRUE;
|
|
sprintf(enhInstr, "OR%c", enhRegChar[enhRB]);
|
|
break;
|
|
|
|
case WORD_MEM:
|
|
enhValid = TRUE;
|
|
sprintf(enhInstr, "OM%c", enhRegChar[enhRB]);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case OPC_STOCRE:
|
|
switch (enhMode) {
|
|
case WORD_REG:
|
|
if (enhRB != REG_NOREG) {
|
|
enhValid = TRUE;
|
|
sprintf(enhInstr, "C%cE", enhRegChar[enhRB]);
|
|
}
|
|
break;
|
|
|
|
case CHAR_REG:
|
|
if (enhRB != REG_NOREG) {
|
|
enhValid = TRUE;
|
|
enhChar = TRUE;
|
|
strcpy(enhInstr, "CCE");
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
if (enhValid) {
|
|
delta = instr2 & OPC_ADDRMASK;
|
|
consumed++;
|
|
|
|
if ((instr & MOD_ENHRE) == 0)
|
|
mode = delta == 0 ? "+ " : "- ";
|
|
else mode = "* ";
|
|
|
|
sprintf(optional, "%04X", instr2);
|
|
if (delta == 0) {
|
|
consumed++;
|
|
sprintf(optional2, "%04X", LoadFromMem(addr + 2));
|
|
sprintf(temp, "$%04X", LoadFromMem(addr + 2));
|
|
} else sprintf(temp, "$%02X", delta);
|
|
|
|
if (!enhChar) {
|
|
if ((delta == 0) &&
|
|
(instr & (MOD_ENHRE | MOD_ENHIN)) == 0)
|
|
isconst = 1;
|
|
|
|
sprintf(decoded, "%s%s%s%s%s%s%s",
|
|
enhInstr,
|
|
mode,
|
|
isconst ? "=" : "",
|
|
(instr & MOD_ENHIN) != 0 ? "(" : "",
|
|
temp,
|
|
(instr & MOD_ENHIN) != 0 ? ")" : "",
|
|
enhIdxName[(instr & MOD_ENHRA) >> 3]);
|
|
} else {
|
|
sprintf(decoded, "%s%s%s%s%s%s%s",
|
|
enhInstr,
|
|
mode,
|
|
(instr & MOD_ENHIN) != 0 ? "(" : "",
|
|
temp,
|
|
(instr & MOD_ENHIN) != 0 ? ")" : "",
|
|
enhIdxName[enhRB],
|
|
enhIdxName[(instr & MOD_ENHRA) >> 3]);
|
|
}
|
|
} else {
|
|
strcpy(decoded, "UNDEF");
|
|
targ = FALSE;
|
|
}
|
|
break;
|
|
|
|
case OPC_SPB:
|
|
if ((instr & OPC_DRPMBZ) == 0) {
|
|
char reg = enhRegChar[(instr & OPC_DRPRA) >> 5];
|
|
uint8 sk = instr & OPC_DRPSK;
|
|
|
|
sprintf(decoded, "D%cP $%1X", reg, sk);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case OPC_CPB:
|
|
if ((instr & OPC_ENHXFRF2A) == 0) {
|
|
if ((instr & (OPC_ENHXFRRA | OPC_ENHXFRRB)) != 0) {
|
|
char ra = enhRegChar[(instr & OPC_ENHXFRRA) >> 5];
|
|
char rb = enhRegChar[instr & OPC_ENHXFRRB];
|
|
|
|
sprintf(decoded, "XF%c %c", ra, rb);
|
|
break;
|
|
}
|
|
}
|
|
strcpy(decoded, "UNDEF");
|
|
targ = FALSE;
|
|
break;
|
|
}
|
|
} else {
|
|
sprintf(decoded, "%s", spc);
|
|
targ = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case OPC_NOP:
|
|
switch (INSTR_SET) {
|
|
case INSTR_ORIGINAL:
|
|
sprintf(decoded, "%s", spc);
|
|
break;
|
|
|
|
case INSTR_BASIC:
|
|
if (delta != 0) {
|
|
sprintf(decoded, "%s", "NOP [ Possible enhanced instruction");
|
|
} else sprintf(decoded, "%s", spc);
|
|
break;
|
|
|
|
case INSTR_ENHANCED:
|
|
if (delta != 0) {
|
|
uint8 miscFN = instr & OPC_MISCF3;
|
|
char reg = enhRegChar[(instr & OPC_MISCRA) >> 5];
|
|
|
|
targ = FALSE;
|
|
if ((instr & OPC_MISCRA) == 0) {
|
|
if (miscFN <= ENH_MAXMISC0)
|
|
spc = enhMiscName0[miscFN];
|
|
else spc = "UNDEF";
|
|
sprintf(decoded, "%s", spc);
|
|
} else {
|
|
if (miscFN <= ENH_MAXMISC1) {
|
|
spc = enhMiscName1[miscFN];
|
|
sprintf(decoded, "%s %c", spc, reg);
|
|
} else strcpy(decoded, "UNDEF");
|
|
}
|
|
} else sprintf(decoded, "%s", spc);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case OPC_EXI:
|
|
sprintf(decoded, "%s $%02X", spc, delta);
|
|
break;
|
|
|
|
case OPC_SKIPS:
|
|
sprintf(decoded, "%s $%01X",
|
|
skpName[(instr & OPC_SKIPMASK) >> 4], instr & OPC_SKIPCOUNT);
|
|
break;
|
|
|
|
case OPC_SLS:
|
|
if (delta != 0) {
|
|
switch (INSTR_SET) {
|
|
case INSTR_BASIC:
|
|
sprintf(decoded, "%s", "NOP [ Possible enhanced instruction");
|
|
break;
|
|
|
|
case INSTR_ORIGINAL:
|
|
sprintf(decoded, "%s $%02X", spc, delta);
|
|
break;
|
|
|
|
case INSTR_ENHANCED:
|
|
{
|
|
char reg = enhSkipReg[(instr & OPC_ENHSKIPREG) >> 6];
|
|
char type = enhSkipType[(instr & OPC_ENHSKIPTY) >> 4];
|
|
uint8 sk = instr & OPC_ENHSKIPCNT;
|
|
|
|
sprintf(decoded, "S%c%c $%1X", reg, type, sk);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case OPC_INP:
|
|
case OPC_OUT:
|
|
case OPC_INA:
|
|
case OPC_ENA:
|
|
case OPC_ENQ:
|
|
case OPC_INQ:
|
|
sprintf(decoded, "%s $%02X", spc, delta);
|
|
break;
|
|
|
|
case OPC_INTER:
|
|
t = instr & (MOD_LP | MOD_XR | MOD_O_A | MOD_O_Q | MOD_O_M);
|
|
inter = interName[t >> 3];
|
|
dest = destName[instr & (MOD_D_A | MOD_D_Q | MOD_D_M)];
|
|
if (inter != NULL)
|
|
sprintf(decoded, "%s %s", inter, dest);
|
|
break;
|
|
|
|
case OPC_SHIFTS:
|
|
shift = shiftName[(instr & OPC_SHIFTMASK) >> 5];
|
|
if (shift != NULL)
|
|
sprintf(decoded, "%s $%X", shift, instr & OPC_SHIFTCOUNT);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dbg) {
|
|
if (INSTR_SET == INSTR_ENHANCED)
|
|
sprintf(buf, "%c %04X %04X %s %s %s",
|
|
prot, addr, instr, optional, optional2, decoded);
|
|
else
|
|
sprintf(buf, "%c %04X %04X %s %s",
|
|
prot, addr, instr, optional, decoded);
|
|
} else {
|
|
if (INSTR_SET == INSTR_ENHANCED)
|
|
sprintf(buf, "%c %04X %s %s %s",
|
|
prot, instr, optional, optional2, decoded);
|
|
else
|
|
sprintf(buf, "%c %04X %s %s",
|
|
prot, instr, optional, decoded);
|
|
}
|
|
|
|
if (targ) {
|
|
const char *rel = "";
|
|
t_bool indJmp = FALSE;
|
|
uint16 taddr, taddr2, base;
|
|
|
|
switch (instr & OPC_MASK) {
|
|
case OPC_ADQ:
|
|
case OPC_LDQ:
|
|
case OPC_RAO:
|
|
case OPC_LDA:
|
|
case OPC_EOR:
|
|
case OPC_AND:
|
|
case OPC_SUB:
|
|
case OPC_ADD:
|
|
case OPC_SPA:
|
|
case OPC_STA:
|
|
case OPC_STQ:
|
|
case OPC_DVI:
|
|
case OPC_MUI:
|
|
if (((instr & (MOD_IN | MOD_I1 | MOD_I2)) == 0) || exec)
|
|
if (disEffectiveAddr(addr, instr, &base, &taddr) == SCPE_OK) {
|
|
more = cpu_dev.dctrl & DBG_FULL ? 2 : 1;
|
|
taddr2 = taddr;
|
|
if (((instr & (MOD_RE | MOD_IN | MOD_I1 | MOD_I2)) == MOD_RE) &&
|
|
((sim_switches & SWMASK('R')) != 0)) {
|
|
taddr2 -= RelBase;
|
|
rel = "*";
|
|
}
|
|
}
|
|
break;
|
|
|
|
case OPC_JMP:
|
|
if (((instr & (MOD_IN | MOD_I1 | MOD_I2)) == MOD_IN) & !dbg) {
|
|
if (disEffectiveAddr(addr, instr & ~MOD_IN, &base, &taddr) == SCPE_OK) {
|
|
taddr2 = taddr;
|
|
indJmp = TRUE;
|
|
if (((instr & MOD_RE) != 0) && ((sim_switches & SWMASK('R')) != 0)) {
|
|
taddr2 -= RelBase;
|
|
rel = "*";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
/* FALLTHROUGH */
|
|
|
|
case OPC_RTJ:
|
|
if (((instr & (MOD_IN | MOD_I1 | MOD_I2)) != 0) & !dbg)
|
|
break;
|
|
|
|
if (disEffectiveAddr(addr, instr, &base, &taddr) == SCPE_OK) {
|
|
more = cpu_dev.dctrl & DBG_FULL ? 2 : 1;
|
|
taddr2 = taddr;
|
|
if (((instr & (MOD_RE | MOD_IN | MOD_I1 | MOD_I2)) == MOD_RE) &&
|
|
((sim_switches & SWMASK('R')) != 0)) {
|
|
taddr2 -= RelBase;
|
|
rel = "*";
|
|
}
|
|
}
|
|
break;
|
|
|
|
case OPC_SPECIAL:
|
|
switch (instr & OPC_SPECIALMASK) {
|
|
case OPC_SLS:
|
|
break;
|
|
|
|
case OPC_SKIPS:
|
|
taddr = doADDinternal(MEMADDR(addr + 1), instr & OPC_SKIPCOUNT);
|
|
taddr2 = taddr;
|
|
if ((sim_switches & SWMASK('R')) != 0)
|
|
taddr2 -= RelBase;
|
|
more = 1;
|
|
break;
|
|
|
|
case OPC_SPB:
|
|
case OPC_CPB:
|
|
if (exec) {
|
|
taddr = Qreg;
|
|
taddr2 = taddr;
|
|
if ((sim_switches & SWMASK('R')) != 0)
|
|
taddr2 -= RelBase;
|
|
more = 1;
|
|
}
|
|
break;
|
|
|
|
case OPC_INP:
|
|
case OPC_OUT:
|
|
taddr = doADDinternal(addr, EXTEND8(instr & OPC_MODMASK));
|
|
taddr2 = taddr;
|
|
if ((sim_switches & SWMASK('R')) != 0)
|
|
taddr2 -= RelBase;
|
|
more = 1;
|
|
break;
|
|
|
|
case OPC_EIN:
|
|
case OPC_IIN:
|
|
case OPC_INTER:
|
|
case OPC_INA:
|
|
case OPC_ENA:
|
|
case OPC_NOP:
|
|
case OPC_ENQ:
|
|
case OPC_INQ:
|
|
case OPC_EXI:
|
|
case OPC_SHIFTS:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (more || indJmp) {
|
|
int i, count = 48 - strlen(buf);
|
|
|
|
for (i = 0; i < count; i++)
|
|
strcat(buf, " ");
|
|
|
|
buf += strlen(buf);
|
|
if (indJmp) {
|
|
sprintf(buf, "[ => (%04X%s)", taddr2, rel);
|
|
} else {
|
|
switch (more) {
|
|
case 1:
|
|
sprintf(buf, "[ => %04X%s %s {%04X}", taddr2, rel,
|
|
P[MEMADDR(taddr)] ? "(P)" : "",
|
|
LoadFromMem(taddr));
|
|
break;
|
|
|
|
case 2:
|
|
sprintf(buf, "[ => %04X%s (B:%04X%s) %s {%04X}",
|
|
taddr2, rel, base, rel,
|
|
P[MEMADDR(taddr)] ? "(P)" : "",
|
|
LoadFromMem(taddr));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return consumed;
|
|
}
|