/* vax_sys.c: VAX simulator interface | |
Copyright (c) 1998-2011, Robert M Supnik | |
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 | |
ROBERT M SUPNIK 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 Robert M Supnik shall not be | |
used in advertising or otherwise to promote the sale, use or other dealings | |
in this Software without prior written authorization from Robert M Supnik. | |
21-Mar-11 RMS Modified string for STOP_BOOT message | |
19-Nov-08 RMS Moved bad block routine to I/O library | |
03-Nov-05 RMS Added 780 stop codes | |
04-Sep-05 RMS Fixed missing assignment (Peter Schorn) | |
16-Aug-05 RMS Fixed C++ declaration and cast problems | |
15-Sep-04 RMS Fixed bugs in character display and parse | |
30-Sep-04 RMS Fixed bugs in parsing indirect displacement modes | |
Added compatibility mode support | |
04-Sep-04 RMS Added octa instruction support | |
02-Sep-04 RMS Fixed parse branch return status | |
13-Jul-04 RMS Fixed bad block routine | |
16-Jun-04 RMS Added DHQ11 support | |
21-Mar-04 RMS Added RXV21 support | |
06-May-03 RMS Added support for second DELQA | |
12-Oct-02 RMS Added multiple RQ controller support | |
10-Oct-02 RMS Added DELQA support | |
21-Sep-02 RMS Extended symbolic ex/mod to all byte devices | |
06-Sep-02 RMS Added TMSCP support | |
14-Jul-02 RMS Added infinite loop message | |
*/ | |
#include "vax_defs.h" | |
#include <ctype.h> | |
#if defined (FULL_VAX) | |
#define ODC(x) (x) | |
#else | |
#define ODC(x) ((x) << DR_V_USPMASK) | |
#endif | |
extern REG cpu_reg[]; | |
t_stat fprint_sym_m (FILE *of, uint32 addr, t_value *val); | |
int32 fprint_sym_qoimm (FILE *of, t_value *val, int32 vp, int32 lnt); | |
t_stat parse_char (char *cptr, t_value *val, int32 lnt); | |
t_stat parse_sym_m (char *cptr, uint32 addr, t_value *val); | |
int32 parse_brdisp (char *cptr, uint32 addr, t_value *val, | |
int32 vp, int32 lnt, t_stat *r); | |
int32 parse_spec (char *cptr, uint32 addr, t_value *val, | |
int32 vp, int32 disp, t_stat *r); | |
char *parse_rnum (char *cptr, int32 *rn); | |
int32 parse_sym_qoimm (int32 *lit, t_value *val, int32 vp, | |
int lnt, int32 minus); | |
extern t_stat fprint_sym_cm (FILE *of, t_addr addr, t_value *bytes, int32 sw); | |
extern t_stat parse_sym_cm (char *cptr, t_addr addr, t_value *bytes, int32 sw); | |
/* SCP data structures and interface routines | |
sim_name simulator name string | |
sim_PC pointer to saved PC register descriptor | |
sim_emax number of words for examine | |
sim_devices array of pointers to simulated devices | |
sim_stop_messages array of pointers to stop messages | |
sim_load binary loader | |
*/ | |
REG *sim_PC = &cpu_reg[0]; | |
int32 sim_emax = 60; | |
const char *sim_stop_messages[] = { | |
"Unknown error", | |
"HALT instruction", | |
"Breakpoint", | |
"CHMx on interrupt stack", | |
"Invalid SCB vector", | |
"Exception in interrupt or exception", | |
"Process PTE in P0 or P1 space", | |
"Interrupt at undefined IPL", | |
"Fatal RQDX3 error", | |
"Infinite loop", | |
"Sanity timer expired", | |
"Software done", | |
"Reboot request failed", | |
"Unknown error", | |
"Unknown abort code", | |
"DECtape off reel" | |
}; | |
/* Dispatch/decoder table | |
The first entry contains: | |
- FPD legal flag (DR_F) | |
- number of specifiers for decode bits 2:0> | |
- number of specifiers for unimplemented instructions bits<6:4> | |
- ONLY for simulator instruction history bits 11:8 reflect where | |
results are recorded from | |
*/ | |
const uint16 drom[NUM_INST][MAX_SPEC + 1] = { | |
{0, 0, 0, 0, 0, 0, 0}, /* HALT */ | |
{0, 0, 0, 0, 0, 0, 0}, /* NOP */ | |
{0, 0, 0, 0, 0, 0, 0}, /* REI */ | |
{0, 0, 0, 0, 0, 0, 0}, /* BPT */ | |
{0, 0, 0, 0, 0, 0, 0}, /* RET */ | |
{0, 0, 0, 0, 0, 0, 0}, /* RSB */ | |
{0, 0, 0, 0, 0, 0, 0}, /* LDPCTX */ | |
{0, 0, 0, 0, 0, 0, 0}, /* SVPCTX */ | |
{4+DR_F, RW, AB, RW, AB, 0, 0}, /* CVTPS */ | |
{4+DR_F, RW, AB, RW, AB, 0, 0}, /* CVTSP */ | |
{6 +RB_L, RL, RL, RL, RL, RL, WL}, /* INDEX */ | |
{4+DR_F +RB_L, AB, RL, RW, AB, 0, 0}, /* CRC */ | |
{3, RB, RW, AB, 0, 0, 0}, /* PROBER */ | |
{3, RB, RW, AB, 0, 0, 0}, /* PROBEW */ | |
{2, AB, AB, 0, 0, 0, 0}, /* INSQUE */ | |
{2, AB, WL, 0, 0, 0, 0}, /* REMQUE */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BSBB */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BRB */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BNEQ */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BEQL */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BGTR */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BLEQ */ | |
{1, AB, 0, 0, 0, 0, 0}, /* JSB */ | |
{1, AB, 0, 0, 0, 0, 0}, /* JMP */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BGEQ */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BLSS */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BGTRU */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BLEQU */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BVC */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BVS */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BCC */ | |
{1, BB, 0, 0, 0, 0, 0}, /* BCS */ | |
{4+DR_F +RB_R3, RW, AB, RW, AB, 0, 0}, /* ADDP4 */ | |
{6+DR_F +RB_R5, RW, AB, RW, AB, RW, AB}, /* ADDP6 */ | |
{4+DR_F +RB_R3, RW, AB, RW, AB, 0, 0}, /* SUBP4 */ | |
{6+DR_F +RB_R5, RW, AB, RW, AB, RW, AB}, /* SUBP6 */ | |
{5+DR_F +RB_R3, RW, AB, AB, RW, AB, 0}, /* CVTPT */ | |
{6+DR_F +RB_R5, RW, AB, RW, AB, RW, AB}, /* MULP6 */ | |
{5+DR_F +RB_R3, RW, AB, AB, RW, AB, 0}, /* CVTTP */ | |
{6+DR_F +RB_R5, RW, AB, RW, AB, RW, AB}, /* DIVP6 */ | |
{3+DR_F +RB_R5, RW, AB, AB, 0, 0, 0}, /* MOVC3 */ | |
{3+DR_F +RB_R3, RW, AB, AB, 0, 0, 0}, /* CMPC3 */ | |
{4+DR_F +RB_R3, RW, AB, AB, RB, 0, 0}, /* SCANC */ | |
{4+DR_F +RB_R3, RW, AB, AB, RB, 0, 0}, /* SPANC */ | |
{5+DR_F +RB_R5, RW, AB, RB, RW, AB, 0}, /* MOVC5 */ | |
{5+DR_F +RB_R3, RW, AB, RB, RW, AB, 0}, /* CMPC5 */ | |
{6+DR_F +RB_R5, RW, AB, RB, AB, RW, AB}, /* MOVTC */ | |
{6+DR_F +RB_R3, RW, AB, RB, AB, RW, AB}, /* MOVTUC */ | |
{1, BW, 0, 0, 0, 0, 0}, /* BSBW */ | |
{1, BW, 0, 0, 0, 0, 0}, /* BRW */ | |
{2 +RB_L, RW, WL, 0, 0, 0, 0}, /* CVTWL */ | |
{2 +RB_B, RW, WB, 0, 0, 0, 0}, /* CVTWB */ | |
{3+DR_F +RB_R3, RW, AB, AB, 0, 0, 0}, /* MOVP */ | |
{3+DR_F +RB_R3, RW, AB, AB, 0, 0, 0}, /* CMPP3 */ | |
{3+DR_F +RB_L, RW, AB, WL, 0, 0, 0}, /* CVTPL */ | |
{4+DR_F +RB_R3, RW, AB, RW, AB, 0, 0}, /* CMPP4 */ | |
{4+DR_F +RB_R5, RW, AB, AB, AB, 0, 0}, /* EDITPC */ | |
{4+DR_F +RB_R3, RW, AB, RW, AB, 0, 0}, /* MATCHC */ | |
{3+DR_F +RB_R1, RB, RW, AB, 0, 0, 0}, /* LOCC */ | |
{3+DR_F +RB_R1, RB, RW, AB, 0, 0, 0}, /* SKPC */ | |
{2 +RB_L, RW, WL, 0, 0, 0, 0}, /* MOVZWL */ | |
{4, RW, RW, MW, BW, 0, 0}, /* ACBW */ | |
{2, AW, WL, 0, 0, 0, 0}, /* MOVAW */ | |
{1 +RB_SP, AW, 0, 0, 0, 0, 0}, /* PUSHAW */ | |
{2 +RB_L, RF, ML, 0, 0, 0, 0}, /* ADDF2 */ | |
{3 +RB_L, RF, RF, WL, 0, 0, 0}, /* ADDF3 */ | |
{2 +RB_L, RF, ML, 0, 0, 0, 0}, /* SUBF2 */ | |
{3 +RB_L, RF, RF, WL, 0, 0, 0}, /* SUBF3 */ | |
{2 +RB_L, RF, ML, 0, 0, 0, 0}, /* MULF2 */ | |
{3 +RB_L, RF, RF, WL, 0, 0, 0}, /* MULF3 */ | |
{2 +RB_L, RF, ML, 0, 0, 0, 0}, /* DIVF2 */ | |
{3 +RB_L, RF, RF, WL, 0, 0, 0}, /* DIVF3 */ | |
{2 +RB_B, RF, WB, 0, 0, 0, 0}, /* CVTFB */ | |
{2 +RB_W, RF, WW, 0, 0, 0, 0}, /* CVTFW */ | |
{2 +RB_L, RF, WL, 0, 0, 0, 0}, /* CVTFL */ | |
{2 +RB_L, RF, WL, 0, 0, 0, 0}, /* CVTRFL */ | |
{2 +RB_L, RB, WL, 0, 0, 0, 0}, /* CVTBF */ | |
{2 +RB_L, RW, WL, 0, 0, 0, 0}, /* CVTWF */ | |
{2 +RB_L, RL, WL, 0, 0, 0, 0}, /* CVTLF */ | |
{4, RF, RF, ML, BW, 0, 0}, /* ACBF */ | |
{2 +RB_L, RF, WL, 0, 0, 0, 0}, /* MOVF */ | |
{2, RF, RF, 0, 0, 0, 0}, /* CMPF */ | |
{2 +RB_L, RF, WL, 0, 0, 0, 0}, /* MNEGF */ | |
{1, RF, 0, 0, 0, 0, 0}, /* TSTF */ | |
{5, RF, RB, RF, WL, WL, 0}, /* EMODF */ | |
{3 +RB_R0, RF, RW, AB, 0, 0, 0}, /* POLYF */ | |
{2 +RB_Q, RF, WQ, 0, 0, 0, 0}, /* CVTFD */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{2 +RB_W, RW, WW, 0, 0, 0, 0}, /* ADAWI */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{2, AB, AQ, 0, 0, 0, 0}, /* INSQHI */ | |
{2, AB, AQ, 0, 0, 0, 0}, /* INSQTI */ | |
{2, AQ, WL, 0, 0, 0, 0}, /* REMQHI */ | |
{2, AQ, WL, 0, 0, 0, 0}, /* REMQTI */ | |
{2 +RB_Q, RD, MQ, 0, 0, 0, 0}, /* ADDD2 */ | |
{3 +RB_Q, RD, RD, WQ, 0, 0, 0}, /* ADDD3 */ | |
{2 +RB_Q, RD, MQ, 0, 0, 0, 0}, /* SUBD2 */ | |
{3 +RB_Q, RD, RD, WQ, 0, 0, 0}, /* SUBD3 */ | |
{2 +RB_Q, RD, MQ, 0, 0, 0, 0}, /* MULD2 */ | |
{3 +RB_Q, RD, RD, WQ, 0, 0, 0}, /* MULD3 */ | |
{2 +RB_Q, RD, MQ, 0, 0, 0, 0}, /* DIVD2 */ | |
{3 +RB_Q, RD, RD, WQ, 0, 0, 0}, /* DIVD3 */ | |
{2 +RB_B, RD, WB, 0, 0, 0, 0}, /* CVTDB */ | |
{2 +RB_W, RD, WW, 0, 0, 0, 0}, /* CVTDW */ | |
{2 +RB_L, RD, WL, 0, 0, 0, 0}, /* CVTDL */ | |
{2 +RB_L, RD, WL, 0, 0, 0, 0}, /* CVTRDL */ | |
{2 +RB_Q, RB, WQ, 0, 0, 0, 0}, /* CVTBD */ | |
{2 +RB_Q, RW, WQ, 0, 0, 0, 0}, /* CVTWD */ | |
{2 +RB_Q, RL, WQ, 0, 0, 0, 0}, /* CVTLD */ | |
{4, RD, RD, MQ, BW, 0, 0}, /* ACBD */ | |
{2 +RB_Q, RD, WQ, 0, 0, 0, 0}, /* MOVD */ | |
{2 +RB_Q, RD, RD, 0, 0, 0, 0}, /* CMPD */ | |
{2 +RB_Q, RD, WQ, 0, 0, 0, 0}, /* MNEGD */ | |
{1, RD, 0, 0, 0, 0, 0}, /* TSTD */ | |
{5, RD, RB, RD, WL, WQ, 0}, /* EMODD */ | |
{3 +RB_R1, RD, RW, AB, 0, 0, 0}, /* POLYD */ | |
{2 +RB_L, RD, WL, 0, 0, 0, 0}, /* CVTDF */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{3 +RB_L, RB, RL, WL, 0, 0, 0}, /* ASHL */ | |
{3 +RB_Q, RB, RQ, WQ, 0, 0, 0}, /* ASHQ */ | |
{4, RL, RL, RL, WQ, 0, 0}, /* EMUL */ | |
{4, RL, RQ, WL, WL, 0, 0}, /* EDIV */ | |
{1 +RB_Q, WQ, 0, 0, 0, 0, 0}, /* CLRQ */ | |
{2 +RB_Q, RQ, WQ, 0, 0, 0, 0}, /* MOVQ */ | |
{2 +RB_L, AQ, WL, 0, 0, 0, 0}, /* MOVAQ */ | |
{1 +RB_SP, AQ, 0, 0, 0, 0, 0}, /* PUSHAQ */ | |
{2 +RB_B, RB, MB, 0, 0, 0, 0}, /* ADDB2 */ | |
{3 +RB_B, RB, RB, WB, 0, 0, 0}, /* ADDB3 */ | |
{2 +RB_B, RB, MB, 0, 0, 0, 0}, /* SUBB2 */ | |
{3 +RB_B, RB, RB, WB, 0, 0, 0}, /* SUBB3 */ | |
{2 +RB_B, RB, MB, 0, 0, 0, 0}, /* MULB2 */ | |
{3 +RB_B, RB, RB, WB, 0, 0, 0}, /* MULB3 */ | |
{2 +RB_B, RB, MB, 0, 0, 0, 0}, /* DIVB2 */ | |
{3 +RB_B, RB, RB, WB, 0, 0, 0}, /* DIVB3 */ | |
{2 +RB_B, RB, MB, 0, 0, 0, 0}, /* BISB2 */ | |
{3 +RB_B, RB, RB, WB, 0, 0, 0}, /* BISB3 */ | |
{2 +RB_B, RB, MB, 0, 0, 0, 0}, /* BICB2 */ | |
{3 +RB_B, RB, RB, WB, 0, 0, 0}, /* BICB3 */ | |
{2 +RB_B, RB, MB, 0, 0, 0, 0}, /* XORB2 */ | |
{3 +RB_B, RB, RB, WB, 0, 0, 0}, /* XORB3 */ | |
{2 +RB_B, RB, WB, 0, 0, 0, 0}, /* MNEGB */ | |
{3, RB, RB, RB, 0, 0, 0}, /* CASEB */ | |
{2 +RB_B, RB, WB, 0, 0, 0, 0}, /* MOVB */ | |
{2, RB, RB, 0, 0, 0, 0}, /* CMPB */ | |
{2 +RB_B, RB, WB, 0, 0, 0, 0}, /* MCOMB */ | |
{2 +RB_B, RB, RB, 0, 0, 0, 0}, /* BITB */ | |
{1 +RB_B, WB, 0, 0, 0, 0, 0}, /* CLRB */ | |
{1, RB, 0, 0, 0, 0, 0}, /* TSTB */ | |
{1 +RB_B, MB, 0, 0, 0, 0, 0}, /* INCB */ | |
{1 +RB_B, MB, 0, 0, 0, 0, 0}, /* DECB */ | |
{2 +RB_L, RB, WL, 0, 0, 0, 0}, /* CVTBL */ | |
{2 +RB_W, RB, WW, 0, 0, 0, 0}, /* CVTBW */ | |
{2 +RB_L, RB, WL, 0, 0, 0, 0}, /* MOVZBL */ | |
{2 +RB_W, RB, WW, 0, 0, 0, 0}, /* MOVZBW */ | |
{3 +RB_L, RB, RL, WL, 0, 0, 0}, /* ROTL */ | |
{4, RB, RB, MB, BW, 0, 0}, /* ACBB */ | |
{2 +RB_L, AB, WL, 0, 0, 0, 0}, /* MOVAB */ | |
{1 +RB_SP, AB, 0, 0, 0, 0, 0}, /* PUSHAB */ | |
{2 +RB_W, RW, MW, 0, 0, 0, 0}, /* ADDW2 */ | |
{3 +RB_W, RW, RW, WW, 0, 0, 0}, /* ADDW3 */ | |
{2 +RB_W, RW, MW, 0, 0, 0, 0}, /* SUBW2 */ | |
{3 +RB_W, RW, RW, WW, 0, 0, 0}, /* SUBW3 */ | |
{2 +RB_W, RW, MW, 0, 0, 0, 0}, /* MULW2 */ | |
{3 +RB_W, RW, RW, WW, 0, 0, 0}, /* MULW3 */ | |
{2 +RB_W, RW, MW, 0, 0, 0, 0}, /* DIVW2 */ | |
{3 +RB_W, RW, RW, WW, 0, 0, 0}, /* DIVW3 */ | |
{2 +RB_W, RW, MW, 0, 0, 0, 0}, /* BISW2 */ | |
{3 +RB_W, RW, RW, WW, 0, 0, 0}, /* BISW3 */ | |
{2 +RB_W, RW, MW, 0, 0, 0, 0}, /* BICW2 */ | |
{3 +RB_W, RW, RW, WW, 0, 0, 0}, /* BICW3 */ | |
{2 +RB_W, RW, MW, 0, 0, 0, 0}, /* XORW2 */ | |
{3 +RB_W, RW, RW, WW, 0, 0, 0}, /* XORW3 */ | |
{2 +RB_W, RW, WW, 0, 0, 0, 0}, /* MNEGW */ | |
{3, RW, RW, RW, 0, 0, 0}, /* CASEW */ | |
{2 +RB_W, RW, WW, 0, 0, 0, 0}, /* MOVW */ | |
{2, RW, RW, 0, 0, 0, 0}, /* CMPW */ | |
{2 +RB_W, RW, WW, 0, 0, 0, 0}, /* MCOMW */ | |
{2, RW, RW, 0, 0, 0, 0}, /* BITW */ | |
{1 +RB_W, WW, 0, 0, 0, 0, 0}, /* CLRW */ | |
{1, RW, 0, 0, 0, 0, 0}, /* TSTW */ | |
{1 +RB_W, MW, 0, 0, 0, 0, 0}, /* INCW */ | |
{1 +RB_W, MW, 0, 0, 0, 0, 0}, /* DECW */ | |
{1, RW, 0, 0, 0, 0, 0}, /* BISPSW */ | |
{1, RW, 0, 0, 0, 0, 0}, /* BICPSW */ | |
{1, RW, 0, 0, 0, 0, 0}, /* POPR */ | |
{1, RW, 0, 0, 0, 0, 0}, /* PUSHR */ | |
{1, RW, 0, 0, 0, 0, 0}, /* CHMK */ | |
{1, RW, 0, 0, 0, 0, 0}, /* CHME */ | |
{1, RW, 0, 0, 0, 0, 0}, /* CHMS */ | |
{1, RW, 0, 0, 0, 0, 0}, /* CHMU */ | |
{2 +RB_L, RL, ML, 0, 0, 0, 0}, /* ADDL2 */ | |
{3 +RB_L, RL, RL, WL, 0, 0, 0}, /* ADDL3 */ | |
{2 +RB_L, RL, ML, 0, 0, 0, 0}, /* SUBL2 */ | |
{3 +RB_L, RL, RL, WL, 0, 0, 0}, /* SUBL3 */ | |
{2 +RB_L, RL, ML, 0, 0, 0, 0}, /* MULL2 */ | |
{3 +RB_L, RL, RL, WL, 0, 0, 0}, /* MULL3 */ | |
{2 +RB_L, RL, ML, 0, 0, 0, 0}, /* DIVL2 */ | |
{3 +RB_L, RL, RL, WL, 0, 0, 0}, /* DIVL3 */ | |
{2 +RB_L, RL, ML, 0, 0, 0, 0}, /* BISL2 */ | |
{3 +RB_L, RL, RL, WL, 0, 0, 0}, /* BISL3 */ | |
{2 +RB_L, RL, ML, 0, 0, 0, 0}, /* BICL2 */ | |
{3 +RB_L, RL, RL, WL, 0, 0, 0}, /* BICL3 */ | |
{2 +RB_L, RL, ML, 0, 0, 0, 0}, /* XORL2 */ | |
{3 +RB_L, RL, RL, WL, 0, 0, 0}, /* XORL3 */ | |
{2 +RB_L, RL, WL, 0, 0, 0, 0}, /* MNEGL */ | |
{3, RL, RL, RL, 0, 0, 0}, /* CASEL */ | |
{2 +RB_L, RL, WL, 0, 0, 0, 0}, /* MOVL */ | |
{2, RL, RL, 0, 0, 0, 0}, /* CMPL */ | |
{2 +RB_L, RL, WL, 0, 0, 0, 0}, /* MCOML */ | |
{2, RL, RL, 0, 0, 0, 0}, /* BITL */ | |
{1 +RB_L, WL, 0, 0, 0, 0, 0}, /* CLRL */ | |
{1, RL, 0, 0, 0, 0, 0}, /* TSTL */ | |
{1 +RB_L, ML, 0, 0, 0, 0, 0}, /* INCL */ | |
{1 +RB_L, ML, 0, 0, 0, 0, 0}, /* DECL */ | |
{2 +RB_L, RL, ML, 0, 0, 0, 0}, /* ADWC */ | |
{2 +RB_L, RL, ML, 0, 0, 0, 0}, /* SBWC */ | |
{2, RL, RL, 0, 0, 0, 0}, /* MTPR */ | |
{2 +RB_L, RL, WL, 0, 0, 0, 0}, /* MFPR */ | |
{1 +RB_L, WL, 0, 0, 0, 0, 0}, /* MOVPSL */ | |
{1 +RB_SP, RL, 0, 0, 0, 0, 0}, /* PUSHL */ | |
{2 +RB_L, AL, WL, 0, 0, 0, 0}, /* MOVAL */ | |
{1 +RB_SP, AL, 0, 0, 0, 0, 0}, /* PUSHAL */ | |
{3, RL, VB, BB, 0, 0, 0}, /* BBS */ | |
{3, RL, VB, BB, 0, 0, 0}, /* BBC */ | |
{3, RL, VB, BB, 0, 0, 0}, /* BBSS */ | |
{3, RL, VB, BB, 0, 0, 0}, /* BBCS */ | |
{3, RL, VB, BB, 0, 0, 0}, /* BBSC */ | |
{3, RL, VB, BB, 0, 0, 0}, /* BBCC */ | |
{3, RL, VB, BB, 0, 0, 0}, /* BBSSI */ | |
{3, RL, VB, BB, 0, 0, 0}, /* BBCCI */ | |
{2, RL, BB, 0, 0, 0, 0}, /* BLBS */ | |
{2, RL, BB, 0, 0, 0, 0}, /* BLBC */ | |
{4 +RB_L, RL, RB, VB, WL, 0, 0}, /* FFS */ | |
{4 +RB_L, RL, RB, VB, WL, 0, 0}, /* FFC */ | |
{4, RL, RB, VB, RL, 0, 0}, /* CMPV */ | |
{4, RL, RB, VB, RL, 0, 0}, /* CMPZV */ | |
{4 +RB_L, RL, RB, VB, WL, 0, 0}, /* EXTV */ | |
{4 +RB_L, RL, RB, VB, WL, 0, 0}, /* EXTZV */ | |
{4, RL, RL, RB, VB, 0, 0}, /* INSV */ | |
{4, RL, RL, ML, BW, 0, 0}, /* ACBL */ | |
{3, RL, ML, BB, 0, 0, 0}, /* AOBLSS */ | |
{3, RL, ML, BB, 0, 0, 0}, /* AOBLEQ */ | |
{2, ML, BB, 0, 0, 0, 0}, /* SOBGEQ */ | |
{2, ML, BB, 0, 0, 0, 0}, /* SOBGTR */ | |
{2 +RB_B, RL, WB, 0, 0, 0, 0}, /* CVTLB */ | |
{2 +RB_W, RL, WW, 0, 0, 0, 0}, /* CVTLW */ | |
{6+DR_F+RB_R3, RB, RW, AB, RB, RW, AB}, /* ASHP */ | |
{3+DR_F+RB_R3, RL, RW, AB, 0, 0, 0}, /* CVTLP */ | |
{2, AB, AB, 0, 0, 0, 0}, /* CALLG */ | |
{2, RL, AB, 0, 0, 0, 0}, /* CALLS */ | |
{0, 0, 0, 0, 0, 0, 0}, /* XFC */ | |
{0, 0, 0, 0, 0, 0, 0}, /* 0FD */ | |
{0, 0, 0, 0, 0, 0, 0}, /* 0FE */ | |
{0, 0, 0, 0, 0, 0, 0}, /* 0FF */ | |
{0, 0, 0, 0, 0, 0, 0}, /* 100-10F */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, /* 110-11F */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, /* 120-12F */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, /* 130-13F */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{ODC(2) +RB_O, RD, WO, 0, 0, 0, 0}, /* CVTDH */ | |
{2 +RB_L, RG, WL, 0, 0, 0, 0}, /* CVTGF */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{2 +RB_Q, RG, MQ, 0, 0, 0, 0}, /* ADDG2 */ | |
{3 +RB_Q, RG, RG, WQ, 0, 0, 0}, /* ADDG3 */ | |
{2 +RB_Q, RG, MQ, 0, 0, 0, 0}, /* SUBG2 */ | |
{3 +RB_Q, RG, RG, WQ, 0, 0, 0}, /* SUBG3 */ | |
{2 +RB_Q, RG, MQ, 0, 0, 0, 0}, /* MULG2 */ | |
{3 +RB_Q, RG, RG, WQ, 0, 0, 0}, /* MULG3 */ | |
{2 +RB_Q, RG, MQ, 0, 0, 0, 0}, /* DIVG2 */ | |
{3 +RB_Q, RG, RG, WQ, 0, 0, 0}, /* DIVG3 */ | |
{2 +RB_B, RG, WB, 0, 0, 0, 0}, /* CVTGB */ | |
{2 +RB_W, RG, WW, 0, 0, 0, 0}, /* CVTGW */ | |
{2 +RB_L, RG, WL, 0, 0, 0, 0}, /* CVTGL */ | |
{2 +RB_L, RG, WL, 0, 0, 0, 0}, /* CVTRGL */ | |
{2 +RB_Q, RB, WQ, 0, 0, 0, 0}, /* CVTBG */ | |
{2 +RB_Q, RW, WQ, 0, 0, 0, 0}, /* CVTWG */ | |
{2 +RB_Q, RL, WQ, 0, 0, 0, 0}, /* CVTLG */ | |
{4, RG, RG, MQ, BW, 0, 0}, /* ACBG */ | |
{2 +RB_Q, RG, WQ, 0, 0, 0, 0}, /* MOVG */ | |
{2, RG, RG, 0, 0, 0, 0}, /* CMPG */ | |
{2 +RB_Q, RG, WQ, 0, 0, 0, 0}, /* MNEGG */ | |
{1, RG, 0, 0, 0, 0, 0}, /* TSTG */ | |
{5, RG, RW, RG, WL, WQ, 0}, /* EMODG */ | |
{3 +RB_R1, RG, RW, AB, 0, 0, 0}, /* POLYG */ | |
{ODC(2) +RB_O, RG, WO, 0, 0, 0, 0}, /* CVTGH */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{ODC(2) +RB_O, RH, MO, 0, 0, 0, 0}, /* ADDH2 */ | |
{ODC(3) +RB_O, RH, RH, WO, 0, 0, 0}, /* ADDH3 */ | |
{ODC(2) +RB_O, RH, MO, 0, 0, 0, 0}, /* SUBH2 */ | |
{ODC(3) +RB_O, RH, RH, WO, 0, 0, 0}, /* SUBH3 */ | |
{ODC(2) +RB_O, RH, MO, 0, 0, 0, 0}, /* MULH2 */ | |
{ODC(3) +RB_O, RH, RH, WO, 0, 0, 0}, /* MULH3 */ | |
{ODC(2) +RB_O, RH, MO, 0, 0, 0, 0}, /* DIVH2 */ | |
{ODC(3) +RB_O, RH, RH, WO, 0, 0, 0}, /* DIVH3 */ | |
{ODC(2) +RB_B, RH, WB, 0, 0, 0, 0}, /* CVTHB */ | |
{ODC(2) +RB_W, RH, WW, 0, 0, 0, 0}, /* CVTHW */ | |
{ODC(2) +RB_L, RH, WL, 0, 0, 0, 0}, /* CVTHL */ | |
{ODC(2) +RB_O, RH, WL, 0, 0, 0, 0}, /* CVTRHL */ | |
{ODC(2) +RB_O, RB, WO, 0, 0, 0, 0}, /* CVTBH */ | |
{ODC(2) +RB_O, RW, WO, 0, 0, 0, 0}, /* CVTWH */ | |
{ODC(2) +RB_O, RL, WO, 0, 0, 0, 0}, /* CVTLH */ | |
{ODC(4), RH, RH, MO, BW, 0, 0}, /* ACBH */ | |
{ODC(2) +RB_O, RH, RO, 0, 0, 0, 0}, /* MOVH */ | |
{ODC(2), RH, RH, 0, 0, 0, 0}, /* CMPH */ | |
{ODC(2) +RB_O, RH, WO, 0, 0, 0, 0}, /* MNEGH */ | |
{ODC(1), RH, 0, 0, 0, 0, 0}, /* TSTH */ | |
{ODC(5), RH, RW, RH, WL, WO, 0}, /* EMODH */ | |
{ODC(3) +RB_R3, RH, RW, AB, 0, 0, 0}, /* POLYH */ | |
{ODC(2) +RB_Q, RH, WQ, 0, 0, 0, 0}, /* CVTHG */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{0, 0, 0, 0, 0, 0, 0}, /* reserved */ | |
{ODC(1) +RB_O, WO, 0, 0, 0, 0, 0}, /* CLRO */ | |
{ODC(2) +RB_O, RO, RO, 0, 0, 0, 0}, /* MOVO */ | |
{ODC(2) +RB_L, AO, WL, 0, 0, 0, 0}, /* MOVAO*/ | |
{ODC(1) +RB_SP, AO, 0, 0, 0, 0, 0}, /* PUSHAO*/ | |
{0, 0, 0, 0, 0, 0, 0}, /* 180-18F */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, /* 190-19F */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{ODC(2) +RB_O, RF, WO, 0, 0, 0, 0}, /* CVTFH */ | |
{2 +RB_Q, RF, WQ, 0, 0, 0, 0}, /* CVTFG */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, /* 1A0-1AF */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, /* 1B0-1BF */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, /* 1C0-1CF */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, /* 1D0-1DF */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, /* 1E0-1EF */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, /* 1F0-1FF */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{ODC(2) +RB_B, RH, WL, 0, 0, 0, 0}, /* CVTHF */ | |
{ODC(2) +RB_Q, RH, WQ, 0, 0, 0, 0}, /* CVTHD */ | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0}, | |
{0, 0, 0, 0, 0, 0, 0} | |
}; | |
/* Opcode mnemonics table */ | |
const char *opcode[] = { | |
"HALT", "NOP", "REI", "BPT", "RET", "RSB", "LDPCTX", "SVPCTX", | |
"CVTPS", "CVTSP", "INDEX", "CRC", "PROBER", "PROBEW", "INSQUE", "REMQUE", | |
"BSBB", "BRB", "BNEQ", "BEQL", "BGTR", "BLEQ", "JSB", "JMP", | |
"BGEQ", "BLSS", "BGTRU", "BLEQU", "BVC", "BVS", "BGEQU", "BLSSU", | |
"ADDP4", "ADDP6", "SUBP4", "SUBP6", "CVTPT", "MULP", "CVTTP", "DIVP", | |
"MOVC3", "CMPC3", "SCANC", "SPANC", "MOVC5", "CMPC5", "MOVTC", "MOVTUC", | |
"BSBW", "BRW", "CVTWL", "CVTWB", "MOVP", "CMPP3", "CVTPL", "CMPP4", | |
"EDITPC", "MATCHC", "LOCC", "SKPC", "MOVZWL", "ACBW", "MOVAW", "PUSHAW", | |
"ADDF2", "ADDF3", "SUBF2", "SUBF3", "MULF2", "MULF3", "DIVF2", "DIVF3", | |
"CVTFB", "CVTFW", "CVTFL", "CVTRFL", "CVTBF", "CVTWF", "CVTLF", "ACBF", | |
"MOVF", "CMPF", "MNEGF", "TSTF", "EMODF", "POLYF", "CVTFD", NULL, | |
"ADAWI", NULL, NULL, NULL, "INSQHI", "INSQTI", "REMQHI", "REMQTI", | |
"ADDD2", "ADDD3", "SUBD2", "SUBD3", "MULD2", "MULD3", "DIVD2", "DIVD3", | |
"CVTDB", "CVTDW", "CVTDL", "CVTRDL", "CVTBD", "CVTWD", "CVTLD", "ACBD", | |
"MOVD", "CMPD", "MNEGD", "TSTD", "EMODD", "POLYD", "CVTDF", NULL, | |
"ASHL", "ASHQ", "EMUL", "EDIV", "CLRQ", "MOVQ", "MOVAQ", "PUSHAQ", | |
"ADDB2", "ADDB3", "SUBB2", "SUBB3", "MULB2", "MULB3", "DIVB2", "DIVB3", | |
"BISB2", "BISB3", "BICB2", "BICB3", "XORB2", "XORB3", "MNEGB", "CASEB", | |
"MOVB", "CMPB", "MCOMB", "BITB", "CLRB", "TSTB", "INCB", "DECB", | |
"CVTBL", "CVTBW", "MOVZBL", "MOVZBW", "ROTL", "ACBB", "MOVAB", "PUSHAB", | |
"ADDW2", "ADDW3", "SUBW2", "SUBW3", "MULW2", "MULW3", "DIVW2", "DIVW3", | |
"BISW2", "BISW3", "BICW2", "BICW3", "XORW2", "XORW3", "MNEGW", "CASEW", | |
"MOVW", "CMPW", "MCOMW", "BITW", "CLRW", "TSTW", "INCW", "DECW", | |
"BISPSW", "BICPSW", "POPR", "PUSHR", "CHMK", "CHME", "CHMS", "CHMU", | |
"ADDL2", "ADDL3", "SUBL2", "SUBL3", "MULL2", "MULL3", "DIVL2", "DIVL3", | |
"BISL2", "BISL3", "BICL2", "BICL3", "XORL2", "XORL3", "MNEGL", "CASEL", | |
"MOVL", "CMPL", "MCOML", "BITL", "CLRL", "TSTL", "INCL", "DECL", | |
"ADWC", "SBWC", "MTPR", "MFPR", "MOVPSL", "PUSHL", "MOVAL", "PUSHAL", | |
"BBS", "BBC", "BBSS", "BBCS", "BBSC", "BBCC", "BBSSI", "BBCCI", | |
"BLBS", "BLBC", "FFS", "FFC", "CMPV", "CMPZV", "EXTV", "EXTZV", | |
"INSV", "ACBL", "AOBLSS", "AOBLEQ", "SOBGEQ", "SOBGTR", "CVTLB", "CVTLW", | |
"ASHP", "CVTLP", "CALLG", "CALLS", "XFC", NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 100 - 11F */ | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 120 - 13F */ | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
NULL, NULL, "CVTDH", "CVTGF", NULL, NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
"ADDG2", "ADDG3", "SUBG2", "SUBG3", "MULG2", "MULG3", "DIVG2", "DIVG3", | |
"CVTGB", "CVTGW", "CVTGL", "CVTRGL", "CVTBG", "CVTWG", "CVTLG", "ACBG", | |
"MOVG", "CMPG", "MNEGG", "TSTG", "EMODG", "POLYG", "CVTGH", NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
"ADDH2", "ADDH3", "SUBH2", "SUBH3", "MULH2", "MULH3", "DIVH2", "DIVH3", | |
"CVTHB", "CVTHW", "CVTHL", "CVTRHL", "CVTBH", "CVTWH", "CVTLH", "ACBH", | |
"MOVH", "CMPH", "MNEGH", "TSTH", "EMODH", "POLYH", "CVTHG", NULL, | |
NULL, NULL, NULL, NULL, "CLRO", "MOVO", "MOVAO", "PUSHAO", | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 180 - 19F */ | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
"CVTFH", "CVTFG", NULL, NULL, NULL, NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 1A0 - 1BF */ | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 1C0 - 1DF */ | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 1E0 - 1FF */ | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
NULL, NULL, NULL, NULL, NULL, NULL, "CVTHF", "CVTHD", | |
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL | |
}; | |
const char *altcod[] = { | |
"CLRF", "CLRD", "CLRG", "CLRH", "MOVAF", "MOVAD", "MOVAG", "MOVAH", | |
"PUSHAF", "PUSHAD", "PUSHAG", "PUSHAH", "BNEQU", "BEQLU", "BCC", "BCS", | |
NULL | |
}; | |
const int32 altop[] = { | |
0xD4, 0x7C, 0x7C, 0x17C, 0xDE, 0x7E, 0x7E, 0x17E, | |
0xDF, 0x7F, 0x7F, 0x17F, 0x12, 0x13, 0x1E, 0x1F | |
}; | |
const char* regname[] = { | |
"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", | |
"R8", "R9", "R10", "R11", "AP", "FP", "SP", "PC" | |
}; | |
#define GETNUM(d,n) for (k = d = 0; k < n; k++) \ | |
d = d | (((int32) val[vp++]) << (k * 8)) | |
/* Symbolic decode | |
Inputs: | |
*of = output stream | |
addr = current PC | |
*val = values to decode | |
*uptr = pointer to unit | |
sw = switches | |
Outputs: | |
return = if >= 0, error code | |
if < 0, number of extra bytes retired | |
*/ | |
/* Use scp.c provided fprintf function */ | |
#define fprintf Fprintf | |
#define fputs(_s,f) Fprintf(f,"%s",_s) | |
#define fputc(_c,f) Fprintf(f,"%c",_c) | |
t_stat fprint_sym (FILE *of, t_addr exta, t_value *val, | |
UNIT *uptr, int32 sw) | |
{ | |
uint32 addr = (uint32) exta; | |
int32 c, k, num, vp, lnt, rdx; | |
t_stat r; | |
DEVICE *dptr; | |
if (uptr == NULL) /* anon = CPU */ | |
uptr = &cpu_unit; | |
if ((sw & SIM_SW_STOP) && (PSL & PSL_CM)) /* stop in CM? */ | |
sw = sw | SWMASK ('P'); /* force CM print */ | |
dptr = find_dev_from_unit (uptr); /* find dev */ | |
if (dptr == NULL) | |
return SCPE_IERR; | |
if (dptr->dwidth != 8) /* byte dev only */ | |
return SCPE_ARG; | |
if (sw & SWMASK ('B')) /* get length */ | |
lnt = 1; | |
else if (sw & SWMASK ('W')) | |
lnt = 2; | |
else if (sw & SWMASK ('L')) | |
lnt = 4; | |
else lnt = (uptr == &cpu_unit)? 4: 1; | |
if (sw & SWMASK ('D')) /* get radix */ | |
rdx = 10; | |
else if (sw & SWMASK ('O')) | |
rdx = 8; | |
else if (sw & SWMASK ('H')) | |
rdx = 16; | |
else rdx = dptr->dradix; | |
if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */ | |
for (vp = lnt - 1; vp >= 0; vp--) { | |
c = (int32) val[vp] & 0x7F; | |
fprintf (of, (c < 0x20)? "<%02X>": "%c", c); | |
} | |
return -(lnt - 1); /* return # chars */ | |
} | |
if ((sw & (SWMASK ('P') | SWMASK ('R'))) && /* cmode or rad50? */ | |
(uptr == &cpu_unit)) { | |
r = fprint_sym_cm (of, addr, val, sw); /* decode inst */ | |
if (r <= 0) | |
return r; | |
} | |
if ((sw & SWMASK ('M')) && (uptr == &cpu_unit)) { /* inst format? */ | |
r = fprint_sym_m (of, addr, val); /* decode inst */ | |
if (r <= 0) | |
return r; | |
} | |
vp = 0; /* init ptr */ | |
GETNUM (num, lnt); /* get number */ | |
fprint_val (of, (uint32) num, rdx, lnt * 8, PV_RZRO); | |
return -(vp - 1); | |
} | |
/* Symbolic decode for -m | |
Inputs: | |
of = output stream | |
addr = current PC | |
*val = values to decode | |
Outputs: | |
return = if >= 0, error code | |
if < 0, number of extra bytes retired | |
*/ | |
t_stat fprint_sym_m (FILE *of, uint32 addr, t_value *val) | |
{ | |
int32 i, k, vp, inst, numspec; | |
int32 num, spec, rn, disp, index; | |
vp = 0; /* init ptr */ | |
inst = (int32) val[vp++]; /* get opcode */ | |
if (inst == 0xFD) /* 2 byte op? */ | |
inst = 0x100 | (int32) val[vp++]; | |
if (opcode[inst] == NULL) /* defined? */ | |
return SCPE_ARG; | |
numspec = DR_GETNSP (drom[inst][0]); /* get # spec */ | |
if (numspec == 0) | |
numspec = DR_GETUSP (drom[inst][0]); | |
fprintf (of, "%s", opcode[inst]); /* print name */ | |
for (i = 0; i < numspec; i++) { /* loop thru spec */ | |
fputc (i? ',': ' ', of); /* separator */ | |
disp = drom[inst][i + 1]; /* get drom value */ | |
if (disp == BB) { /* byte br disp? */ | |
GETNUM (num, 1); | |
fprintf (of, "%-X", SXTB (num) + addr + vp); | |
} | |
else if (disp == BW) { /* word br disp? */ | |
GETNUM (num, 2); | |
fprintf (of, "%-X", SXTW (num) + addr + vp); | |
} | |
else { | |
spec = (int32) val[vp++]; /* get specifier */ | |
if ((spec & 0xF0) == IDX) { /* index? */ | |
index = spec; /* copy, get next */ | |
spec = (int32) val[vp++]; | |
} | |
else index = 0; | |
rn = spec & 0xF; /* get reg # */ | |
switch (spec & 0xF0) { /* case on mode */ | |
case SH0: case SH1: case SH2: case SH3: /* s^# */ | |
fprintf (of, "#%-X", spec); | |
break; | |
case GRN: /* Rn */ | |
fprintf (of, "%-s", regname[rn]); | |
break; | |
case RGD: /* (Rn) */ | |
fprintf (of, "(%-s)", regname[rn]); | |
break; | |
case ADC: /* -(Rn) */ | |
fprintf (of, "-(%-s)", regname[rn]); | |
break; | |
case AIN: /* (Rn)+, #n */ | |
if (rn != nPC) | |
fprintf (of, "(%-s)+", regname[rn]); | |
else { | |
if (DR_LNT (disp) == L_OCTA) | |
vp = fprint_sym_qoimm (of, val, vp, 4); | |
else if (DR_LNT (disp) == L_QUAD) | |
vp = fprint_sym_qoimm (of, val, vp, 2); | |
else { | |
GETNUM (num, DR_LNT (disp)); | |
fprintf (of, "#%-X", num); | |
} | |
} | |
break; | |
case AID: /* @(Rn)+, @#n */ | |
if (rn != nPC) | |
fprintf (of, "@(%-s)+", regname[rn]); | |
else { | |
GETNUM (num, 4); | |
fprintf (of, "@#%-X", num); | |
} | |
break; | |
case BDD: /* @b^d(r),@b^n */ | |
fputc ('@', of); | |
case BDP: /* b^d(r), b^n */ | |
GETNUM (num, 1); | |
if (rn == nPC) | |
fprintf (of, "%-X", addr + vp + SXTB (num)); | |
else if (num & BSIGN) fprintf (of, "-%-X(%-s)", | |
-num & BMASK, regname[rn]); | |
else fprintf (of, "%-X(%-s)", num, regname[rn]); | |
break; | |
case WDD: /* @w^d(r),@w^n */ | |
fputc ('@', of); | |
case WDP: /* w^d(r), w^n */ | |
GETNUM (num, 2); | |
if (rn == nPC) | |
fprintf (of, "%-X", addr + vp + SXTW (num)); | |
else if (num & WSIGN) fprintf (of, "-%-X(%-s)", | |
-num & WMASK, regname[rn]); | |
else fprintf (of, "%-X(%-s)", num, regname[rn]); | |
break; | |
case LDD: /* @l^d(r),@l^n */ | |
fputc ('@', of); | |
case LDP: /* l^d(r),l^n */ | |
GETNUM (num, 4); | |
if (rn == nPC) | |
fprintf (of, "%-X", addr + vp + num); | |
else if (num & LSIGN) fprintf (of, "-%-X(%-s)", | |
-num, regname[rn]); | |
else fprintf (of, "%-X(%-s)", num, regname[rn]); | |
break; | |
} /* end case */ | |
if (index) | |
fprintf (of, "[%-s]", regname[index & 0xF]); | |
} /* end else */ | |
} /* end for */ | |
return -(vp - 1); | |
} | |
/* Symbolic decode, quad/octa immediates | |
Inputs: | |
*of = output stream | |
*val = pointer to input values | |
vp = current index into val | |
lnt = number of longwords in immediate | |
Outputs: | |
vp = updated index into val | |
*/ | |
int32 fprint_sym_qoimm (FILE *of, t_value *val, int32 vp, int32 lnt) | |
{ | |
int32 i, k, startp, num[4]; | |
for (i = 0; i < lnt; i++) { | |
GETNUM (num[lnt - 1 - i], 4); | |
} | |
for (i = startp = 0; i < lnt; i++) { | |
if (startp) | |
fprintf (of, "%08X", num[i]); | |
else if (num[i] || (i == (lnt - 1))) { | |
fprintf (of, "#%-X", num[i]); | |
startp = 1; | |
} | |
} | |
return vp; | |
} | |
#define PUTNUM(d,n) for (k = 0; k < n; k++) val[vp++] = (d >> (k * 8)) & 0xFF | |
/* Symbolic input | |
Inputs: | |
*cptr = pointer to input string | |
addr = current PC | |
*uptr = pointer to unit | |
*val = pointer to output values | |
sw = switches | |
Outputs: | |
status = > 0 error code | |
<= 0 -number of extra words | |
*/ | |
t_stat parse_sym (char *cptr, t_addr exta, UNIT *uptr, t_value *val, int32 sw) | |
{ | |
uint32 addr = (uint32) exta; | |
int32 k, rdx, lnt, num, vp; | |
t_stat r; | |
DEVICE *dptr; | |
static const uint32 maxv[5] = { 0, 0xFF, 0xFFFF, 0, 0xFFFFFFFF }; | |
if (uptr == NULL) /* anon = CPU */ | |
uptr = &cpu_unit; | |
dptr = find_dev_from_unit (uptr); /* find dev */ | |
if (dptr == NULL) | |
return SCPE_IERR; | |
if (dptr->dwidth != 8) /* byte dev only */ | |
return SCPE_ARG; | |
if (sw & SWMASK ('B')) /* get length */ | |
lnt = 1; | |
else if (sw & SWMASK ('W')) | |
lnt = 2; | |
else if (sw & SWMASK ('L')) | |
lnt = 4; | |
else lnt = (uptr == &cpu_unit)? 4: 1; | |
if (sw & SWMASK ('D')) /* get radix */ | |
rdx = 10; | |
else if (sw & SWMASK ('O')) | |
rdx = 8; | |
else if (sw & SWMASK ('H')) | |
rdx = 16; | |
else rdx = dptr->dradix; | |
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) /* ASCII char? */ | |
return parse_char (cptr, val, lnt); | |
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) /* ASCII string? */ | |
return parse_char (cptr, val, sim_emax); | |
if ((sw & (SWMASK ('P') | SWMASK ('R'))) && /* cmode or rad50? */ | |
(uptr == &cpu_unit)) { | |
r = parse_sym_cm (cptr, addr, val, sw); /* try to parse */ | |
if (r <= 0) | |
return r; | |
} | |
if (uptr == &cpu_unit) { /* cpu only */ | |
r = parse_sym_m (cptr, addr, val); /* try to parse inst */ | |
if (r <= 0) | |
return r; | |
} | |
num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */ | |
if (r != SCPE_OK) | |
return r; | |
vp = 0; | |
PUTNUM (num, lnt); /* store */ | |
return -(lnt - 1); | |
} | |
/* Character input for -a or -c | |
Inputs: | |
*cptr = pointer to input string | |
addr = current PC | |
*val = pointer to output values | |
Outputs: | |
status = > 0 error code | |
<= 0 -number of extra words | |
*/ | |
t_stat parse_char (char *cptr, t_value *val, int32 lnt) | |
{ | |
int32 vp; | |
if (*cptr == 0) | |
return SCPE_ARG; | |
vp = 0; | |
while ((vp < lnt) && *cptr) { /* get chars */ | |
val[vp++] = *cptr++; | |
} | |
return -(vp - 1); /* return # chars */ | |
} | |
/* Symbolic input for -m | |
Inputs: | |
*cptr = pointer to input string | |
addr = current PC | |
*val = pointer to output values | |
Outputs: | |
status = > 0 error code | |
<= 0 -number of extra words | |
*/ | |
t_stat parse_sym_m (char *cptr, uint32 addr, t_value *val) | |
{ | |
int32 i, numspec, disp, opc, vp; | |
t_stat r; | |
char gbuf[CBUFSIZE]; | |
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ | |
for (i = 0, opc = -1; (i < NUM_INST) && (opc < 0); i++) { | |
if (opcode[i] && strcmp (gbuf, opcode[i]) == 0) | |
opc = i; | |
} | |
if (opc < 0) { /* check alternates */ | |
for (i = 0; altcod[i] && (opc < 0); i++) { | |
if (strcmp (gbuf, altcod[i]) == 0) | |
opc = altop[i]; | |
} | |
} | |
if (opc < 0) | |
return SCPE_ARG; /* undefined? */ | |
vp = 0; | |
if (opc >= 0x100) /* 2 byte? */ | |
val[vp++] = 0xFD; | |
val[vp++] = opc & 0xFF; /* store opcode */ | |
numspec = DR_GETNSP (drom[opc][0]); /* get # specifiers */ | |
if (numspec == 0) | |
numspec = DR_GETUSP (drom[opc][0]); | |
for (i = 1; i <= numspec; i++) { /* loop thru specs */ | |
if (i == numspec) | |
cptr = get_glyph (cptr, gbuf, 0); | |
else cptr = get_glyph (cptr, gbuf, ','); /* get specifier */ | |
disp = drom[opc][i]; /* get drom value */ | |
if (disp == BB) | |
vp = parse_brdisp (gbuf, addr, val, vp, 0, &r); | |
else if (disp == BW) | |
vp = parse_brdisp (gbuf, addr, val, vp, 1, &r); | |
else vp = parse_spec (gbuf, addr, val, vp, disp, &r); | |
if (r != SCPE_OK) | |
return r; | |
} | |
if (*cptr != 0) | |
return SCPE_ARG; | |
return -(vp - 1); | |
} | |
/* Parse a branch displacement | |
Inputs: | |
cptr = pointer to input buffer | |
addr = current address | |
val = pointer to output array | |
vp = current pointer in output array | |
lnt = length (0 = byte, 1 = word) | |
r = pointer to status | |
Outputs: | |
vp = updated output pointer | |
*/ | |
int32 parse_brdisp (char *cptr, uint32 addr, t_value *val, int32 vp, | |
int32 lnt, t_stat *r) | |
{ | |
int32 k, dest, num; | |
dest = (int32) get_uint (cptr, 16, 0xFFFFFFFF, r); /* get value */ | |
num = dest - (addr + vp + lnt + 1); /* compute offset */ | |
if ((num > (lnt? 32767: 127)) || (num < (lnt? -32768: -128))) | |
*r = SCPE_ARG; | |
else { | |
PUTNUM (num, lnt + 1); /* store offset */ | |
*r = SCPE_OK; | |
} | |
return vp; | |
} | |
/* Parse a specifier | |
Inputs: | |
cptr = pointer to input buffer | |
addr = current address | |
val = pointer to output array | |
vp = current pointer in output array | |
disp = specifier dispatch | |
r = pointer to status | |
Outputs: | |
vp = updated output pointer | |
*/ | |
#define SP_IND 0x200 /* indirect */ | |
#define SP_V_FORCE 6 | |
#define SP_FS 0x040 /* S^ */ | |
#define SP_FI 0x080 /* I^ */ | |
#define SP_FB 0x0C0 /* B^ */ | |
#define SP_FW 0x100 /* W^ */ | |
#define SP_FL 0x140 /* L^ */ | |
#define SP_LIT 0x020 /* # */ | |
#define SP_PLUS 0x010 /* plus */ | |
#define SP_MINUS 0x008 /* minus */ | |
#define SP_NUM 0x004 /* number */ | |
#define SP_IDX 0x002 /* (Rn) */ | |
#define SP_POSTP 0x001 /* trailing + */ | |
#define M1C(c,v) if (*cptr == c) {\ | |
cptr++; \ | |
fl = fl | v; \ | |
} | |
#define SPUTNUM(v,d) if (fl & SP_MINUS) \ | |
v = -v; \ | |
PUTNUM (v, d) | |
#define PARSE_LOSE { \ | |
*r = SCPE_ARG; \ | |
return vp; \ | |
} | |
#define SEL_LIM(p,m,u) ((fl & SP_PLUS)? (p): ((fl & SP_MINUS)? (m): (u))) | |
int32 parse_spec (char *cptr, uint32 addr, t_value *val, int32 vp, int32 disp, t_stat *r) | |
{ | |
int32 i, k, litsize, rn, index; | |
int32 num, dispsize, mode; | |
int32 lit[4] = { 0 }; | |
int32 fl = 0; | |
char c, *tptr; | |
const char *force[] = { "S^", "I^", "B^", "W^", "L^", NULL }; | |
*r = SCPE_OK; /* assume ok */ | |
M1C ('@', SP_IND); /* look for @ */ | |
if ((tptr = parse_rnum (cptr, &rn))) { /* look for Rn */ | |
if (*cptr == '[') { /* look for [Rx] */ | |
cptr = parse_rnum (++cptr, &index); | |
if ((cptr == NULL) || (*cptr++ != ']')) | |
PARSE_LOSE; | |
val[vp++] = index | IDX; | |
} | |
else val[vp++] = rn | GRN | (fl? 1: 0); /* Rn or @Rn */ | |
if (*tptr != 0) /* must be done */ | |
*r = SCPE_ARG; | |
return vp; | |
} | |
for (i = 0; force[i]; i++) { /* look for x^ */ | |
if (strncmp (cptr, force[i], 2) == 0) { | |
cptr = cptr + 2; | |
fl = fl | ((i + 1) << SP_V_FORCE); | |
break; | |
} | |
} | |
M1C ('#', SP_LIT); /* look for # */ | |
M1C ('+', SP_PLUS); /* look for + */ | |
M1C ('-', SP_MINUS); /* look for - */ | |
for (litsize = 0;; cptr++) { /* look for mprec int */ | |
c = *cptr; | |
if ((c < '0') || (c > 'F') || ((c > '9') && (c < 'A'))) | |
break; | |
num = (c <= '9')? c - '0': c - 'A' + 10; | |
fl = fl | SP_NUM; | |
for (i = 3; i >= 0; i--) { | |
lit[i] = lit[i] << 4; | |
if (i > 0) | |
lit[i] = lit[i] | ((lit[i - 1] >> 28) & 0xF); | |
else lit[i] = lit[i] | num; | |
if (lit[i] && (i > litsize)) | |
litsize = i; | |
} | |
} | |
if (*cptr == '(') { /* look for (Rn) */ | |
cptr = parse_rnum (++cptr, &rn); | |
if ((cptr == NULL) || (*cptr++ != ')')) | |
PARSE_LOSE; | |
fl = fl | SP_IDX; | |
} | |
M1C ('+', SP_POSTP); /* look for + */ | |
if (*cptr == '[') { /* look for [Rx] */ | |
cptr = parse_rnum (++cptr, &index); | |
if ((cptr == NULL) || (*cptr++ != ']')) | |
PARSE_LOSE; | |
val[vp++] = index | IDX; | |
} | |
switch (fl) { /* case on state */ | |
case SP_FS|SP_LIT|SP_NUM: /* S^#n */ | |
case SP_FS|SP_LIT|SP_PLUS|SP_NUM: /* S^#+n */ | |
if ((litsize > 0) || (lit[0] & ~0x3F)) | |
PARSE_LOSE; | |
val[vp++] = lit[0]; | |
break; | |
case SP_IDX: /* (Rn) */ | |
val[vp++] = rn | RGD; | |
break; | |
case SP_MINUS|SP_IDX: /* -(Rn) */ | |
val[vp++] = rn | ADC; | |
break; | |
case SP_IDX|SP_POSTP: /* (Rn)+ */ | |
val[vp++] = rn | AIN; | |
break; | |
case SP_LIT|SP_NUM: /* #n */ | |
case SP_LIT|SP_PLUS|SP_NUM: /* #+n */ | |
if ((litsize == 0) && ((lit[0] & ~0x3F) == 0)) { | |
val[vp++] = lit[0]; | |
break; | |
} /* fall thru */ | |
case SP_LIT|SP_MINUS|SP_NUM: /* #-n */ | |
case SP_FI|SP_LIT|SP_NUM: /* I^#n */ | |
case SP_FI|SP_LIT|SP_PLUS|SP_NUM: /* I^#+n */ | |
case SP_FI|SP_LIT|SP_MINUS|SP_NUM: /* I^#-n */ | |
val[vp++] = nPC | AIN; | |
disp = disp & DR_LNMASK; | |
switch (disp) { /* case spec lnt */ | |
case 00: /* check fit */ | |
if ((litsize > 0) || (lit[0] < 0) || | |
(lit[0] > SEL_LIM (0x7F, 0x80, 0xFF))) | |
PARSE_LOSE; | |
SPUTNUM (lit[0], 1); /* store */ | |
break; | |
case 01: /* check fit */ | |
if ((litsize > 0) || (lit[0] < 0) || | |
(lit[0] > SEL_LIM (0x7FFF, 0x8000, 0xFFFF))) | |
PARSE_LOSE; | |
SPUTNUM (lit[0], 2); | |
break; | |
case 02: /* check 1 lw */ | |
if (litsize > 0) | |
PARSE_LOSE; | |
SPUTNUM (lit[0], 4); | |
break; | |
case 03: /* check 2 lw */ | |
if (litsize > 1) | |
PARSE_LOSE; | |
vp = parse_sym_qoimm (lit, val, vp, 2, fl & SP_MINUS); | |
break; | |
case 04: | |
vp = parse_sym_qoimm (lit, val, vp, 4, fl & SP_MINUS); | |
break; | |
} /* end case lnt */ | |
break; | |
case SP_IND|SP_IDX|SP_POSTP: /* @(Rn)+ */ | |
val[vp++] = rn | AID; | |
break; | |
case SP_IND|SP_LIT|SP_NUM: /* @#n */ | |
if (litsize > 0) | |
PARSE_LOSE; | |
val[vp++] = nPC | AID; | |
PUTNUM (lit[0], 4); | |
break; | |
case SP_NUM|SP_IDX: /* d(rn) */ | |
case SP_PLUS|SP_NUM|SP_IDX: /* +d(rn) */ | |
case SP_MINUS|SP_NUM|SP_IDX: /* -d(rn) */ | |
case SP_IND|SP_NUM|SP_IDX: /* @d(rn) */ | |
case SP_IND|SP_PLUS|SP_NUM|SP_IDX: /* @+d(rn) */ | |
case SP_IND|SP_MINUS|SP_NUM|SP_IDX: /* @-d(rn) */ | |
if (litsize > 0) | |
PARSE_LOSE; | |
dispsize = 4; /* find fit for */ | |
mode = LDP; /* displacement */ | |
if (lit[0] >= 0) { | |
if (lit[0] <= SEL_LIM (0x7F, 0x80, 0xFF)) { | |
dispsize = 1; | |
mode = BDP; | |
} | |
else if (lit[0] <= SEL_LIM (0x7FFF, 0x8000, 0xFFFF)) { | |
dispsize = 2; | |
mode = WDP; | |
} | |
} | |
val[vp++] = mode | rn | ((fl & SP_IND)? 0x10: 0); | |
SPUTNUM (lit[0], dispsize); | |
break; | |
case SP_FB|SP_NUM|SP_IDX: /* B^d(rn) */ | |
case SP_FB|SP_PLUS|SP_NUM|SP_IDX: /* B^+d(rn) */ | |
case SP_FB|SP_MINUS|SP_NUM|SP_IDX: /* B^-d(rn) */ | |
case SP_IND|SP_FB|SP_NUM|SP_IDX: /* @B^d(rn) */ | |
case SP_IND|SP_FB|SP_PLUS|SP_NUM|SP_IDX: /* @B^+d(rn) */ | |
case SP_IND|SP_FB|SP_MINUS|SP_NUM|SP_IDX: /* @B^-d(rn) */ | |
if ((litsize > 0) || (lit[0] < 0) || | |
(lit[0] > SEL_LIM (0x7F, 0x80, 0xFF))) | |
PARSE_LOSE; | |
val[vp++] = rn | BDP | ((fl & SP_IND)? 0x10: 0); | |
SPUTNUM (lit[0], 1); | |
break; | |
case SP_FW|SP_NUM|SP_IDX: /* W^d(rn) */ | |
case SP_FW|SP_PLUS|SP_NUM|SP_IDX: /* W^+d(rn) */ | |
case SP_FW|SP_MINUS|SP_NUM|SP_IDX: /* W^-d(rn) */ | |
case SP_IND|SP_FW|SP_NUM|SP_IDX: /* @W^d(rn) */ | |
case SP_IND|SP_FW|SP_PLUS|SP_NUM|SP_IDX: /* @W^+d(rn) */ | |
case SP_IND|SP_FW|SP_MINUS|SP_NUM|SP_IDX: /* @W^-d(rn) */ | |
if ((litsize > 0) || (lit[0] < 0) || | |
(lit[0] > SEL_LIM (0x7FFF, 0x8000, 0xFFFF))) | |
PARSE_LOSE; | |
val[vp++] = rn | WDP | ((fl & SP_IND)? 0x10: 0); | |
SPUTNUM (lit[0], 2); | |
break; | |
case SP_FL|SP_NUM|SP_IDX: /* L^d(rn) */ | |
case SP_FL|SP_PLUS|SP_NUM|SP_IDX: /* L^+d(rn) */ | |
case SP_FL|SP_MINUS|SP_NUM|SP_IDX: /* L^-d(rn) */ | |
case SP_IND|SP_FL|SP_NUM|SP_IDX: /* @L^d(rn) */ | |
case SP_IND|SP_FL|SP_PLUS|SP_NUM|SP_IDX: /* @L^+d(rn) */ | |
case SP_IND|SP_FL|SP_MINUS|SP_NUM|SP_IDX: /* @L^-d(rn) */ | |
if ((litsize > 0) || (lit[0] < 0)) | |
PARSE_LOSE; | |
val[vp++] = rn | LDP | ((fl & SP_IND)? 0x10: 0); | |
SPUTNUM (lit[0], 4); | |
break; | |
case SP_NUM: /* n */ | |
case SP_IND|SP_NUM: /* @n */ | |
if (litsize > 0) | |
PARSE_LOSE; | |
num = lit[0] - (addr + vp + 2); /* fit in byte? */ | |
if ((num >= -128) && (num <= 127)) { | |
mode = BDP; | |
dispsize = 1; | |
} | |
else { | |
num = lit[0] - (addr + vp + 3); /* fit in word? */ | |
if ((num >= -32768) && (num <= 32767)) { | |
mode = WDP; | |
dispsize = 2; | |
} | |
else { | |
num = lit[0] - (addr + vp + 5); /* no, use lw */ | |
mode = LDP; | |
dispsize = 4; | |
} | |
} | |
val[vp++] = mode | nPC | ((fl & SP_IND)? 1: 0); | |
PUTNUM (num, dispsize); | |
break; | |
case SP_FB|SP_NUM: /* B^n */ | |
case SP_IND|SP_FB|SP_NUM: /* @B^n */ | |
num = lit[0] - (addr + vp + 2); | |
if ((litsize > 0) || (num > 127) || (num < -128)) | |
PARSE_LOSE; | |
val[vp++] = nPC | BDP | ((fl & SP_IND)? 1: 0); | |
PUTNUM (num, 1); | |
break; | |
case SP_FW|SP_NUM: /* W^n */ | |
case SP_IND|SP_FW|SP_NUM: /* @W^n */ | |
num = lit[0] - (addr + vp + 3); | |
if ((litsize > 0) || (num > 32767) || (num < -32768)) | |
PARSE_LOSE; | |
val[vp++] = nPC | WDP | ((fl & SP_IND)? 1: 0); | |
PUTNUM (num, 2); | |
break; | |
case SP_FL|SP_NUM: /* L^n */ | |
case SP_IND|SP_FL|SP_NUM: /* @L^n */ | |
num = lit[0] - (addr + vp + 5); | |
if (litsize > 0) | |
PARSE_LOSE; | |
val[vp++] = nPC | LDP | ((fl & SP_IND)? 1: 0); | |
PUTNUM (num, 4); | |
break; | |
default: | |
PARSE_LOSE; | |
} /* end case */ | |
if (*cptr != 0) /* must be done */ | |
*r = SCPE_ARG; | |
return vp; | |
} | |
char *parse_rnum (char *cptr, int32 *rn) | |
{ | |
int32 i, lnt; | |
t_value regnum; | |
char *tptr; | |
*rn = 0; | |
for (i = 15; i >= 0; i--) { /* chk named reg */ | |
lnt = strlen (regname[i]); | |
if (strncmp (cptr, regname[i], lnt) == 0) { | |
*rn = i; | |
return cptr + lnt; | |
} | |
} | |
if (*cptr++ != 'R') /* look for R */ | |
return NULL; | |
regnum = strtotv (cptr, (const char **)&tptr, 10); /* look for reg # */ | |
if ((cptr == tptr) || (regnum > 15)) | |
return NULL; | |
*rn = (int32) regnum; | |
return tptr; | |
} | |
int32 parse_sym_qoimm (int32 *lit, t_value *val, int32 vp, int lnt, int32 minus) | |
{ | |
int32 i, k, prev; | |
for (i = prev = 0; i < lnt; i++) { | |
if (minus) | |
prev = lit[i] = ~lit[i] + (prev == 0); | |
PUTNUM (lit[i], 4); | |
} | |
return vp; | |
} | |