Mercurial > hg > ede
changeset 30:c0c2e99b6bb0
fixed negative rel8 address bug in assembler
author | james <jb302@eecs.qmul.ac.uk> |
---|---|
date | Tue, 15 Apr 2014 12:21:22 +0100 |
parents | 83e80c2c489c |
children | 7a35e6ae1c36 |
files | .cli.py.swp asm/language.py asm/language.pyc bin/emu cli.py dbg/dbg.pyc doc/general/ede.lyx doc/general/ede.lyx~ emu/.iset.c.swp emu/.mem.c.swp emu/.mem.h.swp emu/iset.c emu/mem.c emu/mem.h tests/emu/a.out tests/emu/test.c |
diffstat | 16 files changed, 319 insertions(+), 119 deletions(-) [+] |
line wrap: on
line diff
--- a/asm/language.py Sun Apr 13 22:42:57 2014 +0100 +++ b/asm/language.py Tue Apr 15 12:21:22 2014 +0100 @@ -332,7 +332,10 @@ else: sym.append('addr') fmt = '>H' - val = stoi(a) + if is_neg == 1: + val = stoi('-' + a) + else: + val = stoi(a) data = data + struct.pack(fmt, val) continue # immediate ints (signed when negative)
--- a/cli.py Sun Apr 13 22:42:57 2014 +0100 +++ b/cli.py Tue Apr 15 12:21:22 2014 +0100 @@ -19,7 +19,7 @@ 'SPH':5, 'PCH':6, 'TMPH':7, - 'RO_1':8, + 'R0_1':8, 'R1_1':9, 'R2_1':10, 'R3_1':11, @@ -73,7 +73,7 @@ print 'invalid instruction' continue - print hex(pcl | (pch << 8)), [hex(b) for b in byte_array] + print 'PC -> ', hex(pcl | (pch << 8)), [hex(b) for b in byte_array] # write to emu memory and execute emu.set_block(pch, pcl, byte_array) emu.step() @@ -102,38 +102,39 @@ cmd = inp[0] args = [] - #try: - # deal with inline execution independently - if cmd == 'exc': - exc() - continue + try: + # deal with inline execution independently + if cmd == 'exc': + exc() + continue - # set block has unique argument syntax - if cmd == 'sb': - args.append(int(inp[1], 0)) - args.append(int(inp[2], 0)) - args.append([int(x, 0) for x in inp[3:]]) - cmds[cmd](*args) + # set block has unique argument syntax + if cmd == 'sb': + args.append(int(inp[1], 0)) + args.append(int(inp[2], 0)) + args.append([int(x, 0) for x in inp[3:]]) + cmds[cmd](*args) + continue + + # decode args + i = 0 + for word in inp[1:]: + if word in syms.keys(): + args.append(syms[word]) + # only arguments after 3 will be data for set block + # this needs to be in a list + else: + args.append(int(word, 0)) + i = i + 1 + + resp = cmds[cmd](*args) + if resp == None: + continue + else: + print [hex(struct.unpack('>B', x)[0]) for x in resp] + + except Exception, e: + print e + print 'invalid command or argument syntax' continue - # decode args - i = 0 - for word in inp[1:]: - if word in syms.keys(): - args.append(syms[word]) - # only arguments after 3 will be data for set block - # this needs to be in a list - else: - args.append(int(word, 0)) - i = i + 1 - - resp = cmds[cmd](*args) - if resp == None: - continue - else: - print [hex(struct.unpack('>B', x)[0]) for x in resp] - - #except: - # print 'invalid command or argument syntax' - # continue -
--- a/doc/general/ede.lyx Sun Apr 13 22:42:57 2014 +0100 +++ b/doc/general/ede.lyx Tue Apr 15 12:21:22 2014 +0100 @@ -329,6 +329,14 @@ Assembler \end_layout +\begin_layout Section +Assembler Overview +\end_layout + +\begin_layout Section +Assembler Implementation +\end_layout + \begin_layout Standard The assembler is written in pure Python 2 using only the standard library. It assembles the assembly the language described in the ELB816 specification @@ -449,8 +457,8 @@ However it must be noted that these are abstract and high level descriptions that do not fully explain minor routines, but give an overview of the entire process. - The full source code is attached in the Appendix and should be referenced - for a deeper understanding of the program's operation. + The full commented source code is attached provided with the supporting + and should be referenced for a deeper understanding of the program's operation. The final section is a short programmers manual demonstrating the assembler's features. \end_layout @@ -462,7 +470,7 @@ \end_layout -\begin_layout Section +\begin_layout Subsection Data Structures \end_layout @@ -735,7 +743,7 @@ \end_layout -\begin_layout Section +\begin_layout Subsection Functions \end_layout @@ -1148,7 +1156,7 @@ \end_layout -\begin_layout Subsection +\begin_layout Subsubsection \begin_inset listings lstparams "basicstyle={\ttfamily}" inline true @@ -1371,7 +1379,7 @@ \end_layout -\begin_layout Subsection +\begin_layout Subsubsection \begin_inset listings lstparams "basicstyle={\ttfamily}" inline true @@ -1573,7 +1581,7 @@ \end_layout -\begin_layout Subsection +\begin_layout Subsubsection \begin_inset listings lstparams "basicstyle={\ttfamily}" inline true @@ -1622,7 +1630,7 @@ \end_layout -\begin_layout Subsection +\begin_layout Subsubsection \begin_inset listings lstparams "basicstyle={\ttfamily}" inline true @@ -1671,27 +1679,20 @@ \end_layout -\begin_layout Section -Assembly language manual -\end_layout - -\begin_layout Standard -\begin_inset Newpage newpage -\end_inset - - -\end_layout - \begin_layout Part Emulator \end_layout \begin_layout Section -Core microprocessor emulation +Emulator Overview \end_layout +\begin_layout Section +Core microprocessor implementation +\end_layout + \begin_layout Standard -The core of the emulator is written in C using only standard libraries. +The core of the emulator is written in C89 using only standard libraries. It executes the machine code output by the assembler according to the ELB816 specification. It consists of the following files: @@ -1772,7 +1773,7 @@ \begin_layout Plain Layout -emu.c +main.c \end_layout \end_inset @@ -1797,7 +1798,20 @@ function. It initializes the emulator and executes the programs fetch/decode/execute cycle. - + It also contains the programs +\begin_inset listings +lstparams "basicstyle={\ttfamily}" +inline true +status open + +\begin_layout Plain Layout + +dbgi() +\end_layout + +\end_inset + + function, which deals with emulator control and communication. \end_layout \begin_layout Standard @@ -1915,8 +1929,7 @@ \end_layout \begin_layout Standard -The figures bellow illustrate the emulator's memory layout as defined in - the +The \begin_inset listings lstparams "basicstyle={\ttfamily}" inline true @@ -1929,7 +1942,8 @@ \end_inset - header file. + header file describes the emulators internal memory structure and makes + this structure available the rest the code. \end_layout \begin_layout Standard @@ -1980,7 +1994,7 @@ \begin_layout Plain Layout -emu.c +main.c \end_layout \end_inset @@ -2013,8 +2027,20 @@ \begin_layout Standard It first executes a number of initialization procedures and then passes control over to the main fetch/decode/execute cycle. - This procedure is shown below as a flowchart. - To understand this it you must be familiar with C's function pointer syntax. + Every cycle it calls the +\begin_inset listings +lstparams "basicstyle={\ttfamily}" +inline true +status open + +\begin_layout Plain Layout + +dbgi() +\end_layout + +\end_inset + + \end_layout \begin_layout Standard @@ -2034,37 +2060,14 @@ \end_layout \begin_layout Standard -\begin_inset ERT -status open - -\begin_layout Plain Layout - - -\backslash -centerline{ +\begin_inset Newpage newpage +\end_inset + + \end_layout -\end_inset - - -\begin_inset Graphics - filename /home/jmz/qm/ede/doc/images/emulator/fetch_decode_exe.svg - scale 70 - -\end_inset - - -\begin_inset ERT -status open - -\begin_layout Plain Layout - -} -\end_layout - -\end_inset - - +\begin_layout Section +Peripheral Design \end_layout \begin_layout Standard @@ -2074,16 +2077,5 @@ \end_layout -\begin_layout Section -Peripherals -\end_layout - -\begin_layout Standard -\begin_inset Newpage newpage -\end_inset - - -\end_layout - \end_body \end_document
--- a/doc/general/ede.lyx~ Sun Apr 13 22:42:57 2014 +0100 +++ b/doc/general/ede.lyx~ Tue Apr 15 12:21:22 2014 +0100 @@ -605,7 +605,7 @@ \begin_layout Plain Layout -mneumonic: (arg type, arg type, ...): [opcode, width] +mnemonic: (arg type, arg type, ...): [opcode, width] \end_layout \end_inset
--- a/emu/iset.c Sun Apr 13 22:42:57 2014 +0100 +++ b/emu/iset.c Tue Apr 15 12:21:22 2014 +0100 @@ -214,7 +214,7 @@ /* 0b00100nnn - MOV @DPTR, Rn*/ case 0x20: set_wide(TMP, get_wide(DPTR)); - set_reg(NNN, mem[get_wide(TMP)]); + mem[get_wide(TMP)] = get_reg(NNN); break; /* 0b00101nnn - immediate movs - MOV Rn, #data8*/ @@ -227,7 +227,7 @@ set_reg(NNN, A); break; - /* 0b00111nnn */ + /* 0b00111nnn MOV A, Rn */ case 0x38: A = get_reg(NNN); break; @@ -237,7 +237,8 @@ } break;; - /* 0b01mmmnnn */ + /* 0b01mmmnnn MOV Rm Rn + * if m == n: MOV Rm, @DPTR */ case 0x40: if (NNN == MMM) { set_wide(TMP, get_wide(DPTR)); @@ -253,17 +254,92 @@ } } + +/* 0x80 - ANL A, R0 + * 0x81 - ANL A, R1 + * 0x82 - ANL A, R2 + * 0x83 - ANL A, R3 + * 0x84 - ANL A, DPH + * 0x85 - ANL A, DPL + * 0x86 - ANL A, #data8 + * 0x87 - ANL A, @DPTR */ void ANL(void) { + if (NNN < 6) { + A = A & get_reg(NNN); + } + else { + switch (NNN) { + + case 6: + A = A & fetch(); + break; + + case 7: + set_wide(TMP, get_wide(DPTR)); + A = A & mem[TMP]; + break; + } + } + set_zp(A); } +/* 0x88 - ORL A, R0 + * 0x89 - ORL A, R1 + * 0x8A - ORL A, R2 + * 0x8B - ORL A, R3 + * 0x8C - ORL A, DPH + * 0x8D - ORL A, DPL + * 0x8E - ORL A, #data8 + * 0x8F - ORL A, @DPTR */ void ORL(void) { + if (NNN < 6) { + A = A | get_reg(NNN); + } + else { + switch (NNN) { + + case 6: + A = A | fetch(); + break; + + case 7: + set_wide(TMP, get_wide(DPTR)); + A = A | mem[TMP]; + break; + } + } + set_zp(A); } +/* 0x90 - XRL A, R0 + * 0x91 - XRL A, R1 + * 0x92 - XRL A, R2 + * 0x93 - XRL A, R3 + * 0x94 - XRL A, DPH + * 0x95 - XRL A, DPL + * 0x96 - XRL A, #data8 + * 0x97 - XRL A, @DPTR */ void XRL(void) { + if (NNN < 6) { + A = A ^ get_reg(NNN); + } + else { + switch (NNN) { + + case 6: + A = A ^ fetch(); + break; + case 7: + set_wide(TMP, get_wide(DPTR)); + A = A ^ mem[TMP]; + break; + } + } + set_zp(A); } /* 0x98 - RL A */ @@ -275,7 +351,9 @@ /* 0x99 - RLC A */ void RLC(void) { - /* implement me */ + tmpb = A; + A = (A << 1) | get_flag(C); + set_flag(C, tmpb >> 7); } /* 0x9A - RR A */ @@ -287,32 +365,129 @@ /* 0x9B - RRC A */ void RRC(void) { - /* implement me */ + tmpb = A; + A = (A >> 1) | (get_flag(C) << 7); + set_flag(C, tmpb & 0x01); } /* 0x9C - INC DPTR * 0x9E - INC A */ void -INC(void) { +INC(void) { + switch (IR) { + + case 0x9C: + tmpw = get_wide(DPTR); + if ((tmpw + 1) > 0xFFFF) { + set_flag(OV, 1); + } + set_wide(DPTR, tmpw + 1); + set_zp(DPL); + set_zp(DPH); + break; + + case 0x9E: + if ((A + 1) > 0xFF) { + set_flag(OV, 1); + } + A++; + set_zp(A); + + } } /* 0x9D - DEC DPTR * 0x9F - DEC A */ void DEC(void) { + switch (IR) { + + case 0x9D: + tmpw = get_wide(DPTR); + if ((tmpw - 1) < 0) { + set_flag(OV, 1); + } + set_wide(DPTR, tmpw - 1); + set_zp(DPL); + set_zp(DPH); + + case 0x9F: + if ((A - 1) < 0) { + set_flag(OV, 1); + } + A--; + set_zp(A); + } } +/* 0xA0 - ADD A, R0 + * 0xA1 - ADD A, R1 + * 0xA2 - ADD A, R2 + * 0xA3 - ADD A, R3 + * 0xA4 - ADD A, DPH + * 0xA5 - ADD A, DPL + * 0xA6 - ADD A, #data8 + * 0xA7 - ADD A, @DPTR */ void ADD(void) { + if (NNN < 6) { + if ((A + get_reg(NNN)) > 0xFF){ + } + A = A + get_reg(NNN); + set_zp(A); + } + else { + switch (NNN) { + + case 6: + A = A + fetch(); + set_zp(A); + break; + + case 7: + set_wide(TMP, get_wide(DPTR)); + A = A + mem[TMP]; + set_zp(A); + break; + } + } + } void ADDC(void) { -/* implement me */ +/* implement me */ } +/* 0xB0 - SUB A, R0 + * 0xB1 - SUB A, R1 + * 0xB2 - SUB A, R2 + * 0xB3 - SUB A, R3 + * 0xB4 - SUB A, DPH + * 0xB5 - SUB A, DPL + * 0xB6 - SUB A, #data8 + * 0xB7 - SUB A, @DPTR */ void SUB(void) { + if (NNN < 6) { + A = A - get_reg(NNN); + set_zp(A); + } + else { + switch (NNN) { + + case 6: + A = A - fetch(); + set_zp(A); + break; + + case 7: + set_wide(TMP, get_wide(DPTR)); + A = A - mem[TMP]; + set_zp(A); + break; + } + } } void @@ -365,6 +540,7 @@ /* 0xDC - SJMP rel8 */ void SJMP(void) { + set_wide(PC, get_wide(PC) + (signed char)fetch()); } /* 0xDD - JMP @A+DPTR
--- a/emu/mem.c Sun Apr 13 22:42:57 2014 +0100 +++ b/emu/mem.c Tue Apr 15 12:21:22 2014 +0100 @@ -28,6 +28,28 @@ } } +/* sets zero and parity flags based on content of byte */ +void +set_zp(BYTE val){ + if (val == 0) { + set_flag(Z, 1); + set_flag(P, 0); + } + else { + /* think of this as folding */ + val ^= val >> 4; + val ^= val >> 2; + val ^= val >> 1; + val &= 1; + if (val == 0) { + set_flag(P, 1); + } + else { + set_flag(P, 0); + } + } +} + WIDE get_wide(BYTE reg) { /* high, low */ @@ -57,7 +79,7 @@ WIDE fetch_wide(void) { - WIDE val = MWIDE(mem[get_wide(PC)], mem[get_wide(PC) + g1]); + WIDE val = MWIDE(mem[get_wide(PC)], mem[get_wide(PC) + 1]); inc_pc(2); return val; }
--- a/emu/mem.h Sun Apr 13 22:42:57 2014 +0100 +++ b/emu/mem.h Tue Apr 15 12:21:22 2014 +0100 @@ -89,6 +89,15 @@ EXTERN void set_flag(BYTE flag, BYTE on); +EXTERN void +set_zp(BYTE val); + +/* this function a byte and returns a byte + * with zero and parity flags set or unset. + * result should be or'd with flags reg */ +EXTERN BYTE +gen_flags(BYTE val); + /* functions for dealing with 16-bit registers * access the 16 bit registers. * register map for these function: @@ -120,4 +129,5 @@ EXTERN void set_reg(BYTE reg, BYTE val); + #endif
--- a/tests/emu/test.c Sun Apr 13 22:42:57 2014 +0100 +++ b/tests/emu/test.c Tue Apr 15 12:21:22 2014 +0100 @@ -4,10 +4,6 @@ void main(void) { - unsigned char* enregs[8]; - unsigned char *p; - p = regs; - *enregs[8] = {p, p+1, p+2, p+3, p+12, p+4, p+13, p+5}; - *enregs[4] = 0xFF; - printf("%d", regs[12]); + unsigned char C = 0xFD; + printf("%i", (signed char)C); }