diff --git a/3B2/3b2_cpu.c b/3B2/3b2_cpu.c index ad6e4fbf..7b3079c7 100644 --- a/3B2/3b2_cpu.c +++ b/3B2/3b2_cpu.c @@ -68,10 +68,6 @@ extern uint16 csr_data; uint32 R[16]; /* Other global CPU state */ -int8 cpu_dtype = -1; /* Default datatype for the current - instruction */ -int8 cpu_etype = -1; /* Currently set expanded datatype */ - t_bool cpu_nmi = FALSE; /* If set, there has been an NMI */ int32 pc_incr = 0; /* Length (in bytes) of instruction @@ -727,7 +723,196 @@ t_stat cpu_set_hist(UNIT *uptr, int32 val, CONST char *cptr, void *desc) return SCPE_OK; } -void fprint_sym_m(FILE *st, instr *ip) +t_stat fprint_sym_m(FILE *of, t_addr addr, t_value *val) +{ + uint8 desc, mode, reg, class, etype; + uint32 w; + int32 vp, inst, i; + mnemonic *mn; + char reg_name[8]; + + mn = NULL; + vp = 0; + etype = -1; + + inst = (int32) val[vp++]; + + if (inst == 0x30) { + /* Scan to find opcode */ + inst = 0x3000 | val[vp++]; + for (i = 0; i < HWORD_OP_COUNT; i++) { + if (hword_ops[i].opcode == inst) { + mn = &hword_ops[i]; + break; + } + } + } else { + mn = &ops[inst]; + } + + if (mn == NULL) { + fprintf(of, "???"); + return -(vp - 1); + } + + fprintf(of, "%s", mn->mnemonic); + + for (i = 0; i < mn->op_count; i++) { + + /* Special cases for non-descriptor opcodes */ + if (mn->mode == OP_BYTE) { + mode = 6; + reg = 15; + } else if (mn->mode == OP_HALF) { + mode = 5; + reg = 15; + } else if (mn->mode == OP_COPR) { + mode = 4; + reg = 15; + } else { + desc = val[vp++]; + mode = (desc >> 4) & 0xf; + reg = desc & 0xf; + + /* Find the expanded data type, if any */ + if (mode == 14 && + (reg == 0 || reg == 2 || reg == 3 || + reg == 4 || reg == 6 || reg == 7)) { + etype = reg; + /* The real descriptor byte lies one ahead */ + desc = val[vp++]; + mode = (desc >> 4) & 0xf; + reg = desc & 0xf; + } + } + + fputc(i ? ',' : ' ', of); + + switch (etype) { + case 0: + fprintf(of, "{uword}"); + break; + case 2: + fprintf(of, "{uhalf}"); + break; + case 3: + fprintf(of, "{ubyte}"); + break; + case 4: + fprintf(of, "{word}"); + break; + case 6: + fprintf(of, "{half}"); + break; + case 7: + fprintf(of, "{sbyte}"); + break; + default: + /* do nothing */ + break; + } + + switch(mode) { + case 0: /* Positive Literal */ + case 1: /* Positive Literal */ + case 2: /* Positive Literal */ + case 3: /* Positive Literal */ + case 15: /* Negative Literal */ + fprintf(of, "&%d", desc); + break; + case 4: /* Halfword Immediate, Register Mode */ + switch (reg) { + case 15: /* Word Immediate */ + OP_R_W(w, val, vp); + fprintf(of, "&0x%x", w); + break; + default: /* Register Mode */ + cpu_register_name(reg, reg_name, 8); + fprintf(of, "%s", reg_name); + break; + } + break; + case 5: /* Halfword Immediate, Register Deferred */ + switch (reg) { + case 15: + OP_R_H(w, val, vp); + fprintf(of, "&0x%x", w); + break; + default: + cpu_register_name(reg, reg_name, 8); + fprintf(of, "(%s)", reg_name); + break; + } + break; + case 6: /* Byte Immediate, FP Short Offset */ + switch (reg) { + case 15: + OP_R_B(w, val, vp); + fprintf(of, "&0x%x", w); + break; + default: + fprintf(of, "%d(%%fp)", reg); + break; + } + break; + case 7: /* Absolute, AP Short Offset */ + switch (reg) { + case 15: + OP_R_W(w, val, vp); + fprintf(of, "$0x%x", w); + break; + default: + fprintf(of, "%d(%%ap)", reg); + break; + } + break; + case 8: /* Word Displacement */ + OP_R_W(w, val, vp); + cpu_register_name(reg, reg_name, 8); + fprintf(of, "0x%x(%s)", w, reg_name); + break; + case 9: /* Word Displacement Deferred */ + OP_R_W(w, val, vp); + cpu_register_name(reg, reg_name, 8); + fprintf(of, "*0x%x(%s)", w, reg_name); + break; + case 10: /* Halfword Displacement */ + OP_R_H(w, val, vp); + cpu_register_name(reg, reg_name, 8); + fprintf(of, "0x%x(%s)", w, reg_name); + break; + case 11: /* Halfword Displacement Deferred */ + OP_R_H(w, val, vp); + cpu_register_name(reg, reg_name, 8); + fprintf(of, "*0x%x(%s)", w, reg_name); + break; + case 12: /* Byte Displacement */ + OP_R_B(w, val, vp); + cpu_register_name(reg, reg_name, 8); + fprintf(of, "%d(%s)", w, reg_name); + break; + case 13: /* Byte Displacement Deferred */ + OP_R_B(w, val, vp); + cpu_register_name(reg, reg_name, 8); + fprintf(of, "*%d(%s)", w, reg_name); + break; + case 14: + if (reg == 15) { + OP_R_W(w, val, vp); + fprintf(of, "*$0x%x", w); + } + break; + default: + fprintf(of, ""); + break; + } + } + + + return -(vp - 1); +} + +void fprint_sym_hist(FILE *st, instr *ip) { int32 i; @@ -794,7 +979,7 @@ t_stat cpu_show_hist(FILE *st, UNIT *uptr, int32 val, CONST void *desc) if (ip->mn == NULL || ip->mn->op_count < 0) { fprintf(st, "???"); } else { - fprint_sym_m(st, ip); + fprint_sym_hist(st, ip); if (ip->mn->op_count > 0 && ip->mn->mode == OP_DESC) { fprintf(st, "\n "); for (j = 0; j < (uint32) ip->mn->op_count; j++) { @@ -936,7 +1121,7 @@ void cpu_show_operand(FILE *st, operand *op) } break; case 15: - fprintf(st, "&%d", (int32)op->embedded.w); + fprintf(st, "&0x%x", (int32)op->embedded.w); break; } } @@ -989,26 +1174,21 @@ static SIM_INLINE void clear_instruction(instr *inst) /* * Decode a single descriptor-defined operand from the instruction - * stream. Returns the number of bytes consumed during decode. + * stream. Returns the number of bytes consumed during decode.type */ -static uint8 decode_operand(uint32 pa, instr *instr, uint8 op_number) +static uint8 decode_operand(uint32 pa, instr *instr, uint8 op_number, uint8 *etype) { uint8 desc; uint8 offset = 0; operand *oper = &instr->operands[op_number]; - /* Set the default data type if none is already set */ - if (cpu_dtype == -1) { - cpu_dtype = instr->mn->dtype; - } - /* Read in the descriptor byte */ desc = read_b(pa + offset++, ACC_OF); oper->mode = (desc >> 4) & 0xf; oper->reg = desc & 0xf; oper->dtype = instr->mn->dtype; - oper->etype = cpu_etype; + oper->etype = *etype; switch (oper->mode) { case 0: /* Positive Literal */ @@ -1016,7 +1196,7 @@ static uint8 decode_operand(uint32 pa, instr *instr, uint8 op_number) case 2: /* Positive Literal */ case 3: /* Positive Literal */ case 15: /* Negative literal */ - oper->embedded.b = (uint8)desc; + oper->embedded.b = desc; oper->data = oper->embedded.b; break; case 4: /* Word Immediate, Register Mode */ @@ -1110,9 +1290,9 @@ static uint8 decode_operand(uint32 pa, instr *instr, uint8 op_number) case 7: /* Expanded Datatype */ /* Recursively decode the remainder of the operand after storing the expanded datatype */ - cpu_etype = (int8) oper->reg; - oper->etype = cpu_etype; - offset += decode_operand(pa + offset, instr, op_number); + *etype = (int8) oper->reg; + oper->etype = *etype; + offset += decode_operand(pa + offset, instr, op_number, etype); break; default: cpu_abort(NORMAL_EXCEPTION, RESERVED_DATATYPE); @@ -1134,9 +1314,9 @@ static uint8 decode_operand(uint32 pa, instr *instr, uint8 op_number) * the opcode type. * 3. Fetch each opcode from main memory. * - * This routine may alter the PSW's ET (Exception Type) and - * ISC (Internal State Code) registers if an exceptional condition - * is encountered during decode. + * This routine is guaranteed not to change state. + * + * returns: a Normal Exception if an error occured, or 0 on success. */ uint8 decode_instruction(instr *instr) { @@ -1146,6 +1326,9 @@ uint8 decode_instruction(instr *instr) uint32 pa; mnemonic *mn = NULL; int i; + int8 etype = -1; /* Expanded datatype (if any) */ + + clear_instruction(instr); pa = R[NUM_PC]; @@ -1154,10 +1337,6 @@ uint8 decode_instruction(instr *instr) instr->sp = R[NUM_SP]; instr->pc = pa; - /* Reset our data types */ - cpu_etype = -1; - cpu_dtype = -1; - if (read_operand(pa + offset++, &b1) != SCPE_OK) { /* We tried to read out of a page that doesn't exist. We need to let the operating system handle it.*/ @@ -1222,13 +1401,13 @@ uint8 decode_instruction(instr *instr) /* Decode subsequent operands */ for (i = 1; i < mn->op_count; i++) { - offset += decode_operand(pa + offset, instr, (uint8) i); + offset += decode_operand(pa + offset, instr, (uint8) i, &etype); } break; case OP_DESC: for (i = 0; i < mn->op_count; i++) { - offset += decode_operand(pa + offset, instr, (uint8) i); + offset += decode_operand(pa + offset, instr, (uint8) i, &etype); } break; } @@ -1508,7 +1687,6 @@ t_stat sim_instr(void) } /* Decode the instruction */ - clear_instruction(cpu_instr); pc_incr = decode_instruction(cpu_instr); /* Make sure to update the valid bit for history keeping (if diff --git a/3B2/3b2_cpu.h b/3B2/3b2_cpu.h index 2640a1f5..905b9f4e 100644 --- a/3B2/3b2_cpu.h +++ b/3B2/3b2_cpu.h @@ -403,7 +403,8 @@ t_bool cpu_is_pc_a_subroutine_call (t_addr **ret_addrs); void cpu_register_name(uint8 reg, char *buf, size_t len); void cpu_show_operand(FILE *st, operand *op); -void fprint_sym_m(FILE *st, instr *ip); +void fprint_sym_hist(FILE *st, instr *ip); +t_stat fprint_sym_m(FILE *of, t_addr addr, t_value *val); instr *cpu_next_instruction(void); @@ -488,4 +489,20 @@ static SIM_INLINE void sub(t_uint64 a, t_uint64 b, operand *dst); } \ } +#define OP_R_W(d,a,p) { \ + (d) = (uint32) (a)[(p)++]; \ + (d) |= (uint32) (a)[(p)++] << 8u; \ + (d) |= (uint32) (a)[(p)++] << 16u; \ + (d) |= (uint32) (a)[(p)++] << 24u; \ + } + +#define OP_R_H(d,a,p) { \ + (d) = (uint16) (a)[(p)++]; \ + (d) |= (uint16) (a)[(p)++] << 8u; \ + } + +#define OP_R_B(d,a,p) { \ + (d) = (uint8) (a)[(p)++]; \ + } + #endif diff --git a/3B2/3b2_sys.c b/3B2/3b2_sys.c index 2234ccf4..3c57d867 100644 --- a/3B2/3b2_sys.c +++ b/3B2/3b2_sys.c @@ -160,6 +160,10 @@ t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) num = 0; vp = 0; + if (sw & (int32) SWMASK('M')) { + return fprint_sym_m(of, addr, val); + } + if (sw & (int32) SWMASK ('B')) { len = 1; } else if (sw & (int32) SWMASK ('H')) { @@ -168,11 +172,6 @@ t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) len = 4; } - if (sw & (int32) SWMASK('M')) { - fprint_sym_m(of, cpu_instr); - return SCPE_OK; - } - if (sw & (int32) SWMASK('C')) { len = 16; for (k = (int32) len - 1; k >= 0; k--) { diff --git a/3B2/3b2_sys.h b/3B2/3b2_sys.h index 4d575858..6400dc0b 100644 --- a/3B2/3b2_sys.h +++ b/3B2/3b2_sys.h @@ -40,9 +40,9 @@ extern int32 sim_emax; extern DEVICE *sim_devices[]; void full_reset(); -t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag); -t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, +t_stat sim_load(FILE *fileref, CONST char *cptr, CONST char *fnam, int flag); +t_stat parse_sym(CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw); -t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw); +t_stat fprint_sym(FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw); #endif