# HG changeset patch # User james # Date 1397560882 -3600 # Node ID c0c2e99b6bb05a4b2d8d9c7f762e864e3aa7935a # Parent 83e80c2c489ca0cc29611f593f3a23fb979143bd fixed negative rel8 address bug in assembler diff -r 83e80c2c489c -r c0c2e99b6bb0 .cli.py.swp Binary file .cli.py.swp has changed diff -r 83e80c2c489c -r c0c2e99b6bb0 asm/language.py --- 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) diff -r 83e80c2c489c -r c0c2e99b6bb0 asm/language.pyc Binary file asm/language.pyc has changed diff -r 83e80c2c489c -r c0c2e99b6bb0 bin/emu Binary file bin/emu has changed diff -r 83e80c2c489c -r c0c2e99b6bb0 cli.py --- 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 - diff -r 83e80c2c489c -r c0c2e99b6bb0 dbg/dbg.pyc Binary file dbg/dbg.pyc has changed diff -r 83e80c2c489c -r c0c2e99b6bb0 doc/general/ede.lyx --- 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 diff -r 83e80c2c489c -r c0c2e99b6bb0 doc/general/ede.lyx~ --- 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 diff -r 83e80c2c489c -r c0c2e99b6bb0 emu/.iset.c.swp Binary file emu/.iset.c.swp has changed diff -r 83e80c2c489c -r c0c2e99b6bb0 emu/.mem.c.swp Binary file emu/.mem.c.swp has changed diff -r 83e80c2c489c -r c0c2e99b6bb0 emu/.mem.h.swp Binary file emu/.mem.h.swp has changed diff -r 83e80c2c489c -r c0c2e99b6bb0 emu/iset.c --- 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 diff -r 83e80c2c489c -r c0c2e99b6bb0 emu/mem.c --- 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; } diff -r 83e80c2c489c -r c0c2e99b6bb0 emu/mem.h --- 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 diff -r 83e80c2c489c -r c0c2e99b6bb0 tests/emu/a.out Binary file tests/emu/a.out has changed diff -r 83e80c2c489c -r c0c2e99b6bb0 tests/emu/test.c --- 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); }