1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-03-01 17:36:21 +00:00

IBM360: Added TOD support, Channel status managment.

This commit is contained in:
Richard Cornwell
2020-02-03 22:21:10 -05:00
parent 7fac3ee2ba
commit 179f859c4d
4 changed files with 276 additions and 233 deletions

View File

@@ -97,6 +97,7 @@ uint16 chan_status[CHAN_SZ]; /* Channel status */
uint16 chan_dev[CHAN_SZ]; /* Device on channel */
uint32 chan_buf[CHAN_SZ]; /* Channel data buffer */
uint8 chan_byte[CHAN_SZ]; /* Current byte, dirty/full */
uint8 chan_pend[CHAN_SZ]; /* Pending status on this channel */
DIB *dev_unit[MAX_DEV]; /* Pointer to Device info block */
uint8 dev_status[MAX_DEV]; /* last device status flags */
@@ -594,8 +595,10 @@ set_devattn(uint16 addr, uint8 flags) {
if (chan_dev[chan] == addr && (chan_status[chan] & STATUS_CEND) != 0 &&
(flags & SNS_DEVEND) != 0) {
chan_status[chan] |= ((uint16)flags) << 8;
} else
} else {
dev_status[addr] = flags;
chan_pend[chan] = 1;
}
sim_debug(DEBUG_EXP, &cpu_dev, "set_devattn(%x, %x) %x\n",
addr, flags, chan_dev[chan]);
irq_pend = 1;
@@ -659,7 +662,7 @@ chan_end(uint16 addr, uint8 flags) {
/*
* Save full csw.
*/
int
void
store_csw(uint16 chan) {
M[0x40 >> 2] = caw[chan];
M[0x44 >> 2] = (((uint32)ccw_count[chan])) | ((uint32)chan_status[chan]<<16);
@@ -672,7 +675,6 @@ store_csw(uint16 chan) {
}
sim_debug(DEBUG_EXP, &cpu_dev, "Channel store csw %02x %06x %08x\n",
chan, M[0x40>>2], M[0x44 >> 2]);
return chan_dev[chan];
}
/*
@@ -697,8 +699,21 @@ startio(uint16 addr) {
}
/* If channel is active return cc=2 */
if (ccw_cmd[chan] != 0 || (ccw_flags[chan] & (FLAG_CD|FLAG_CC)) != 0 || chan_status[chan] != 0)
return 2;
if (ccw_cmd[chan] != 0 || (ccw_flags[chan] & (FLAG_CD|FLAG_CC)) != 0 || chan_status[chan] != 0) {
sim_debug(DEBUG_CMD, &cpu_dev, "SIO %x %x cc=2\n", addr, chan);
return 2;
}
if (dev_status[addr] != 0) {
M[0x44 >> 2] = (((uint32)dev_status[addr]) << 24);
M[0x40>>2] = 0;
sim_debug(DEBUG_EXP, &cpu_dev,
"SIO Set atten %03x %x %02x [%08x] %08x\n",
addr, chan, dev_status[addr], M[0x40 >> 2], M[0x44 >> 2]);
dev_status[addr] = 0;
return 1;
}
sim_debug(DEBUG_CMD, &cpu_dev, "SIO %x %x %x %x\n", addr, chan,
ccw_cmd[chan], ccw_flags[chan]);
@@ -794,13 +809,6 @@ int testio(uint16 addr) {
return 2;
}
/* If error pending for another device, return cc=2 */
if (chan_dev[chan] != 0 && chan_dev[chan] != addr) {
sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x %x %x cc=2a\n", addr, chan,
ccw_cmd[chan], ccw_flags[chan]);
return 2;
}
/* Device finished and channel status pending return it and cc=1 */
if (ccw_cmd[chan] == 0 && chan_status[chan] != 0) {
sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x %x %x cc=1a\n", addr, chan,
@@ -817,9 +825,29 @@ int testio(uint16 addr) {
M[0x40 >> 2] = 0;
M[0x44 >> 2] = ((uint32)dev_status[addr]) << 24;
dev_status[addr] = 0;
chan_pend[chan] = 0;
return 1;
}
/* If error pending for another device, return cc=2 */
if (chan_pend[chan] != 0) {
int pend, ch;
chan_pend[chan] = 0;
/* Check if might be false */
for (pend = 0; pend < MAX_DEV; pend++) {
if (dev_status[pend] != 0) {
ch = find_subchan(pend);
if (ch == chan) {
chan_pend[ch] = 1;
sim_debug(DEBUG_CMD, &cpu_dev, "TIO %x %x %x %x %x cc=2a\n", addr, chan,
ccw_cmd[chan], ccw_flags[chan], pend);
return 2;
}
}
}
}
/* Nothing pending, send a 0 command to device to get status */
status = dibp->start_cmd(uptr, chan, 0) << 8;
@@ -884,7 +912,7 @@ int haltio(uint16 addr) {
int testchan(uint16 channel) {
uint16 st = 0;
channel >>= 8;
if (channel == 0)
if (channel == 0 || channels == 4)
return 0;
if (channel > channels)
return 3;
@@ -1001,6 +1029,7 @@ scan_chan(uint16 mask, int irq_en) {
if (ch >= 0 && loading == 0) {
sim_debug(DEBUG_EXP, &cpu_dev, "Scan end (%x %x)\n", chan_dev[ch], pend);
store_csw(ch);
dev_status[pend] = 0;
return pend;
}
} else {

View File

@@ -77,6 +77,7 @@ uint32 clk_cmp[2]; /* Clock compare value */
uint32 cpu_timer[2]; /* CPU timer value */
#endif
int clk_state;
int timer_tics; /* Access count for TOD */
#define CLOCK_UNSET 0 /* Clock not set */
#define CLOCK_SET 1 /* Clock set */
@@ -941,6 +942,7 @@ sim_instr(void)
seg_addr = cregs[0] & AMASK;
seg_len = (((cregs[0] >> 24) & 0xff) + 1) << 4;
} else {
sim_activate(&cpu_unit[1], 1000);
switch((cregs[0] >> 22) & 03) {
default: /* Generate translation exception */
case 1: /* 2K pages */
@@ -1352,14 +1354,12 @@ exe:
if (flags & PROBLEM) {
storepsw(OPPSW, IRC_PRIV);
} else {
fprintf(stderr, "SSM: %08x\r\n", addr1);
if ((cpu_unit[0].flags & FEAT_370) != 0 && (cregs[0] & 0x40000000) != 0) {
storepsw(OPPSW, IRC_SPOP);
goto supress;
}
if (ReadByte(addr1, &src1))
break;
fprintf(stderr, "SSM0: %02x\r\n", src1);
if (ec_mode) {
if ((cpu_unit[0].flags & FEAT_370) != 0) {
if (src1 & 0xb8) {
@@ -2713,11 +2713,19 @@ fprintf(stderr, "Set TOD %016llx\r\n", tod_clock);
goto supress;
if (WriteFull(addr1+4, src1h))
goto supress;
if (clk_state && (cregs[0] & 0x20000000) == 0) {
tod_clock += 0x1000;
timer_tics += 0x1000;
}
#else
if (WriteFull(addr1, tod_clock[0]))
goto supress;
if (WriteFull(addr1+4, tod_clock[1]))
goto supress;
if (clk_state && (cregs[0] & 0x20000000) == 0) {
tod_clock[1] += 0x1000;
timer_tics += 0x1000;
}
#endif
cc = !clk_state;
break;
@@ -2971,6 +2979,7 @@ fprintf(stderr, "Set TOD %016llx\r\n", tod_clock);
if (ReadFull(addr1, &dest))
goto supress;
cregs[reg1] = dest;
sim_debug(DEBUG_CDATA, &cpu_dev,"Loading: CR %x %08x IC=%08x %x\n\r", reg1, dest, PC, reg);
fprintf(stderr, "Loading: CR %x %08x IC=%08x %x\n\r", reg1, dest, PC, reg);
switch (reg1) {
case 0x0: /* General controll register */
@@ -5590,15 +5599,18 @@ clk_srv(UNIT * uptr)
(void)sim_rtcn_calb (clk_tps, TMR_RTC);
sim_activate_after(uptr, 1000000/clk_tps);
#ifdef USE_64BIT
if (clk_state && (cregs[0] & 0x20000000) == 0)
tod_clock += 1000 << 12;
if (clk_state && (cregs[0] & 0x20000000) == 0) {
tod_clock += (1000 << 12) - timer_tics;
timer_tics = 0;
}
cpu_timer -= 1000 << 12;
#else
if (clk_state && (cregs[0] & 0x20000000) == 0) {
t = tod_clock[1] + (1000 << 12);
t = tod_clock[1] + (1000 << 12) - timer_tics;
if (t < tod_clock[1])
tod_clock[0]++;
tod_clock[1] = t;
timer_tics = 0;
}
t = cpu_timer[1] - (1000 << 12);
if (t > cpu_timer[1])

View File

@@ -255,8 +255,6 @@ uint8 mt_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) {
/* Fall through */
case 0x4: /* Sense */
if ((cmd & 0xf) == 0x4)
cmd = 0x4;
uptr->u3 &= ~(MT_CMDMSK);
uptr->u3 |= cmd & MT_CMDMSK;
sim_activate(uptr, 1000); /* Start unit off */
@@ -389,7 +387,7 @@ t_stat mt_srv(UNIT * uptr)
}
}
switch (cmd) {
switch (cmd & 0xf) {
case 0: /* No command, stop tape */
sim_debug(DEBUG_DETAIL, dptr, "Idle unit=%d\n", unit);
break;
@@ -634,232 +632,235 @@ t_stat mt_srv(UNIT * uptr)
sim_activate(uptr, 20);
}
break;
case MT_WTM:
if (uptr->u4 == 0) {
if (sim_tape_wrp(uptr)) {
uptr->u5 |= SNS_CMDREJ;
uptr->u3 &= ~MT_CMDMSK;
mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1;
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
return SCPE_OK;
}
uptr->u4 ++;
sim_activate(uptr, 500);
} else {
sim_debug(DEBUG_DETAIL, dptr, "Write Mark unit=%d\n", unit);
uptr->u3 &= ~(MT_CMDMSK);
r = sim_tape_wrtmk(uptr);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
}
break;
case MT_BSR:
switch (uptr->u4 ) {
case 0:
if (sim_tape_bot(uptr)) {
uptr->u3 &= ~MT_CMDMSK;
mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1;
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
return SCPE_OK;
}
uptr->u4 ++;
sim_activate(uptr, 500);
break;
case 1:
uptr->u4++;
sim_debug(DEBUG_DETAIL, dptr, "Backspace rec unit=%d ", unit);
r = sim_tape_sprecr(uptr, &reclen);
/* We don't set EOF on BSR */
if (r == MTSE_TMK) {
uptr->u4++;
sim_debug(DEBUG_DETAIL, dptr, "MARK\n");
sim_activate(uptr, 50);
case 0x7:
case 0xf:
switch (cmd) {
case MT_WTM:
if (uptr->u4 == 0) {
if (sim_tape_wrp(uptr)) {
uptr->u5 |= SNS_CMDREJ;
uptr->u3 &= ~MT_CMDMSK;
mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1;
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
return SCPE_OK;
}
uptr->u4 ++;
sim_activate(uptr, 500);
} else {
sim_debug(DEBUG_DETAIL, dptr, "%d \n", reclen);
sim_activate(uptr, 10 + (10 * reclen));
sim_debug(DEBUG_DETAIL, dptr, "Write Mark unit=%d\n", unit);
uptr->u3 &= ~(MT_CMDMSK);
r = sim_tape_wrtmk(uptr);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
}
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
break;
case 3:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITEXP);
mt_busy[bufnum] &= ~1;
break;
}
break;
case MT_BSF:
switch(uptr->u4) {
case 0:
if (sim_tape_bot(uptr)) {
uptr->u3 &= ~MT_CMDMSK;
mt_busy[bufnum] &= ~1;
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
break;
}
uptr->u4 ++;
sim_activate(uptr, 500);
break;
case 1:
sim_debug(DEBUG_DETAIL, dptr, "Backspace file unit=%d\n", unit);
r = sim_tape_sprecr(uptr, &reclen);
if (r == MTSE_TMK) {
uptr->u4++;
sim_debug(DEBUG_DETAIL, dptr, "MARK\n");
sim_activate(uptr, 50);
} else if (r == MTSE_BOT) {
uptr->u4+= 2;
sim_activate(uptr, 50);
} else {
sim_activate(uptr, 10 + (10 * reclen));
}
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITEXP);
mt_busy[bufnum] &= ~1;
break;
case 3:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
mt_busy[bufnum] &= ~1;
break;
}
break;
case MT_FSR:
switch(uptr->u4) {
case 0:
uptr->u4 ++;
sim_activate(uptr, 500);
break;
case 1:
uptr->u4++;
sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d ", unit);
r = sim_tape_sprecf(uptr, &reclen);
if (r == MTSE_TMK) {
uptr->u4 = 3;
sim_debug(DEBUG_DETAIL, dptr, "MARK\n");
sim_activate(uptr, 50);
} else if (r == MTSE_EOM) {
uptr->u4 = 4;
sim_activate(uptr, 50);
} else {
sim_debug(DEBUG_DETAIL, dptr, "%d\n", reclen);
sim_activate(uptr, 10 + (10 * reclen));
case MT_BSR:
switch (uptr->u4 ) {
case 0:
if (sim_tape_bot(uptr)) {
uptr->u3 &= ~MT_CMDMSK;
mt_busy[GET_DEV_BUF(dptr->flags)] &= ~1;
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
return SCPE_OK;
}
uptr->u4 ++;
sim_activate(uptr, 500);
break;
case 1:
uptr->u4++;
sim_debug(DEBUG_DETAIL, dptr, "Backspace rec unit=%d ", unit);
r = sim_tape_sprecr(uptr, &reclen);
/* We don't set EOF on BSR */
if (r == MTSE_TMK) {
uptr->u4++;
sim_debug(DEBUG_DETAIL, dptr, "MARK\n");
sim_activate(uptr, 50);
} else {
sim_debug(DEBUG_DETAIL, dptr, "%d \n", reclen);
sim_activate(uptr, 10 + (10 * reclen));
}
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
break;
case 3:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITEXP);
mt_busy[bufnum] &= ~1;
break;
}
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
break;
case 3:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITEXP);
mt_busy[bufnum] &= ~1;
break;
case 4:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
mt_busy[bufnum] &= ~1;
break;
}
break;
case MT_FSF:
switch(uptr->u4) {
case 0:
uptr->u4 ++;
sim_activate(uptr, 500);
break;
case 1:
sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d ", unit);
r = sim_tape_sprecf(uptr, &reclen);
if (r == MTSE_TMK) {
uptr->u4++;
sim_debug(DEBUG_DETAIL, dptr, "MARK\n");
sim_activate(uptr, 50);
} else if (r == MTSE_EOM) {
uptr->u4+= 2;
sim_activate(uptr, 50);
} else {
sim_debug(DEBUG_DETAIL, dptr, "%d\n", reclen);
sim_activate(uptr, 10 + (10 * reclen));
case MT_BSF:
switch(uptr->u4) {
case 0:
if (sim_tape_bot(uptr)) {
uptr->u3 &= ~MT_CMDMSK;
mt_busy[bufnum] &= ~1;
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
break;
}
uptr->u4 ++;
sim_activate(uptr, 500);
break;
case 1:
sim_debug(DEBUG_DETAIL, dptr, "Backspace file unit=%d\n", unit);
r = sim_tape_sprecr(uptr, &reclen);
if (r == MTSE_TMK) {
uptr->u4++;
sim_debug(DEBUG_DETAIL, dptr, "MARK\n");
sim_activate(uptr, 50);
} else if (r == MTSE_BOT) {
uptr->u4+= 2;
sim_activate(uptr, 50);
} else {
sim_activate(uptr, 10 + (10 * reclen));
}
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITEXP);
mt_busy[bufnum] &= ~1;
break;
case 3:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
mt_busy[bufnum] &= ~1;
break;
}
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
sim_debug(DEBUG_DETAIL, dptr, "Skip done unit=%d\n", unit);
case MT_FSR:
switch(uptr->u4) {
case 0:
uptr->u4 ++;
sim_activate(uptr, 500);
break;
case 1:
uptr->u4++;
sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d ", unit);
r = sim_tape_sprecf(uptr, &reclen);
if (r == MTSE_TMK) {
uptr->u4 = 3;
sim_debug(DEBUG_DETAIL, dptr, "MARK\n");
sim_activate(uptr, 50);
} else if (r == MTSE_EOM) {
uptr->u4 = 4;
sim_activate(uptr, 50);
} else {
sim_debug(DEBUG_DETAIL, dptr, "%d\n", reclen);
sim_activate(uptr, 10 + (10 * reclen));
}
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
break;
case 3:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITEXP);
mt_busy[bufnum] &= ~1;
break;
case 4:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
mt_busy[bufnum] &= ~1;
break;
}
break;
case 3:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
mt_busy[bufnum] &= ~1;
case MT_FSF:
switch(uptr->u4) {
case 0:
uptr->u4 ++;
sim_activate(uptr, 500);
break;
case 1:
sim_debug(DEBUG_DETAIL, dptr, "Skip rec unit=%d ", unit);
r = sim_tape_sprecf(uptr, &reclen);
if (r == MTSE_TMK) {
uptr->u4++;
sim_debug(DEBUG_DETAIL, dptr, "MARK\n");
sim_activate(uptr, 50);
} else if (r == MTSE_EOM) {
uptr->u4+= 2;
sim_activate(uptr, 50);
} else {
sim_debug(DEBUG_DETAIL, dptr, "%d\n", reclen);
sim_activate(uptr, 10 + (10 * reclen));
}
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
sim_debug(DEBUG_DETAIL, dptr, "Skip done unit=%d\n", unit);
break;
case 3:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
mt_busy[bufnum] &= ~1;
break;
}
break;
}
break;
case MT_ERG:
switch (uptr->u4) {
case 0:
if (sim_tape_wrp(uptr)) {
uptr->u5 |= SNS_CMDREJ;
uptr->u3 &= ~MT_CMDMSK;
mt_busy[bufnum] &= ~1;
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
} else {
case MT_ERG:
switch (uptr->u4) {
case 0:
if (sim_tape_wrp(uptr)) {
uptr->u5 |= SNS_CMDREJ;
uptr->u3 &= ~MT_CMDMSK;
mt_busy[bufnum] &= ~1;
set_devattn(addr, SNS_DEVEND|SNS_UNITCHK);
} else {
uptr->u4 ++;
sim_activate(uptr, 500);
}
break;
case 1:
sim_debug(DEBUG_DETAIL, dptr, "Erase unit=%d\n", unit);
r = sim_tape_wrgap(uptr, 35);
sim_activate(uptr, 5000);
uptr->u4++;
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
}
break;
case MT_REW:
if (uptr->u4 == 0) {
uptr->u4 ++;
sim_activate(uptr, 500);
sim_activate(uptr, 30000);
mt_busy[bufnum] &= ~1;
} else {
sim_debug(DEBUG_DETAIL, dptr, "Rewind unit=%d\n", unit);
uptr->u3 &= ~(MT_CMDMSK);
r = sim_tape_rewind(uptr);
set_devattn(addr, SNS_DEVEND);
}
break;
case 1:
sim_debug(DEBUG_DETAIL, dptr, "Erase unit=%d\n", unit);
r = sim_tape_wrgap(uptr, 35);
sim_activate(uptr, 5000);
uptr->u4++;
case MT_RUN:
if (uptr->u4 == 0) {
uptr->u4 ++;
mt_busy[bufnum] &= ~1;
sim_activate(uptr, 30000);
} else {
sim_debug(DEBUG_DETAIL, dptr, "Unload unit=%d\n", unit);
uptr->u3 &= ~(MT_CMDMSK);
r = sim_tape_detach(uptr);
set_devattn(addr, SNS_DEVEND);
}
break;
case 2:
uptr->u3 &= ~(MT_CMDMSK);
set_devattn(addr, SNS_DEVEND);
mt_busy[bufnum] &= ~1;
}
break;
case MT_REW:
if (uptr->u4 == 0) {
uptr->u4 ++;
sim_activate(uptr, 30000);
mt_busy[bufnum] &= ~1;
} else {
sim_debug(DEBUG_DETAIL, dptr, "Rewind unit=%d\n", unit);
uptr->u3 &= ~(MT_CMDMSK);
r = sim_tape_rewind(uptr);
set_devattn(addr, SNS_DEVEND);
}
break;
case MT_RUN:
if (uptr->u4 == 0) {
uptr->u4 ++;
mt_busy[bufnum] &= ~1;
sim_activate(uptr, 30000);
} else {
sim_debug(DEBUG_DETAIL, dptr, "Unload unit=%d\n", unit);
uptr->u3 &= ~(MT_CMDMSK);
r = sim_tape_detach(uptr);
set_devattn(addr, SNS_DEVEND);
}
break;
}
return SCPE_OK;
}

View File

@@ -477,6 +477,7 @@ t_opcode *tab;
fprintf(of, "%d)", (val[2] >> 12) & 0xf);
break;
}
break;
}
}
}