プロジェクト実習2で作成したCPUシミュレータを置いてます.
Created
September 27, 2021 05:34
-
-
Save shouth/311e3788d6b8e706e6814dc350626937 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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 *); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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"); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment