Initial public version of Manchester SSEM for SIMH
Initial public version of Manchester University Small Scale Experimental Machine (SSEM) for SIMH
This commit is contained in:
parent
02ebf6bdfc
commit
b97bc9e004
3 changed files with 767 additions and 0 deletions
259
SSEM/ssem_cpu.c
Normal file
259
SSEM/ssem_cpu.c
Normal file
|
@ -0,0 +1,259 @@
|
|||
/* ssem_cpu.c: SSEM (Small Scale Experimental Machine) CPU simulator
|
||||
|
||||
Based on the SIMH package written by Robert M Supnik
|
||||
|
||||
Copyright (c) 2006-2008, Gerardo Ospina
|
||||
|
||||
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
|
||||
THE AUTHOR 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 the author shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the author.
|
||||
|
||||
This is not a supported product, but the author welcomes bug reports and fixes.
|
||||
Mail to ngospina@panix.com
|
||||
|
||||
cpu SSEM CPU
|
||||
|
||||
The system state for the SSEM is:
|
||||
|
||||
A[0]<0:31> accumulator
|
||||
C[0]<0:31> current instruction
|
||||
C[1]<0:31> present instruction
|
||||
|
||||
The SSEM has just one instruction format:
|
||||
|
||||
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| |inst | |address |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
SSEM instructions:
|
||||
|
||||
<13:15> operation
|
||||
|
||||
000 0 C[0] <- S[n]
|
||||
001 1 C[0] <- C[0] + S[n]
|
||||
010 2 A[0] <- -S[n]
|
||||
011 3 S[n] <- A[0]
|
||||
100 4 A[0] <- A[0] - S[n]
|
||||
110 6 C[0] <- C[0] + 1 if (A[0] < 0)
|
||||
111 7 Stop the machine
|
||||
|
||||
The SSEM has 32 32b words of memory.
|
||||
|
||||
This routine is the instruction decode routine for the SSEM.
|
||||
It is called from the simulator control program to execute
|
||||
instructions in simulated memory, starting at the simulated
|
||||
CI. It runs until 'reason' is set non-zero.
|
||||
|
||||
General notes:
|
||||
|
||||
1. Reasons to stop. The simulator can be stopped by:
|
||||
|
||||
Stop instruction
|
||||
breakpoint encountered
|
||||
|
||||
2. Interrupts. There are no interrupts.
|
||||
|
||||
3. Non-existent memory. All of memory always exists.
|
||||
|
||||
4. Adding I/O devices. The SSEM could not support additional
|
||||
I/O devices.
|
||||
*/
|
||||
|
||||
#include "ssem_defs.h"
|
||||
|
||||
uint32 S[MEMSIZE] = { 0 }; /* storage (memory) */
|
||||
|
||||
int32 A[MEMSIZE] = { 0 }; /* A[0] accumulator */
|
||||
uint32 C[MEMSIZE] = { 0, 0 }; /* C[0] current instruction */
|
||||
/* C[1] present instruction */
|
||||
uint32 Staticisor = 0;
|
||||
|
||||
extern int32 sim_interval;
|
||||
extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
extern int32 sim_step;
|
||||
|
||||
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat cpu_reset (DEVICE *dptr);
|
||||
t_stat cpu_one_inst (uint32 opc, uint32 ir);
|
||||
|
||||
/* CPU data structures
|
||||
|
||||
cpu_dev CPU device descriptor
|
||||
cpu_unit CPU unit descriptor
|
||||
cpu_reg CPU register list
|
||||
cpu_mod CPU modifiers list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX, MEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
{ DRDATA (CI, C[0], 5), REG_VMAD },
|
||||
{ HRDATA (A, A[0], 32), REG_VMIO },
|
||||
{ HRDATA (PI, C[1], 32), REG_VMIO + REG_HRO },
|
||||
{ HRDATA (LF, Staticisor, 32), REG_VMIO + REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB cpu_mod[] = {
|
||||
{ UNIT_SSEM, 0, "Manchester SSEM (Small Scale Experimental Machine)", "SSEM" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE cpu_dev = {
|
||||
"CPU", &cpu_unit, cpu_reg, cpu_mod,
|
||||
1, 10, 5, 1, 16, 32,
|
||||
&cpu_ex, &cpu_dep, &cpu_reset,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
t_stat sim_instr (void)
|
||||
{
|
||||
t_stat reason = 0;
|
||||
|
||||
sim_cancel_step (); /* defang SCP step */
|
||||
|
||||
/* Main instruction fetch/decode loop */
|
||||
do {
|
||||
|
||||
if (sim_interval <= 0) { /* check clock queue */
|
||||
#if !UNIX_PLATFORM
|
||||
if ((reason = sim_poll_kbd()) == SCPE_STOP) { /* poll on platforms without reliable signalling */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (reason = sim_process_event ()) break;
|
||||
}
|
||||
|
||||
if (sim_brk_summ && /* breakpoint? */
|
||||
sim_brk_test (*C, SWMASK ('E'))) {
|
||||
reason = STOP_IBKPT; /* stop simulation */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Increment current instruction */
|
||||
*C = (*C + 1) & AMASK;
|
||||
|
||||
/* Get present instruction */
|
||||
C[1] = Read (*C);
|
||||
|
||||
Staticisor = C[1] & IMASK; /* get instruction */
|
||||
sim_interval = sim_interval - 1;
|
||||
|
||||
if (reason = cpu_one_inst (*C, Staticisor)) { /* one instr; error? */
|
||||
break;
|
||||
}
|
||||
|
||||
if (sim_step && (--sim_step <= 0)) /* do step count */
|
||||
reason = SCPE_STOP;
|
||||
|
||||
} while (reason == 0); /* loop until halted */
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
t_stat cpu_reset (DEVICE *dptr)
|
||||
{
|
||||
sim_brk_types = sim_brk_dflt = SWMASK ('E');
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Memory examine */
|
||||
|
||||
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
|
||||
{
|
||||
if (addr >= MEMSIZE) return SCPE_NXM;
|
||||
if (vptr != NULL) *vptr = Read (addr);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Memory deposit */
|
||||
|
||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
|
||||
{
|
||||
if (addr >= MEMSIZE) return SCPE_NXM;
|
||||
Write (addr, val);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Execute one instruction */
|
||||
|
||||
t_stat cpu_one_inst (uint32 opc, uint32 ir)
|
||||
{
|
||||
uint32 ea, op;
|
||||
t_stat reason = 0;
|
||||
|
||||
op = I_GETOP (ir); /* opcode */
|
||||
switch (op) { /* case on opcode */
|
||||
|
||||
case OP_JUMP_INDIRECT: /* C[0] <- S[ea] */
|
||||
ea = I_GETEA (ir); /* address */
|
||||
*C = Read(ea);
|
||||
break;
|
||||
|
||||
case OP_JUMP_INDIRECT_RELATIVE: /* C[0] <- C[0] + S[ea] */
|
||||
ea = I_GETEA (ir); /* address */
|
||||
*C += Read(ea);
|
||||
break;
|
||||
|
||||
case OP_LOAD_NEGATED: /* A[0] <- -S[ea] */
|
||||
ea = I_GETEA (ir); /* address */
|
||||
*A = -((int32)Read(ea));
|
||||
break;
|
||||
|
||||
case OP_STORE: /* S[ea] <- A[0] */
|
||||
ea = I_GETEA (ir); /* address */
|
||||
Write(ea, (uint32) *A);
|
||||
break;
|
||||
|
||||
case OP_SUBSTRACT: /* A[0] <- A[0] - S[ea] */
|
||||
case OP_UNDOCUMENTED:
|
||||
ea = I_GETEA (ir); /* address */
|
||||
*A -= ((int32) Read(ea));
|
||||
break;
|
||||
|
||||
case OP_TEST: /* C[0] <- C[0] + 1 if (A[0] < 0) */
|
||||
if (*A < 0){
|
||||
*C += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_STOP: /* Stop the machine */
|
||||
reason = STOP_STOP; /* stop simulation */
|
||||
break;
|
||||
} /* end switch */
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
/* Support routines */
|
||||
|
||||
uint32 Read (uint32 ea)
|
||||
{
|
||||
return S[ea] & MMASK;
|
||||
}
|
||||
|
||||
void Write (uint32 ea, uint32 dat)
|
||||
{
|
||||
S[ea] = dat & MMASK;
|
||||
return;
|
||||
}
|
82
SSEM/ssem_defs.h
Normal file
82
SSEM/ssem_defs.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
/* ssem_defs.h: SSEM (Small Scale Experimental Machine) simulator definitions
|
||||
|
||||
Based on the SIMH package written by Robert M Supnik
|
||||
|
||||
Copyright (c) 2006-2008 Gerardo Ospina
|
||||
|
||||
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
|
||||
THE AUTHOR 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 the author shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the author.
|
||||
|
||||
This is not a supported product, but the author welcomes bug reports and fixes.
|
||||
Mail to ngospina@panix.com
|
||||
*/
|
||||
|
||||
#ifndef _SSEM_DEFS_H_
|
||||
#define _SSEM_DEFS_H_ 0
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_STOP 1 /* STOP */
|
||||
#define STOP_IBKPT 2 /* breakpoint */
|
||||
|
||||
/* Memory */
|
||||
|
||||
#define MEMSIZE 32 /* memory size */
|
||||
#define AMASK 0x1F /* addr mask */
|
||||
|
||||
/* Architectural constants */
|
||||
|
||||
#define MMASK 0xFFFFFFFF /* memory mask */
|
||||
#define IMASK 0x0000E01F /* instruction mask */
|
||||
#define UMASK 0xFFFF1FE0 /* unused bits mask */
|
||||
#define SMASK 0x80000000 /* sign mask */
|
||||
|
||||
/* Instruction format */
|
||||
|
||||
#define I_M_OP 0x07 /* opcode */
|
||||
#define I_V_OP 13
|
||||
#define I_OP (I_M_OP << I_V_OP)
|
||||
#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP)
|
||||
#define I_M_EA AMASK /* address */
|
||||
#define I_V_EA 0
|
||||
#define I_EA (I_M_EA)
|
||||
#define I_GETEA(x) ((x) & I_M_EA)
|
||||
|
||||
/* Unit flags */
|
||||
|
||||
#define UNIT_V_SSEM (UNIT_V_UF + 0)
|
||||
#define UNIT_SSEM (1u << UNIT_V_SSEM)
|
||||
|
||||
/* Instructions */
|
||||
|
||||
enum opcodes {
|
||||
OP_JUMP_INDIRECT, OP_JUMP_INDIRECT_RELATIVE, OP_LOAD_NEGATED, OP_STORE,
|
||||
OP_SUBSTRACT, OP_UNDOCUMENTED, OP_TEST, OP_STOP
|
||||
};
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
uint32 Read (uint32 ea);
|
||||
void Write (uint32 ea, uint32 dat);
|
||||
|
||||
#endif
|
426
SSEM/ssem_sys.c
Normal file
426
SSEM/ssem_sys.c
Normal file
|
@ -0,0 +1,426 @@
|
|||
/* ssem_sys.c: SSEM (Small Scale Experimental Machine) simulator interface
|
||||
|
||||
Based on the SIMH package written by Robert M Supnik
|
||||
|
||||
Copyright (c) 2006-2008 Gerardo Ospina
|
||||
|
||||
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
|
||||
THE AUTHOR 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 the author shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the author.
|
||||
|
||||
This is not a supported product, but the author welcomes bug reports and fixes.
|
||||
Mail to ngospina@panix.com
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "ssem_defs.h"
|
||||
|
||||
extern uint32 S[];
|
||||
extern uint32 C[];
|
||||
extern int32 A[];
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern REG cpu_reg[];
|
||||
|
||||
/* SCP data structures and interface routines
|
||||
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax maximum number of words for examine/deposit
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
|
||||
fprint_sym memory examine
|
||||
parser_sym memory deposit
|
||||
*/
|
||||
|
||||
char sim_name[] = "SSEM";
|
||||
|
||||
REG *sim_PC = &cpu_reg[0];
|
||||
|
||||
int32 sim_emax = 1;
|
||||
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
"Unknown error",
|
||||
"Stop",
|
||||
"Breakpoint",
|
||||
};
|
||||
|
||||
/* SSEM binary dump */
|
||||
|
||||
t_stat ssem_dump (FILE *fi)
|
||||
{
|
||||
if (sim_fwrite(A, sizeof(int32), 1, fi) != 1 ||
|
||||
sim_fwrite(C, sizeof(uint32), 1, fi) != 1 ||
|
||||
sim_fwrite(S, sizeof(uint32), MEMSIZE, fi) != MEMSIZE) {
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* SSEM binary loader */
|
||||
|
||||
t_stat ssem_load_dmp (FILE *fi)
|
||||
{
|
||||
C[1] = 0;
|
||||
if (sim_fread(A, sizeof(int32), 1, fi) != 1 ||
|
||||
sim_fread(C, sizeof(uint32), 1, fi) != 1 ||
|
||||
sim_fread(S, sizeof(uint32), MEMSIZE, fi) != MEMSIZE) {
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Loader
|
||||
|
||||
Inputs:
|
||||
*fi = input stream
|
||||
*cptr = VM-specific arguments
|
||||
*fnam = file name
|
||||
flag = 1 = dump, 0 = load
|
||||
Outputs:
|
||||
return = status code
|
||||
*/
|
||||
|
||||
t_stat sim_load (FILE *fi, char *cptr, char *fnam, int flag)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = strlen(fnam);
|
||||
if (len <= 4 || strcmp(fnam + (len - 4), ".dmp") != 0) return SCPE_ARG;
|
||||
|
||||
if (flag == 1) return ssem_dump(fi);
|
||||
return ssem_load_dmp(fi);
|
||||
}
|
||||
|
||||
/* Utility routine - prints number in decimal */
|
||||
|
||||
t_stat ssem_fprint_decimal (FILE *of, uint32 inst)
|
||||
{
|
||||
if (inst & SMASK)
|
||||
fprintf (of, "%d [%u]", inst, inst);
|
||||
else
|
||||
fprintf (of, "%d", inst);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Utility routine - prints number in backward binary */
|
||||
|
||||
t_stat ssem_fprint_binary_number (FILE *of, uint32 inst, uint8 nbits)
|
||||
{
|
||||
int i;
|
||||
uint32 n;
|
||||
|
||||
n = inst;
|
||||
for (i = 0; i < nbits; i++) {
|
||||
fprintf(of, "%d", n & 1 ? 1 : 0);
|
||||
n >>= 1;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Utility routine - prints instruction in backward binary */
|
||||
|
||||
t_stat ssem_fprint_binary (FILE *of, uint32 inst, int flag)
|
||||
{
|
||||
uint32 op, ea;
|
||||
|
||||
if (!flag) return ssem_fprint_binary_number(of, inst, 32);
|
||||
|
||||
op = I_GETOP (inst);
|
||||
if (op != OP_TEST && op != OP_STOP) {
|
||||
ea = I_GETEA (inst);
|
||||
ssem_fprint_binary_number(of, ea, 5);
|
||||
fprintf (of, " ");
|
||||
}
|
||||
ssem_fprint_binary_number(of, op, 3);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Utility routine
|
||||
|
||||
prints instruction in the mnemomic style used in the 1998
|
||||
competition reference manual:
|
||||
"The Manchester University Small Scale Experimental Machine
|
||||
Programmer's Reference manual"
|
||||
http://www.computer50.org/mark1/prog98/ssemref.html
|
||||
*/
|
||||
|
||||
t_stat ssem_fprint_competition_mnemonic (FILE *of, uint32 inst)
|
||||
{
|
||||
uint32 op, ea;
|
||||
|
||||
op = I_GETOP (inst);
|
||||
switch (op) {
|
||||
case OP_JUMP_INDIRECT: /* JMP */
|
||||
ea = I_GETEA (inst);
|
||||
fprintf (of, "JMP %d", ea);
|
||||
break;
|
||||
|
||||
case OP_JUMP_INDIRECT_RELATIVE: /* JRP */
|
||||
ea = I_GETEA (inst);
|
||||
fprintf (of, "JRP %d", ea);
|
||||
break;
|
||||
|
||||
case OP_LOAD_NEGATED: /* LDN */
|
||||
ea = I_GETEA (inst);
|
||||
fprintf (of, "LDN %d", ea);
|
||||
break;
|
||||
|
||||
case OP_STORE: /* STO */
|
||||
ea = I_GETEA (inst);
|
||||
fprintf (of, "STO %d", ea);
|
||||
break;
|
||||
|
||||
case OP_SUBSTRACT: /* SUB */
|
||||
ea = I_GETEA (inst);
|
||||
fprintf (of, "SUB %d", ea);
|
||||
break;
|
||||
|
||||
case OP_UNDOCUMENTED: /* invalid instruction */
|
||||
return SCPE_ARG;
|
||||
|
||||
case OP_TEST: /* CMP */
|
||||
fprintf (of, "CMP");
|
||||
break;
|
||||
|
||||
case OP_STOP: /* STOP */
|
||||
fprintf (of, "STOP");
|
||||
break; /* end switch */
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Symbolic decode
|
||||
|
||||
Inputs:
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = pointer to data
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
Outputs:
|
||||
return = status code
|
||||
*/
|
||||
|
||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
uint32 inst;
|
||||
|
||||
if (sw & SWMASK ('H')) return SCPE_ARG; /* hexadecimal? */
|
||||
|
||||
inst = val[0];
|
||||
|
||||
if (sw & SWMASK ('D')) /* decimal? */
|
||||
return ssem_fprint_decimal(of, inst);
|
||||
|
||||
if (sw & SWMASK ('M')) { /* mnemomic? */
|
||||
return ssem_fprint_competition_mnemonic(of, inst);
|
||||
}
|
||||
|
||||
return ssem_fprint_binary(of, inst, sw & SWMASK ('I') || sw & SWMASK ('M'));
|
||||
}
|
||||
|
||||
static const char *opcode[] = {
|
||||
"JMP", "JRP", "LDN",
|
||||
"STO", "SUB", "",
|
||||
"CMP", "STOP",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Utility function - parses decimal number. */
|
||||
|
||||
t_stat parse_sym_d (char *cptr, t_value *val)
|
||||
{
|
||||
char *start;
|
||||
int n;
|
||||
|
||||
start = cptr;
|
||||
if (*cptr == '-') cptr++; /* skip sign */
|
||||
n = 0;
|
||||
while (*cptr >= '0' && *cptr <= '9') {
|
||||
n = (n * 10) + (*cptr - '0');
|
||||
cptr++;
|
||||
}
|
||||
if (*start == '-') n = -n;
|
||||
if (*start) *start = 'x';
|
||||
|
||||
if (*cptr) return SCPE_ARG; /* junk at end? */
|
||||
|
||||
*val = n;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Utility function
|
||||
|
||||
Parses mnemonic instruction.
|
||||
|
||||
It accepts the mnemonics used in the 1998 competition reference
|
||||
manual:
|
||||
"The Manchester University Small Scale Experimental Machine
|
||||
Programmer's Reference manual"
|
||||
http://www.computer50.org/mark1/prog98/ssemref.html
|
||||
*/
|
||||
|
||||
t_stat parse_sym_m (char *cptr, t_value *val)
|
||||
{
|
||||
char *start;
|
||||
uint32 n,a;
|
||||
char gbuf[CBUFSIZE];
|
||||
|
||||
start = cptr;
|
||||
cptr = get_glyph(cptr, gbuf, 0);
|
||||
if (*start) *start = 'x';
|
||||
|
||||
for (n = 0; opcode[n] != NULL && strcmp(opcode[n], gbuf) != 0; n++) ;
|
||||
if (opcode[n] == NULL) return SCPE_ARG; /* invalid mnemonic? */
|
||||
|
||||
if (!(*cptr) && n > OP_UNDOCUMENTED && n <= OP_STOP) {
|
||||
*val = n << I_V_OP; return SCPE_OK;
|
||||
}
|
||||
|
||||
while (isspace (*cptr)) cptr++; /* absorb spaces */
|
||||
|
||||
if (*cptr < '0' || *cptr > '9') return SCPE_ARG; /* address expected */
|
||||
|
||||
a = 0;
|
||||
while (*cptr >= '0' && *cptr <= '9') {
|
||||
a = (a * 10) + (*cptr - '0');
|
||||
cptr++;
|
||||
}
|
||||
|
||||
if (a >= MEMSIZE) return SCPE_ARG; /* invalid address? */
|
||||
|
||||
if (*cptr) return SCPE_ARG; /* junk at end? */
|
||||
|
||||
*val = (n << I_V_OP) + a;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Utility function - parses binary backward number. */
|
||||
|
||||
t_stat parse_sym_b (char *cptr, t_value *val)
|
||||
{
|
||||
char *start;
|
||||
int count;
|
||||
t_value n;
|
||||
|
||||
start = cptr;
|
||||
count = 0;
|
||||
n = 0;
|
||||
while (*cptr == '0' || *cptr == '1') {
|
||||
n = n + ((*cptr - '0') << count);
|
||||
count++;
|
||||
cptr++;
|
||||
}
|
||||
if (*start) *start = 'x';
|
||||
|
||||
if (*cptr) return SCPE_ARG; /* junk at end? */
|
||||
|
||||
*val = n;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Utility function - parses binary backward instruccion. */
|
||||
|
||||
t_stat parse_sym_i (char *cptr, t_value *val)
|
||||
{
|
||||
char *start;
|
||||
int count;
|
||||
t_value a,n;
|
||||
|
||||
start = cptr;
|
||||
count = 0;
|
||||
n = 0;
|
||||
while (*cptr == '0' || *cptr == '1') {
|
||||
n = n + ((*cptr - '0') << count);
|
||||
count++;
|
||||
cptr++;
|
||||
}
|
||||
if (*start) *start = 'x';
|
||||
|
||||
if (!(*cptr) && n > OP_UNDOCUMENTED && n <= OP_STOP) {
|
||||
*val = n << I_V_OP; return SCPE_OK;
|
||||
}
|
||||
|
||||
a = n;
|
||||
if (a >= MEMSIZE) return SCPE_ARG; /* invalid addresss */
|
||||
|
||||
while (isspace (*cptr)) cptr++; /* absorb spaces */
|
||||
|
||||
if (*cptr != '0' && *cptr != '1') return SCPE_ARG; /* instruction expected */
|
||||
|
||||
count = 0;
|
||||
n = 0;
|
||||
while (*cptr == '0' || *cptr == '1') {
|
||||
n = n + ((*cptr - '0') << count);
|
||||
count++;
|
||||
cptr++;
|
||||
}
|
||||
if (n >= OP_UNDOCUMENTED) return SCPE_ARG; /* invalid instruction? */
|
||||
|
||||
if (*cptr) return SCPE_ARG; /* junk at end? */
|
||||
|
||||
*val = (n << I_V_OP) + a;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Symbolic input
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*uptr = pointer to unit
|
||||
*val = pointer to output values
|
||||
sw = switches
|
||||
Outputs:
|
||||
status = error status
|
||||
*/
|
||||
|
||||
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||
{
|
||||
|
||||
if (sw & SWMASK ('H')) return SCPE_ARG; /* hexadecimal? */
|
||||
|
||||
while (isspace (*cptr)) cptr++; /* absorb spaces */
|
||||
|
||||
if (sw & SWMASK ('D')) { /* decimal? */
|
||||
return parse_sym_d (cptr, val);
|
||||
}
|
||||
|
||||
if (sw & SWMASK ('I')) { /* backward binary instruction? */
|
||||
return parse_sym_i (cptr, val);
|
||||
}
|
||||
|
||||
if (sw & SWMASK ('M')) { /* mnemonic? */
|
||||
return parse_sym_m (cptr, val);
|
||||
}
|
||||
|
||||
return parse_sym_b(cptr, val); /* backward binary number */
|
||||
}
|
Loading…
Add table
Reference in a new issue