URL
https://opencores.org/ocsvn/tv80/tv80/trunk
Subversion Repositories tv80
Compare Revisions
- This comparison shows the changes necessary to convert path
/tv80/trunk/sc_env
- from Rev 95 to Rev 96
- ↔ Reverse comparison
Rev 95 → Rev 96
/sc_env_top.cpp
5,6 → 5,7
#include "Vtv80s.h" |
#include "SpTraceVcd.h" |
#include <unistd.h> |
#include "z80_decoder.h" |
|
extern char *optarg; |
extern int optind, opterr, optopt; |
17,8 → 18,9
char *dumpfile_name; |
char *mem_src_name; |
SpTraceFile *tfp; |
z80_decoder dec0 ("dec0"); |
|
while ( (index = getopt(argc, argv, "d:i:")) != -1) { |
while ( (index = getopt(argc, argv, "d:i:k")) != -1) { |
printf ("DEBUG: getopt optind=%d index=%d char=%c\n", optind, index, (char) index); |
if (index == 'd') { |
dumpfile_name = new char(strlen(optarg)+1); |
29,6 → 31,9
mem_src_name = new char(strlen(optarg)+1); |
strcpy (mem_src_name, optarg); |
memfile = true; |
} else if (index == 'k') { |
printf ("Z80 Instruction decode enabled\n"); |
dec0.en_decode = true; |
} |
} |
sc_clock clk("clk125", 8, SC_NS, 0.5); |
98,6 → 103,15
tv_resp0.di_resp (di_resp); |
tv_resp0.dout (dout); |
tv_resp0.halt_n (halt_n); |
|
dec0.clk (clk); |
dec0.m1_n (m1_n); |
dec0.addr (addr); |
dec0.mreq_n (mreq_n); |
dec0.rd_n (rd_n); |
dec0.wait_n (wait_n); |
dec0.di (di); |
dec0.reset_n (reset_n); |
|
// create dumpfile |
/* |
/z80_decoder.cpp
0,0 → 1,260
#include "z80_decoder.h" |
|
char *table_r[] = { "B", "C", "D", "E", "H", "L", "(HL)", "A" }; |
char *table_cc[] = { "NZ", "Z", "NC", "C", "PO", "PE", "P", "M" }; |
char *table_rp[] = {"BC", "DE", "HL", "SP" }; |
char *table_rp2[] = {"BC","DE","HL","AF"}; |
char *table_alu[] = {"ADD A,","ADC A,","SUB","SBC A,","AND","XOR","OR","CP"}; |
|
void z80_decoder::op_print () |
{ |
printf ("DECODE :[%04x] %s\n", op_addr, op_name); |
} |
|
void z80_decoder::decode_unpre() |
{ |
int x = opcode.range(7,6); |
int y = opcode.range(5,3); |
int z = opcode.range(2,0); |
|
sprintf (op_buf, "Unknown (%02x)", (int) opcode); |
op_name = op_buf; |
|
switch (x) { |
case 0 : |
switch (z) { |
case 0 : |
if (y == 0) |
op_name = "NOP"; |
else if (y == 1) |
op_name = "EX AF, AF'"; |
else if (y == 2) { |
op_name = "DJNZ %d"; |
state = DISP; |
} else if (y == 3) { |
op_name = "JR %d"; |
state = DISP; |
} else { |
sprintf (op_buf, "JR %s, %%02x", table_cc[y-4]); |
op_name = op_buf; |
state = IMM1; |
} |
break; |
case 1 : |
if (opcode.bit(3)) { |
sprintf (op_buf, "ADD HL, %s", table_rp[y>>1]); |
op_name = op_buf; |
} else { |
sprintf (op_buf, "LD %s, %%04x", table_rp[y>>1]); |
op_name = op_buf; |
state = IMM2; |
} |
break; |
case 2 : |
switch (y) { |
case 0 : op_name = "LD (BC), A"; break; |
case 1 : op_name = "LD (DE), A"; break; |
case 2 : op_name = "LD (%04x), HL"; state = IMM2; break; |
case 3 : op_name = "LD (%04x), A"; state = IMM2; break; |
case 4 : op_name = "LD A, (BC)"; break; |
case 5 : op_name = "LD A, (DE)"; break; |
case 6 : op_name = "LD HL, (%04x)"; state = IMM2; break; |
case 7 : op_name = "LD A, (%02x)"; state = IMM1; break; |
} |
break; |
case 3 : |
if (opcode.bit(3)) { |
sprintf (op_buf, "DEC %s", table_rp[opcode.range(5,4)]); |
op_name = op_buf; |
} else { |
sprintf (op_buf, "INC %s", table_rp[opcode.range(5,4)]); |
op_name = op_buf; |
} |
break; |
case 4 : |
sprintf (op_buf, "INC %s", table_r[y]); |
op_name = op_buf; |
break; |
case 5 : |
sprintf (op_buf, "DEC %s", table_r[y]); |
op_name = op_buf; |
break; |
case 6 : |
sprintf (op_buf, "LD %s, %%02x", table_r[y]); |
op_name = op_buf; |
state = IMM1; |
break; |
case 7 : |
switch (y) { |
case 0 : op_name = "RLCA"; break; |
case 1 : op_name = "RRCA"; break; |
case 2 : op_name = "RLA"; break; |
case 3 : op_name = "RRA"; break; |
case 4 : op_name = "DAA"; break; |
case 5 : op_name = "CPL"; break; |
case 6 : op_name = "SCF"; break; |
case 7 : op_name = "CCF"; break; |
} |
break; |
} |
break; |
|
case 1 : |
if ((z == 6) && (y == 6)) { |
op_name = "HALT"; |
} else { |
sprintf (op_buf, "LD %s, %s", table_r[y], table_r[z]); |
op_name = op_buf; |
} |
break; |
|
case 2 : // ALU |
sprintf (op_buf, "%s %s", table_alu[y], table_r[z]); |
op_name = op_buf; |
break; |
|
case 3 : |
switch (z) { |
case 0 : |
sprintf (op_buf, "RET %s", table_cc[y]); |
op_name = op_buf; |
break; |
case 1 : // TBD, POP & opcodes |
switch (y) { |
case 0 : case 1: case 2 : case 3 : |
sprintf (op_buf, "POP %s", table_rp2[y>>1]); |
op_name = op_buf; |
break; |
case 4 : op_name = "RET"; break; |
case 5 : op_name = "EXX"; break; |
case 6 : op_name = "JP HL"; break; |
case 7 : op_name = "LD SP, HL"; break; |
} |
break; |
case 2 : |
sprintf (op_buf, "JP %s, %%04x", table_cc[y]); |
op_name = op_buf; |
state = IMM2; |
break; |
case 3 : // JP and opcodes |
switch (y) { |
case 0 : op_name = "JP %04x"; state = IMM2; break; |
case 1 : state = PRE_CB; break; |
case 2 : op_name = "OUT (%02x), A"; state = IMM1; break; |
case 3 : op_name = "IN A, (%02x)"; state = IMM1; break; |
case 4 : op_name = "EX (SP), HL"; break; |
case 5 : op_name = "EX DE, HL"; break; |
case 6 : op_name = "DI"; break; |
case 7 : op_name = "EI"; break; |
|
} |
break; |
case 4 : |
sprintf (op_buf, "CALL %s, %%04x", table_cc[y]); |
op_name = op_buf; |
state = IMM2; |
break; |
case 5 : |
switch (y) { |
case 0 : |
case 1 : |
case 2 : |
case 3 : |
sprintf (op_buf, "PUSH %s", table_rp2[y>>1]); |
op_name = op_buf; |
break; |
case 4 : |
op_name = "CALL %04x"; |
state = IMM2; |
break; |
case 5 : state = PRE_DD; break; |
case 6 : state = PRE_ED; break; |
case 7 : state = PRE_FD; break; |
} |
break; |
} |
break; |
} |
/*FOR x=0 |
z=0 |
y=0 NOP y=2 DJNZ d |
y=1 EX AF, AF' y=3 JR d |
y=4..7 JR cc[y-4], d |
Relative jumps and assorted ops |
z=1 |
q=0 LD rp[p], nn |
q=1 ADD HL, rp[p] |
16-bit load immediate/add |
z=2 |
q=0 p=0 LD (BC), A p=2 LD (nn), HL |
p=1 LD (DE), A p=3 LD (nn), A |
q=1 p=0 LD A, (BC) p=2 LD HL, (nn) |
p=1 LD A, (DE) p=3 LD A, (nn) |
Indirect loading |
z=3 |
q=0 INC rp[p] |
q=1 DEC rp[p] |
16-bit INC/DEC |
z=4 |
INC r[y] |
8-bit INC |
z=5 |
DEC r[y] |
8-bit DEC |
z=6 |
LD r[y], n |
8-bit load immediate |
z=7 |
y=0 RLCA y=4 DAA |
y=1 RRCA y=5 CPL |
y=2 RLA y=6 SCF |
y=3 RRA y=7 CCF |
Assorted operations on accumulator/flags |
*/ |
|
if (state == UNPRE) { |
//printf ("DECODE : %02x %s\n", (int) opcode, op_name); |
op_print(); |
} |
} |
|
void z80_decoder::event() |
{ |
if ((en_decode == false) || !reset_n) return; |
|
if (!m1_n && !mreq_n && !rd_n && wait_n) { |
imm = 0; |
op_addr = (int) addr; |
switch ( (int) di.read() ) { |
case 0xCB : state = PRE_CB; break; |
case 0xDD : state = PRE_DD; break; |
case 0xED : state = PRE_ED; break; |
case 0xFD : state = PRE_FD; break; |
default : |
opcode = di; |
state = UNPRE; |
decode_unpre(); |
break; |
} |
} else if (!mreq_n && !rd_n && wait_n && (state != UNPRE)) { |
switch (state) { |
case IMM2 : |
imm = ((unsigned int) di) & 0xff; |
state = IMM2B; |
break; |
case IMM2B : |
imm |= ((unsigned int) di << 8)& 0xFF00; |
sprintf (op_buf, op_name, imm); |
op_name = op_buf; |
op_print(); |
break; |
case IMM1 : |
imm = ((unsigned int) di) & 0xff; |
sprintf (op_buf, op_name, imm); |
//printf ("DECODE : %02x %s\n", (int) opcode, op_name); |
op_name = op_buf; |
op_print(); |
break; |
} |
} |
} |
/z80_decoder.h
0,0 → 1,40
#ifndef Z80_DECODER_H_ |
#define Z80_DECODER_H_ |
|
#include "systemc.h" |
|
typedef enum { UNPRE, PRE_CB, PRE_DD, PRE_ED, PRE_FD, DISP, IMM1, IMM2, IMM2B } dec_state; |
|
SC_MODULE(z80_decoder) |
{ |
private: |
dec_state state; |
sc_uint<8> opcode; |
char *op_name; |
char op_buf[80]; |
uint16_t imm, op_addr; |
|
void decode_unpre(); |
void op_print(); |
|
public: |
sc_in<bool> clk; |
sc_in<uint32_t> addr; |
sc_in<bool> m1_n; |
sc_in<bool> mreq_n; |
sc_in<bool> rd_n; |
sc_in<bool> wait_n; |
sc_in<uint32_t> di; |
sc_in<bool> reset_n; |
bool en_decode; |
|
void event(); |
|
SC_CTOR(z80_decoder) { |
SC_METHOD (event); |
sensitive << clk.pos(); |
en_decode = false; |
} |
}; |
|
#endif /*Z80_DECODER_H_*/ |
/Makefile
4,7 → 4,7
INCLUDES=-I$(SYSTEMC)/include -I$(VERIDIR) -I$(VERILATOR_ROOT)/include -I$(SYSTEMPERL) |
LINKOPT=-L$(SYSTEMC)/lib-linux64 -lsystemc -lm |
DEFINES=-DDEBUG |
OBJFILES=sc_env_top.o env_memory.o tv_responder.o \ |
OBJFILES=sc_env_top.o env_memory.o tv_responder.o z80_decoder.o \ |
$(VERIDIR)/Vtv80s.o $(VERIDIR)/Vtv80s__Syms.o \ |
$(VERIDIR)/Vtv80s__Trace.o \ |
$(VERIDIR)/Vtv80s__Trace__Slow.o \ |