B5500: Added CPU Idle support, clean minor bugs.

b5500_cpu.c: Added idle support to cpu. Cleaned up some
        bugs introduced when cleaning up compiler warnings.
This commit is contained in:
Richard Cornwell 2016-02-08 17:09:29 -05:00
parent c45878feb3
commit b1d0eb3492

View file

@ -154,6 +154,7 @@ uint8 loading; /* Set when loading */
uint8 HALT; /* Set when halt requested */
uint8 P1_run; /* Run flag for P1 */
uint8 P2_run; /* Run flag for P2 */
uint16 idle_addr = 0; /* Address of idle loop */
struct InstHistory
@ -218,7 +219,7 @@ int32 rtc_tps = 60 ;
*/
UNIT cpu_unit[] =
{{ UDATA(rtc_srv, MEMAMOUNT(7), MAXMEMSIZE ), 16667 },
{{ UDATA(rtc_srv, MEMAMOUNT(7)|UNIT_IDLE, MAXMEMSIZE ), 16667 },
{ UDATA(0, UNIT_DISABLE|UNIT_DIS, 0 ), 0 }};
REG cpu_reg[] = {
@ -262,6 +263,8 @@ MTAB cpu_mod[] = {
{UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(6), NULL, "28K", &cpu_set_size},
{UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(7), NULL, "32K", &cpu_set_size},
{MTAB_VDV, 0, "MEMORY", NULL, NULL, &cpu_show_size},
{MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },
{MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
{MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_SHP, 0, "HISTORY", "HISTORY",
&cpu_set_hist, &cpu_show_hist},
{0}
@ -305,21 +308,21 @@ DEVICE cpu_dev = {
#define HLTF hltf[cpu_index]
/* Definitions to help extract fields */
#define FF(x) ((uint16)(((x) >> FFIELD_V) & CORE))
#define CF(x) ((uint16)((x) & CORE))
#define LF(x) ((uint8)(((x) & RL) >> RL_V) & 03)
#define FF(x) (uint16)(((x) & FFIELD) >> FFIELD_V)
#define CF(x) (uint16) ((x) & CORE)
#define LF(x) (uint16)(((x) & RL) >> RL_V)
#define RF(x) (uint16)(((x) & RFIELD) >> RFIELD_V)
#define toF(x) (((t_uint64)((x) & CORE)) << FFIELD_V)
#define toC(x) ((t_uint64)((x) & CORE))
#define toL(x) (((t_uint64)(x)) << RL_V)
#define toR(x) (((t_uint64)(x)) << RFIELD_V)
#define toF(x) ((((t_uint64)(x)) << FFIELD_V) & FFIELD)
#define toC(x) (((t_uint64)(x)) & CORE)
#define toL(x) ((((t_uint64)(x)) << RL_V) & RL)
#define toR(x) ((((t_uint64)(x)) << RFIELD_V) & RFIELD)
#define replF(y, x) ((y & ~FFIELD) | toF(x))
#define replC(y, x) ((y & ~CORE) | toC(x))
#define next_addr(x) (x = (x + 1) & CORE)
#define prev_addr(x) (x = (x - 1) & CORE)
#define next_addr(x) (x = (x + 1) & 077777)
#define prev_addr(x) (x = (x - 1) & 077777)
/* Definitions to handle building of control words */
#define MSCW (FLAG | DFLAG | toR(R) | toF(F) | \
@ -936,6 +939,59 @@ void storeInterrupt(int forced, int test) {
}
}
/* Check if in idle loop.
assume that current instruction is ITI */
/* Typical idle loop for MCP is:
-1 ITI 0211
+0 TUS 2431
+1 OPDC address1 xxx2
+2 LOR 0215
+3 OPDC address2 xxx2
+4 NEQ 0425
+5 LITC 010 LITC 1 0040 0004
+6 BBC LBC 0131 2131
*/
int check_idle() {
static uint16 loop_data[7] = {
WMOP_TUS, WMOP_OPDC, WMOP_LOR, WMOP_OPDC,
WMOP_NEQ, WMOP_LITC, WMOP_BBC };
static uint16 loop_mask[7] = {
07777, 00003, 07777, 00003,
07777, 07733, 05777};
t_uint64 data;
uint16 addr = C;
int l = (3 - L) * 12;
uint16 word;
int i;
/* Quick check to see if not correct location */
if (idle_addr != 0 && idle_addr != addr)
return 0;
/* If address same, then idle loop */
if (idle_addr == addr)
return 1;
/* Not set, see if this could be loop */
data = M[addr];
for (i = 0; i < 7; i++) {
word = (uint16)(data >> l) & 07777;
if ((word & loop_mask[i]) != loop_data[i])
return 0;
if (l == 0) {
addr++;
l = 3 * 12;
data = M[addr];
} else {
l -= 12;
}
}
idle_addr = C;
return 1;
}
/* Math helper routines. */
@ -1807,7 +1863,7 @@ void double_divide() {
void relativeAddr(int store) {
uint16 base = R;
uint16 addr = (A & 01777);
uint16 addr = (uint16)(A & 01777);
if (SALF) {
switch ((addr >> 7) & 7) {
@ -2111,7 +2167,7 @@ crf_loop:
L = 0;
} else {
C = CF(B);
L = RF(B) + 1;
L = LF(B) + 1;
if (L > 3) {
L = 0;
next_addr(C);
@ -2152,7 +2208,7 @@ crf_loop:
field--;
}
B &= FLAG|FWORD;
GH = (B >> 12) & 070;
GH = (uint8)((B >> 12) & 070);
Ma = CF(B);
break;
@ -2172,7 +2228,7 @@ crf_loop:
field--;
}
BROF = 0;
KV = (temp >> 12) & 070;
KV = (uint8)((temp >> 12) & 070);
S = CF(temp);
break;
@ -2181,7 +2237,8 @@ crf_loop:
AROF = BROF;
B = toF(F) | toL(L) | toC(C);
F = S;
S = CF(FF(B) - field);
S = FF(B);
S = (S - field) & CORE;
memory_cycle(013); /* Store B in S */
S = F;
F = FF(B);
@ -2313,7 +2370,8 @@ crf_loop:
A = toC(F);
B = R >> 6;
F = S;
S = CF(CF(A) - field);
S = CF(A);
S = (S - field) & CORE;
memory_cycle(11);
S = F;
F = CF(A);
@ -2839,7 +2897,7 @@ desc:
if (A & FLAG) {
/* Check if it is a control word. */
if ((A & DFLAG) != 0 && (A & PROGF) == 0) {
A = toC(Ma) | PRESENT | FLAG;
A = FLAG | PRESENT | toC(Ma);
break;
}
/* Check if descriptor present */
@ -2854,10 +2912,10 @@ desc:
} else {
if (indexWord())
break;
A |= FLAG|PRESENT;
A |= FLAG | PRESENT;
}
} else {
A = toC(Ma) | FLAG | PRESENT;
A = FLAG | PRESENT | toC(Ma);
}
break;
@ -2950,7 +3008,14 @@ control:
q_reg[1] &= ~STK_OVERFL;
}
} else {
/* False IRQ */
/* Could be an idle loop, if P2 running, continue */
if (P2_run)
break;
if (sim_idle_enab) {
/* Check if possible idle loop */
if (check_idle())
sim_idle (TMR_RTC, FALSE);
}
break;
}
sim_debug(DEBUG_DETAIL, &cpu_dev, "IAR=%05o Q=%03o\n\r",
@ -3396,7 +3461,7 @@ control:
next_addr(Ma);
memory_cycle(4);
}
A = toC(Ma) | FLAG | PRESENT;
A = FLAG | PRESENT | toC(Ma);
break;
}
break;
@ -3716,6 +3781,7 @@ cpu_reset(DEVICE * dptr)
hltf[0] = 0;
P1_run = 0;
idle_addr = 0;
sim_brk_types = sim_brk_dflt = SWMASK('E') | SWMASK('A') | SWMASK('B');
hst_p = 0;