Skip to content

Instantly share code, notes, and snippets.

@shouth
Created September 27, 2021 05:34
Show Gist options
  • Save shouth/311e3788d6b8e706e6814dc350626937 to your computer and use it in GitHub Desktop.
Save shouth/311e3788d6b8e706e6814dc350626937 to your computer and use it in GitHub Desktop.
/*
* Project-based Learning II (CPU)
*
* Program: instruction set simulator of the Educational CPU Board
* File Name: cpuboard.c
* Descrioption: simulation(emulation) of an instruction
*/
#include "cpuboard.h"
Bit bit(Uword value, int digit)
{
return (value >> digit) & 1;
}
Bit is_add_carried(Uword a, Uword b)
{
return bit(a, 7) && bit(b, 7);
}
Bit is_sub_borrowed(Uword a, Uword b)
{
return a < b;
}
Bit is_left_shift_carried(Uword a)
{
return bit(a, 7);
}
Bit is_right_shift_carried(Uword a)
{
return bit(a, 0);
}
Bit is_add_sub_overflowed(Uword a, Uword b)
{
Uword value = a + b;
return (bit(a, 7) == bit(b, 7)) && (bit(a, 7) != bit(a + b, 7));
}
Bit is_left_shift_overflowed(Uword a)
{
return bit(a, 7) ^ bit(a << 1, 7);
}
Bit is_negative(Uword value)
{
return bit(value, 7);
}
Bit is_zero(Uword value)
{
return value == 0;
}
Uword get_operand_a(Uword inst, Cpub *cpub)
{
switch (bit(inst, 3)) {
case 0x0:
return cpub->acc;
case 0x1:
return cpub->ix;
}
}
void set_operand_a(Uword inst, Cpub *cpub, Uword value)
{
switch (bit(inst, 3)) {
case 0x0:
cpub->acc = value;
return;
case 0x1:
cpub->ix = value;
return;
}
}
Uword get_operand_b(Uword inst, Cpub *cpub)
{
Addr mar;
switch (inst & 0x07) {
case 0x0:
return cpub->acc;
case 0x1:
return cpub->ix;
case 0x2:
case 0x3:
mar = cpub->pc++;
return cpub->mem[mar];
}
mar = cpub->pc++;
switch (inst & 0x07) {
case 0x4:
mar = cpub->mem[mar];
break;
case 0x5:
mar = cpub->mem[mar] + 0x100;
break;
case 0x6:
mar = cpub->ix + cpub->mem[mar];
break;
case 0x7:
mar = cpub->ix + cpub->mem[mar] + 0x100;
break;
}
return cpub->mem[mar];
}
int set_operand_b(Uword inst, Cpub *cpub, Uword value)
{
Addr mar = cpub->pc++;
switch (inst & 0x07) {
case 0x4:
mar = cpub->mem[mar];
break;
case 0x5:
mar = cpub->mem[mar] + 0x100;
break;
case 0x6:
mar = cpub->ix + cpub->mem[mar];
break;
case 0x7:
mar = cpub->ix + cpub->mem[mar] + 0x100;
break;
default:
return -1;
}
cpub->mem[mar] = value;
return 0;
}
int nop(Uword inst, Cpub *cpub)
{
return RUN_STEP;
}
int hlt(Uword inst, Cpub *cpub)
{
return RUN_HALT;
}
int out(Uword inst, Cpub *cpub)
{
cpub->obuf.buf = cpub->acc;
cpub->obuf.flag = 1;
return RUN_STEP;
}
int in(Uword inst, Cpub *cpub)
{
cpub->acc = cpub->ibuf->buf;
cpub->ibuf->flag = 0;
return RUN_STEP;
}
int rcf(Uword inst, Cpub *cpub)
{
cpub->cf = 0;
return RUN_STEP;
}
int scf(Uword inst, Cpub *cpub)
{
cpub->cf = 1;
return RUN_STEP;
}
int ld(Uword inst, Cpub *cpub)
{
Uword b = get_operand_b(inst, cpub);
set_operand_a(inst, cpub, b);
return RUN_STEP;
}
int st(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
int res = set_operand_b(inst, cpub, a);
return res < 0 ? RUN_HALT : RUN_STEP;
}
int add(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword b = get_operand_b(inst, cpub);
Uword value = a + b;
set_operand_a(inst, cpub, value);
cpub->vf = is_add_sub_overflowed(a, b);
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int adc(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword b = get_operand_b(inst, cpub);
Uword cf = cpub->cf;
Uword value = a + b + cf;
set_operand_a(inst, cpub, value);
cpub->cf = is_add_carried(a, b) || is_add_carried(a + b, cf);
cpub->vf = is_add_sub_overflowed(a, b) || is_add_sub_overflowed(a + b, cf);
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int sub(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword b = get_operand_b(inst, cpub);
Uword value = a - b;
set_operand_a(inst, cpub, value);
cpub->vf = is_add_sub_overflowed(a, -b);
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int sbc(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword b = get_operand_b(inst, cpub);
Uword cf = cpub->cf;
Uword value = a - b - cf;
set_operand_a(inst, cpub, value);
cpub->cf = is_sub_borrowed(a, b) || is_sub_borrowed(a - b, cf);
cpub->vf = is_add_sub_overflowed(a, -b) || is_add_sub_overflowed(a - b, -cf);
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int cmp(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword b = get_operand_b(inst, cpub);
Uword value = a - b;
cpub->vf = is_add_sub_overflowed(a, -b);
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int and(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword b = get_operand_b(inst, cpub);
Uword value = a & b;
set_operand_a(inst, cpub, value);
cpub->vf = 0;
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int or(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword b = get_operand_b(inst, cpub);
Uword value = a | b;
set_operand_a(inst, cpub, value);
cpub->vf = 0;
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int eor(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword b = get_operand_b(inst, cpub);
Uword value = a ^ b;
set_operand_a(inst, cpub, value);
cpub->vf = 0;
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int sra(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword value = (bit(a, 7) << 7) | (a >> 1);
set_operand_a(inst, cpub, value);
cpub->cf = is_right_shift_carried(a);
cpub->vf = 0;
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int sla(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword value = a << 1;
set_operand_a(inst, cpub, value);
cpub->cf = is_left_shift_carried(a);
cpub->vf = is_left_shift_overflowed(a);
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int srl(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword value = a >> 1;
set_operand_a(inst, cpub, value);
cpub->cf = is_right_shift_carried(a);
cpub->vf = 0;
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int sll(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword value = a << 1;
set_operand_a(inst, cpub, value);
cpub->cf = is_left_shift_carried(a);
cpub->vf = 0;
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int rra(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword cf = cpub->cf;
Uword value = (cf << 7) | (a >> 1);
set_operand_a(inst, cpub, value);
cpub->cf = is_right_shift_carried(a);
cpub->vf = 0;
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int rla(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword cf = cpub->cf;
Uword value = cf | (a << 1);
set_operand_a(inst, cpub, value);
cpub->cf = is_left_shift_carried(a);
cpub->vf = is_left_shift_overflowed(a);
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int rrl(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword value = (a << 7) | (a >> 1);
set_operand_a(inst, cpub, value);
cpub->cf = is_right_shift_carried(a);
cpub->vf = 0;
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int rll(Uword inst, Cpub *cpub)
{
Uword a = get_operand_a(inst, cpub);
Uword value = (a >> 7) | (a << 1);
set_operand_a(inst, cpub, value);
cpub->cf = is_left_shift_carried(a);
cpub->vf = 0;
cpub->nf = is_negative(value);
cpub->zf = is_zero(value);
return RUN_STEP;
}
int branch(int cond, Cpub *cpub)
{
Addr mar = cpub->pc++;
if (cond) cpub->pc = cpub->mem[mar];
return RUN_STEP;
}
int ba(Uword inst, Cpub *cpub)
{
return branch(1, cpub);
}
int bvf(Uword inst, Cpub *cpub)
{
return branch(cpub->vf, cpub);
}
int bnz(Uword inst, Cpub *cpub)
{
return branch(!cpub->zf, cpub);
}
int bz(Uword inst, Cpub *cpub)
{
return branch(cpub->zf, cpub);
}
int bzp(Uword inst, Cpub *cpub)
{
return branch(!cpub->nf, cpub);
}
int bn(Uword inst, Cpub *cpub)
{
return branch(cpub->nf, cpub);
}
int bp(Uword inst, Cpub *cpub)
{
return branch(!(cpub->nf | cpub->zf), cpub);
}
int bzn(Uword inst, Cpub *cpub)
{
return branch(cpub->nf | cpub->zf, cpub);
}
int bni(Uword inst, Cpub *cpub)
{
return branch(!cpub->ibuf->flag, cpub);
}
int bno(Uword inst, Cpub *cpub)
{
return branch(!cpub->obuf.flag, cpub);
}
int bnc(Uword inst, Cpub *cpub)
{
return branch(!cpub->cf, cpub);
}
int bc(Uword inst, Cpub *cpub)
{
return branch(cpub->cf, cpub);
}
int bge(Uword inst, Cpub *cpub)
{
return branch(!(cpub->vf ^ cpub->nf), cpub);
}
int blt(Uword inst, Cpub *cpub)
{
return branch(cpub->vf ^ cpub->nf, cpub);
}
int bgt(Uword inst, Cpub *cpub)
{
return branch(!((cpub->vf ^ cpub->nf) | cpub->zf), cpub);
}
int ble(Uword inst, Cpub *cpub)
{
return branch((cpub->vf ^ cpub->nf) | cpub->zf, cpub);
}
int jal(Uword inst, Cpub *cpub)
{
Addr mar = cpub->pc++;
cpub->acc = cpub->pc;
cpub->pc = cpub->mem[mar];
return RUN_STEP;
}
int jr(Uword inst, Cpub *cpub)
{
cpub->pc = cpub->acc;
return RUN_STEP;
}
typedef struct {
Uword mask;
Uword pattern;
int (*instruction)(Uword, Cpub *);
} Decoder;
Decoder decoders[] = {
{ 0xf8, 0x00, nop }, /* 00000--- NOP no operation */
{ 0xfc, 0x0c, hlt }, /* 000011-- HLT halt */
{ 0xf8, 0x10, out }, /* 00010--- OUT output */
{ 0xf8, 0x18, in }, /* 00011--- IN input */
{ 0xf8, 0x20, rcf }, /* 00100--- RCF reset carry flag */
{ 0xf8, 0x28, scf }, /* 00101--- SCF set carry flag */
{ 0xf0, 0x60, ld }, /* 0110abbb LD load */
{ 0xf0, 0x70, st }, /* 0111abbb ST store */
{ 0xf0, 0xb0, add }, /* 1011abbb ADD add */
{ 0xf0, 0x90, adc }, /* 1001abbb ADC add with carry flag */
{ 0xf0, 0xa0, sub }, /* 1010abbb SUB subtract */
{ 0xf0, 0x80, sbc }, /* 1000abbb SBC subtract with carry flag */
{ 0xf0, 0xf0, cmp }, /* 1111abbb CMP compare */
{ 0xf0, 0xe0, and }, /* 1110abbb AND and */
{ 0xf0, 0xd0, or }, /* 1101abbb OR or */
{ 0xf0, 0xc0, eor }, /* 1100abbb EOR exclusive or */
{ 0xf7, 0x40, sra }, /* 0100a000 SRA shift right arithmetic */
{ 0xf7, 0x41, sla }, /* 0100a001 SLA shift left arithmetic */
{ 0xf7, 0x42, srl }, /* 0100a010 SRL shift right logical */
{ 0xf7, 0x43, sll }, /* 0100a011 SLL shift left logical */
{ 0xf7, 0x44, rra }, /* 0100a100 RRA rotate right arithmetic */
{ 0xf7, 0x45, rla }, /* 0100a101 RLA rotate left arithmetic */
{ 0xf7, 0x46, rrl }, /* 0100a110 RRL rotate right logical */
{ 0xf7, 0x47, rll }, /* 0100a111 RLL rotate left logical */
{ 0xff, 0x30, ba }, /* 00110000 BA branch always */
{ 0xff, 0x38, bvf }, /* 00111000 BVF branch on overflow */
{ 0xff, 0x31, bnz }, /* 00110001 BNZ branch on not zero */
{ 0xff, 0x39, bz }, /* 00111001 BZ branch on zero */
{ 0xff, 0x32, bzp }, /* 00110010 BZP branch on zero or positive */
{ 0xff, 0x3a, bn }, /* 00111010 BN branch on negative */
{ 0xff, 0x33, bp }, /* 00110011 BP branch on positive */
{ 0xff, 0x3b, bzn }, /* 00111011 BZN branch on zero or negative */
{ 0xff, 0x34, bni }, /* 00110100 BNI branch on no input */
{ 0xff, 0x3c, bno }, /* 00111100 BNO branch on no output */
{ 0xff, 0x35, bnc }, /* 00110101 BNC branch on not carry */
{ 0xff, 0x3d, bc }, /* 00111101 BC branch on carry */
{ 0xff, 0x36, bge }, /* 00110110 BGE branch on greater than or equal */
{ 0xff, 0x3e, blt }, /* 00111110 BLT branch on less than */
{ 0xff, 0x37, bgt }, /* 00110111 BGT branch on greater than */
{ 0xff, 0x3f, ble }, /* 00111111 BLE branch on less than or equal */
{ 0xff, 0x0a, jal }, /* 00001010 JAL jump and link */
{ 0xff, 0x0b, jr }, /* 00001011 JR jump register */
};
int step(Cpub *cpub)
{
Addr mar = cpub->pc++;
Uword ir = cpub->mem[mar];
int i;
int size = sizeof(decoders) / sizeof(Decoder);
for (i = 0; i < size; i++) {
if ((ir & decoders[i].mask) == decoders[i].pattern) {
return decoders[i].instruction(ir, cpub);
}
}
return RUN_HALT;
}
/*
* Project-based Learning II (CPU)
*
* Program: instruction set simulator of the Educational CPU Board
* File Name: cpuboard.h
* Descrioption: resource definition of the educational computer board
*/
/*=============================================================================
* Architectural Data Types
*===========================================================================*/
typedef signed char Sword;
typedef unsigned char Uword;
typedef unsigned short Addr;
typedef unsigned char Bit;
/*=============================================================================
* CPU Board Resources
*===========================================================================*/
#define MEMORY_SIZE 256*2
#define IMEMORY_SIZE 256
typedef struct iobuf {
Bit flag;
Uword buf;
} IOBuf;
typedef struct cpuboard {
Uword pc;
Uword acc;
Uword ix;
Bit cf, vf, nf, zf;
IOBuf *ibuf;
IOBuf obuf;
/*
* [ add here the other CPU resources if necessary ]
*/
Uword mem[MEMORY_SIZE]; /* 0XX:Program, 1XX:Data */
} Cpub;
/*=============================================================================
* Top Function of an Instruction Simulation
*===========================================================================*/
#define RUN_HALT 0
#define RUN_STEP 1
int step(Cpub *);
/*
* Project-based Learning II (CPU)
*
* Program: instruction set simulator of the Educational CPU Board
* File Name: main.c
* Descrioption: main profram (command interpreter)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cpuboard.h"
void help(void);
int init_cpub(void);
void cont(Cpub *, char *);
void display_regs(Cpub *);
void set_reg(Cpub *, char *, char *);
void display_mem(Cpub *, char *);
void display_mem_line(Cpub *, Addr);
void display_mem_all(Cpub *);
void set_mem(Cpub *, char *, char *);
void read_mem_file(Cpub *, char *);
void cmd_syntax_error(void);
void unknown_command(void);
/*=============================================================================
* CPU Board States
*===========================================================================*/
Cpub cpuboard[2]; /* CPU board state */
/*=============================================================================
* Command: Display a Help Menu
*===========================================================================*/
void
help(void)
{
fprintf(stderr," i\t\t--- execute an instruction "
"(one step execution)\n");
fprintf(stderr," c [addr]\t--- continue(start) execution "
"[to address(hex)]\n");
fprintf(stderr," d\t\t--- display the contents of registers\n");
fprintf(stderr," s reg data\t--- set data(hex) to the register\n"
"\t\t\treg: pc,acc,ix,cf,vf,nf,zf,"
"ibuf,if,obuf,of\n");
fprintf(stderr," m [addr]\t--- dump memory or display data "
"at memory address(hex)\n");
fprintf(stderr," w addr data\t--- write data(hex) "
"at memory address(hex)\n");
fprintf(stderr," r file\t--- load a program into the main memory "
"from the file\n");
fprintf(stderr," t\t\t--- toggle current computer(context)\n");
fprintf(stderr," h\t\t--- help (this menu)\n");
fprintf(stderr," ?\t\t--- help (this menu)\n");
fprintf(stderr," q\t\t--- quit\n");
}
/*=============================================================================
* Initialization for the System Organization
*===========================================================================*/
int
init_cpub(void)
{
cpuboard[0].ibuf = &(cpuboard[1].obuf);
cpuboard[1].ibuf = &(cpuboard[0].obuf);
return 0;
}
/*=============================================================================
* Main Routine: Command Interpreter
*===========================================================================*/
int
main()
{
#define CLSIZE 160
char cmdline[CLSIZE]; /* command line buffer */
char cmd[CLSIZE], arg1[CLSIZE], arg2[CLSIZE], dummy[CLSIZE];
Cpub *cpub; /* current CPU board state */
int cpub_id; /* current CPU board ID */
int n;
/*
* Initialize the CPU board state
*/
cpub_id = init_cpub();
cpub = &(cpuboard[cpub_id]);
/*
* Interpret commands
*/
while(1) {
/*
* Prompt
*/
fprintf(stderr,"CPU%d,PC=0x%x> ",cpub_id,cpub->pc);
fflush(stderr);
/*
* Input a command line
*/
if( fgets(cmdline,CLSIZE,stdin) == NULL )
return 0; /* exiting */
if( (n = sscanf(cmdline,"%s%s%s%s",cmd,arg1,arg2,dummy)) <= 0 )
continue; /* empty input, so retry */
/*
* Interpet a command
*/
if( cmd[1] != '\0' ) {
unknown_command();
continue;
}
switch( cmd[0] ) {
case 'i':
if( step(cpub) == RUN_HALT ) {
fprintf(stderr,"Program Halted.\n");
}
break;
case 'c':
switch( n ) {
case 1: cont(cpub,NULL); break;
case 2: cont(cpub,arg1); break;
default: goto syntaxerr;
}
break;
case 'd':
if( n != 1 ) goto syntaxerr;
display_regs(cpub);
break;
case 's':
if( n != 3 ) goto syntaxerr;
set_reg(cpub,arg1,arg2);
break;
case 'm':
switch( n ) {
case 1: display_mem_all(cpub); break;
case 2: display_mem(cpub,arg1); break;
default: goto syntaxerr;
}
break;
case 'w':
if( n != 3 ) goto syntaxerr;
set_mem(cpub,arg1,arg2);
break;
case 'r':
if( n != 2 ) goto syntaxerr;
read_mem_file(cpub,arg1);
break;
case 't':
cpub_id ^= 1;
cpub = &(cpuboard[cpub_id]);
break;
case 'h':
case '?':
help();
break;
case 'q':
if( n != 1 )
goto syntaxerr;
else
return 0; /* exiting */
break; /* never reach here */
default:
unknown_command();
break;
syntaxerr:
cmd_syntax_error();
break;
}
}
/* never reach here */
}
/*=============================================================================
* Command: Continue(Start) Execution
*===========================================================================*/
void
cont(Cpub *cpub, char *straddr)
{
#define MAX_EXEC_COUNT 500
int addr;
Addr breakp;
int count;
/*
* Check and set a break-point address
*/
if( straddr == NULL )
breakp = 0xffff; /* impossible address (on purpose) */
else {
sscanf(straddr,"%x",&addr);
if( addr < 0 || addr >= IMEMORY_SIZE ) {
fprintf(stderr,"Invalid address: 0x%x\n",addr);
return;
}
breakp = addr;
}
/*
* Execute a program
*/
count = 1;
do {
if( step(cpub) == RUN_HALT ) {
fprintf(stderr,"Program Halted.\n");
return;
}
if( count++ > MAX_EXEC_COUNT ) {
fprintf(stderr,"Too Many Instructions are Executed.\n");
return;
}
} while( cpub->pc != breakp );
}
/*=============================================================================
* Command: Display Registers and Flags
*===========================================================================*/
#define DispRegVec(R) (Uword)(R),(Sword)(R),(Uword)(R)
void
display_regs(Cpub *cpub)
{
fprintf(stderr,"\tacc=0x%02x(%d,%u) ix=0x%02x(%d,%u)"
" cf=%d vf=%x nf=%x zf=%x\n",
DispRegVec(cpub->acc),DispRegVec(cpub->ix),
cpub->cf,cpub->vf,cpub->nf,cpub->zf);
fprintf(stderr,"\tibuf=%x:0x%02x(%d,%u) obuf=%x:0x%02x(%d,%u)\n",
cpub->ibuf->flag,DispRegVec(cpub->ibuf->buf),
cpub->obuf.flag,DispRegVec(cpub->obuf.buf));
}
/*=============================================================================
* Command: Set a Register/Flag
*===========================================================================*/
void
set_reg(Cpub *cpub, char *regname, char *strval)
{
unsigned int value, max;
unsigned char *reg;
/*
* Check the register/flag name
*/
if( !strcmp(regname,"pc") ) reg = &(cpub->pc), max = 0xff;
else
if( !strcmp(regname,"acc") ) reg = &(cpub->acc), max = 0xff;
else
if( !strcmp(regname,"ix") ) reg = &(cpub->ix), max = 0xff;
else
if( !strcmp(regname,"cf") ) reg = &(cpub->cf), max = 1;
else
if( !strcmp(regname,"vf") ) reg = &(cpub->vf), max = 1;
else
if( !strcmp(regname,"nf") ) reg = &(cpub->nf), max = 1;
else
if( !strcmp(regname,"zf") ) reg = &(cpub->zf), max = 1;
else
if( !strcmp(regname,"ibuf") ) reg = &(cpub->ibuf->buf), max = 0xff,
cpub->ibuf->flag = 1;
else
if( !strcmp(regname,"if") ) reg = &(cpub->ibuf->flag), max = 1;
else
if( !strcmp(regname,"obuf") ) reg = &(cpub->obuf.buf), max = 0xff,
cpub->obuf.flag = 1;
else
if( !strcmp(regname,"of") ) reg = &(cpub->obuf.flag), max = 1;
else {
fprintf(stderr,"Unknown register name: %s\n",regname);
return;
}
/*
* Write to the register/flag
*/
sscanf(strval,"%x",&value);
if( value > max )
fprintf(stderr,"Invalid value (out of range): 0x%x\n",value);
else
*reg = value;
/*
* For confirmation
*/
display_regs(cpub);
}
/*=============================================================================
* Command: Display the Contents of the Main Memory
*===========================================================================*/
#define MemLineBase(A) ((A) & ~0xf)
void
display_mem(Cpub *cpub, char *straddr)
{
unsigned int addr;
sscanf(straddr,"%x",&addr);
if( addr > MEMORY_SIZE ) {
fprintf(stderr,"Invalid address (out of range): 0x%x\n",addr);
return;
}
display_mem_line(cpub,(Addr)MemLineBase(addr));
}
void
display_mem_line(Cpub *cpub, Addr addr)
{
int i, j;
for( j = 0 ; j < 2 ; j++ ) {
fprintf(stderr," | %03x: ",addr);
for( i = 0 ; i < 8 ; i++ ) {
fprintf(stderr," %02x",(Uword)cpub->mem[addr++]);
}
}
fprintf(stderr,"\n");
}
void
display_mem_all(Cpub *cpub)
{
Addr addr;
for( addr = 0 ; addr < MEMORY_SIZE ; addr += 16 )
display_mem_line(cpub,addr);
}
/*=============================================================================
* Command: Write a Word to a Memory Location
*===========================================================================*/
void
set_mem(Cpub *cpub, char *straddr, char *strval)
{
unsigned int addr, value;
sscanf(straddr,"%x",&addr);
if( addr > MEMORY_SIZE ) {
fprintf(stderr,"Invalid address (out of range): 0x%x\n",addr);
return;
}
sscanf(strval,"%x",&value);
if( value > 0xff ) {
fprintf(stderr,"Invalid value (out of range): 0x%x\n",value);
return;
}
cpub->mem[addr] = value;
display_mem_line(cpub,(Addr)MemLineBase(addr));
}
/*=============================================================================
* Command: Read a Program File
*===========================================================================*/
void
read_mem_file(Cpub *cpub, char *file)
{
#define TOKENSIZE 160
FILE *fp;
unsigned int addr, word;
Addr area;
char token[TOKENSIZE];
if( (fp = fopen(file,"r")) == NULL ) {
fprintf(stderr,"Unable to open %s\n",file);
return;
}
addr = 0; /* default initial address */
while( fscanf(fp,"%s",token) == 1 ) {
if( token[0] == '.' ) { /* directive */
/*
* Check the directive type
*/
if( !strcmp(token+1,"text") ) {
area = 0x000;
} else
if( !strcmp(token+1,"data") ) {
area = 0x100;
} else {
fprintf(stderr,"Unknown directive: %s\n",token); goto error;
}
/*
* Change the current address
*/
fscanf(fp,"%x",&addr);
if( addr > 0xff ) {
fprintf(stderr,"Invalid address: %s %x\n",
token,addr);
goto error;
}
addr |= area;
} else { /* instruction word or data */
sscanf(token,"%x",&word);
if( word > 0xff ) {
fprintf(stderr,"Invalid value at addr=0x%03x: "
"0x%x\n",addr,word);
goto error;
}
cpub->mem[addr++] = word;
}
}
error:
fclose(fp);
}
/*=============================================================================
* Error Handling
*===========================================================================*/
void
cmd_syntax_error(void)
{
fprintf(stderr,"Command syntax error. Type \'h\' for help.\n");
}
void
unknown_command(void)
{
fprintf(stderr,"Unknown command. Type \'h\' for help.\n");
}

プロジェクト実習2で作成したCPUシミュレータを置いてます.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment