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:
parent
c45878feb3
commit
b1d0eb3492
1 changed files with 87 additions and 21 deletions
|
@ -154,6 +154,7 @@ uint8 loading; /* Set when loading */
|
||||||
uint8 HALT; /* Set when halt requested */
|
uint8 HALT; /* Set when halt requested */
|
||||||
uint8 P1_run; /* Run flag for P1 */
|
uint8 P1_run; /* Run flag for P1 */
|
||||||
uint8 P2_run; /* Run flag for P2 */
|
uint8 P2_run; /* Run flag for P2 */
|
||||||
|
uint16 idle_addr = 0; /* Address of idle loop */
|
||||||
|
|
||||||
|
|
||||||
struct InstHistory
|
struct InstHistory
|
||||||
|
@ -218,7 +219,7 @@ int32 rtc_tps = 60 ;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UNIT cpu_unit[] =
|
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 }};
|
{ UDATA(0, UNIT_DISABLE|UNIT_DIS, 0 ), 0 }};
|
||||||
|
|
||||||
REG cpu_reg[] = {
|
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(6), NULL, "28K", &cpu_set_size},
|
||||||
{UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(7), NULL, "32K", &cpu_set_size},
|
{UNIT_MSIZE|MTAB_VDV, MEMAMOUNT(7), NULL, "32K", &cpu_set_size},
|
||||||
{MTAB_VDV, 0, "MEMORY", NULL, NULL, &cpu_show_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",
|
{MTAB_XTD | MTAB_VDV | MTAB_NMO | MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||||
&cpu_set_hist, &cpu_show_hist},
|
&cpu_set_hist, &cpu_show_hist},
|
||||||
{0}
|
{0}
|
||||||
|
@ -305,21 +308,21 @@ DEVICE cpu_dev = {
|
||||||
#define HLTF hltf[cpu_index]
|
#define HLTF hltf[cpu_index]
|
||||||
|
|
||||||
/* Definitions to help extract fields */
|
/* Definitions to help extract fields */
|
||||||
#define FF(x) ((uint16)(((x) >> FFIELD_V) & CORE))
|
#define FF(x) (uint16)(((x) & FFIELD) >> FFIELD_V)
|
||||||
#define CF(x) ((uint16)((x) & CORE))
|
#define CF(x) (uint16) ((x) & CORE)
|
||||||
#define LF(x) ((uint8)(((x) & RL) >> RL_V) & 03)
|
#define LF(x) (uint16)(((x) & RL) >> RL_V)
|
||||||
#define RF(x) (uint16)(((x) & RFIELD) >> RFIELD_V)
|
#define RF(x) (uint16)(((x) & RFIELD) >> RFIELD_V)
|
||||||
|
|
||||||
#define toF(x) (((t_uint64)((x) & CORE)) << FFIELD_V)
|
#define toF(x) ((((t_uint64)(x)) << FFIELD_V) & FFIELD)
|
||||||
#define toC(x) ((t_uint64)((x) & CORE))
|
#define toC(x) (((t_uint64)(x)) & CORE)
|
||||||
#define toL(x) (((t_uint64)(x)) << RL_V)
|
#define toL(x) ((((t_uint64)(x)) << RL_V) & RL)
|
||||||
#define toR(x) (((t_uint64)(x)) << RFIELD_V)
|
#define toR(x) ((((t_uint64)(x)) << RFIELD_V) & RFIELD)
|
||||||
|
|
||||||
#define replF(y, x) ((y & ~FFIELD) | toF(x))
|
#define replF(y, x) ((y & ~FFIELD) | toF(x))
|
||||||
#define replC(y, x) ((y & ~CORE) | toC(x))
|
#define replC(y, x) ((y & ~CORE) | toC(x))
|
||||||
|
|
||||||
#define next_addr(x) (x = (x + 1) & CORE)
|
#define next_addr(x) (x = (x + 1) & 077777)
|
||||||
#define prev_addr(x) (x = (x - 1) & CORE)
|
#define prev_addr(x) (x = (x - 1) & 077777)
|
||||||
|
|
||||||
/* Definitions to handle building of control words */
|
/* Definitions to handle building of control words */
|
||||||
#define MSCW (FLAG | DFLAG | toR(R) | toF(F) | \
|
#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. */
|
/* Math helper routines. */
|
||||||
|
|
||||||
|
@ -1807,7 +1863,7 @@ void double_divide() {
|
||||||
|
|
||||||
void relativeAddr(int store) {
|
void relativeAddr(int store) {
|
||||||
uint16 base = R;
|
uint16 base = R;
|
||||||
uint16 addr = (A & 01777);
|
uint16 addr = (uint16)(A & 01777);
|
||||||
|
|
||||||
if (SALF) {
|
if (SALF) {
|
||||||
switch ((addr >> 7) & 7) {
|
switch ((addr >> 7) & 7) {
|
||||||
|
@ -2111,7 +2167,7 @@ crf_loop:
|
||||||
L = 0;
|
L = 0;
|
||||||
} else {
|
} else {
|
||||||
C = CF(B);
|
C = CF(B);
|
||||||
L = RF(B) + 1;
|
L = LF(B) + 1;
|
||||||
if (L > 3) {
|
if (L > 3) {
|
||||||
L = 0;
|
L = 0;
|
||||||
next_addr(C);
|
next_addr(C);
|
||||||
|
@ -2152,7 +2208,7 @@ crf_loop:
|
||||||
field--;
|
field--;
|
||||||
}
|
}
|
||||||
B &= FLAG|FWORD;
|
B &= FLAG|FWORD;
|
||||||
GH = (B >> 12) & 070;
|
GH = (uint8)((B >> 12) & 070);
|
||||||
Ma = CF(B);
|
Ma = CF(B);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2172,7 +2228,7 @@ crf_loop:
|
||||||
field--;
|
field--;
|
||||||
}
|
}
|
||||||
BROF = 0;
|
BROF = 0;
|
||||||
KV = (temp >> 12) & 070;
|
KV = (uint8)((temp >> 12) & 070);
|
||||||
S = CF(temp);
|
S = CF(temp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2181,7 +2237,8 @@ crf_loop:
|
||||||
AROF = BROF;
|
AROF = BROF;
|
||||||
B = toF(F) | toL(L) | toC(C);
|
B = toF(F) | toL(L) | toC(C);
|
||||||
F = S;
|
F = S;
|
||||||
S = CF(FF(B) - field);
|
S = FF(B);
|
||||||
|
S = (S - field) & CORE;
|
||||||
memory_cycle(013); /* Store B in S */
|
memory_cycle(013); /* Store B in S */
|
||||||
S = F;
|
S = F;
|
||||||
F = FF(B);
|
F = FF(B);
|
||||||
|
@ -2313,7 +2370,8 @@ crf_loop:
|
||||||
A = toC(F);
|
A = toC(F);
|
||||||
B = R >> 6;
|
B = R >> 6;
|
||||||
F = S;
|
F = S;
|
||||||
S = CF(CF(A) - field);
|
S = CF(A);
|
||||||
|
S = (S - field) & CORE;
|
||||||
memory_cycle(11);
|
memory_cycle(11);
|
||||||
S = F;
|
S = F;
|
||||||
F = CF(A);
|
F = CF(A);
|
||||||
|
@ -2839,7 +2897,7 @@ desc:
|
||||||
if (A & FLAG) {
|
if (A & FLAG) {
|
||||||
/* Check if it is a control word. */
|
/* Check if it is a control word. */
|
||||||
if ((A & DFLAG) != 0 && (A & PROGF) == 0) {
|
if ((A & DFLAG) != 0 && (A & PROGF) == 0) {
|
||||||
A = toC(Ma) | PRESENT | FLAG;
|
A = FLAG | PRESENT | toC(Ma);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Check if descriptor present */
|
/* Check if descriptor present */
|
||||||
|
@ -2854,10 +2912,10 @@ desc:
|
||||||
} else {
|
} else {
|
||||||
if (indexWord())
|
if (indexWord())
|
||||||
break;
|
break;
|
||||||
A |= FLAG|PRESENT;
|
A |= FLAG | PRESENT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
A = toC(Ma) | FLAG | PRESENT;
|
A = FLAG | PRESENT | toC(Ma);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2950,7 +3008,14 @@ control:
|
||||||
q_reg[1] &= ~STK_OVERFL;
|
q_reg[1] &= ~STK_OVERFL;
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
break;
|
||||||
}
|
}
|
||||||
sim_debug(DEBUG_DETAIL, &cpu_dev, "IAR=%05o Q=%03o\n\r",
|
sim_debug(DEBUG_DETAIL, &cpu_dev, "IAR=%05o Q=%03o\n\r",
|
||||||
|
@ -3396,7 +3461,7 @@ control:
|
||||||
next_addr(Ma);
|
next_addr(Ma);
|
||||||
memory_cycle(4);
|
memory_cycle(4);
|
||||||
}
|
}
|
||||||
A = toC(Ma) | FLAG | PRESENT;
|
A = FLAG | PRESENT | toC(Ma);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -3716,6 +3781,7 @@ cpu_reset(DEVICE * dptr)
|
||||||
hltf[0] = 0;
|
hltf[0] = 0;
|
||||||
P1_run = 0;
|
P1_run = 0;
|
||||||
|
|
||||||
|
idle_addr = 0;
|
||||||
sim_brk_types = sim_brk_dflt = SWMASK('E') | SWMASK('A') | SWMASK('B');
|
sim_brk_types = sim_brk_dflt = SWMASK('E') | SWMASK('A') | SWMASK('B');
|
||||||
hst_p = 0;
|
hst_p = 0;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue