diff --git a/avr.binary.tex b/avr.binary.tex index e545745..3f7b69e 100644 --- a/avr.binary.tex +++ b/avr.binary.tex @@ -62,6 +62,7 @@ } \newcommand{\avrloadc}[2][-Os -mmcu=atmega8]{% + \avr@init% \avr@compile{#2}{#1}% \avr@ihex@load{#2.hex}% } diff --git a/avr.bitops.tex b/avr.bitops.tex index 57d4b3d..638eb90 100644 --- a/avr.bitops.tex +++ b/avr.bitops.tex @@ -103,15 +103,22 @@ \xdef#2{\@tmpa\@tmpa\@tmpa\@tmpa\@tmpa\@tmpa\@tmpa\@tmpa#1}% } -\def\avr@bin@wtb@helper#1#2#3#4#5#6#7#8#9\@nnil{% - #9% +\def\avr@bin@word@low#1#2{% + \edef\@tempa{#1}% + \edef#2{\expandafter\avr@bin@word@low@helper\@tempa\@nnil}% +} +\def\avr@bin@word@low@helper#1#2#3#4#5#6#7#8#9\@nnil{#9} + +\def\avr@bin@word@high#1#2{% + \edef\@tempa{#1}% + \edef#2{\expandafter\avr@bin@word@high@helper\@tempa\@nnil}% +} +\def\avr@bin@word@high@helper#1#2#3#4#5#6#7#8#9\@nnil{% + #1#2#3#4#5#6#7#8% } % \avr@bin@wtb bs:word, \result = ((uint8_t) bs) -\def\avr@bin@wtb#1#2{% - \edef\@tempa{#1}% - \edef#2{\expandafter\avr@bin@wtb@helper\@tempa\@nnil}% -} +\def\avr@bin@wtb{\avr@bin@word@low} % \avr@bin@shiftleft bs:(byte|word), count, \result, \carry % -> \result = bs << count; \carry = (bs >> count) & 1 diff --git a/avr.instr.tex b/avr.instr.tex index d074bb5..d94d576 100644 --- a/avr.instr.tex +++ b/avr.instr.tex @@ -3,14 +3,17 @@ } \def\avr@error#1{% - \typeout{#1}\bye% + \errmessage{\the\avr@pc: #1}\bye% } % Execution Engine \def\avr@instr@step{% \avr@code@get{\avr@instr@current}% - %\avr@debug{\avr@instr@current}% + %\avr@reg@get{\csuse{avr@r24}}{\@@A}% + %\avr@reg@get{\csuse{avr@r28}}{\@@B}% + %\avr@reg@get{\csuse{avr@r29}}{\@@C}% + %\avr@debug{{r24=\@@A} {r28=\@@B} {r29=\@@C}}% % Dispatch Instruction by prefix \expandafter\avr@instr@dispatch\avr@instr@current\@nnil% \relax% @@ -76,7 +79,9 @@ % Match also from end for these prefixes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \csdef{avr@instr@1001010}{\avr@instr@matchend{1001010}} - +% POP/PUSH +\csdef{avr@instr@1001000}{\avr@instr@matchend{1001000}} +\csdef{avr@instr@1001001}{\avr@instr@matchend{1001001}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -109,7 +114,6 @@ \avr@reg@get{#2#3#4#5#6}{\avr@Rd}% \avr@debug{ADD - \%#2#3#4#5#6 <- #2#3#4#5#6 + \%#1#7}% \avr@debug{ADD - \avr@Rd <- \avr@Rd + \avr@Rr}% - \def\avr@instr@adder@RrPreprocess{\avr@bit@id}% \csuse{avr@instr@adder@helper}% \avr@reg@set{\avr@Rx}{#2#3#4#5#6}% \avr@pc@inc% @@ -124,7 +128,6 @@ \avr@flag@get C \avr@instr@extracarry% \avr@debug{ADC - \%#2#3#4#5#6 <- #2#3#4#5#6 + \%#1#7}% \avr@debug{ADC - \avr@Rd <- \avr@Rd + \avr@Rr + \avr@instr@extracarry}% - \def\avr@instr@adder@RrPreprocess{\avr@bit@id}% \csuse{avr@instr@adder@helper}% % Set the result register \avr@reg@set{\avr@Rx}{#2#3#4#5#6}% @@ -139,8 +142,7 @@ \def\avr@instr@extracarry{1}% \avr@debug{SUB - \%#2#3#4#5#6 <- #2#3#4#5#6 + \%#1#7}% \avr@debug{SUB - \avr@Rd <- \avr@Rd - \avr@Rr}% - \def\avr@instr@adder@RrPreprocess{\avr@bit@negate}% - \csuse{avr@instr@adder@helper}% + \csuse{avr@instr@subber@helper}% % Set the result register \avr@reg@set{\avr@Rx}{#2#3#4#5#6}% \avr@pc@inc% @@ -154,8 +156,7 @@ \xdef \avr@instr@extracarry {\avr@bit@negate \@@carry}% \avr@debug{SBC - \%#2#3#4#5#6 <- #2#3#4#5#6 + \%#1#7}% \avr@debug{SBC - \avr@Rd <- \avr@Rd - \avr@Rr - \@@carry}% - \def\avr@instr@adder@RrPreprocess{\avr@bit@negate}% - \csuse{avr@instr@adder@helper}% + \csuse{avr@instr@subber@helper}% % Set the result register \avr@reg@set{\avr@Rx}{#2#3#4#5#6}% \avr@pc@inc% @@ -168,14 +169,13 @@ \def\avr@Rr{#1#2#3#4#9}% \def\avr@instr@extracarry{1}% \avr@debug{SUBI - \%#2#3#4#5#6 <- #2#3#4#5#6(=\avr@Rd) - \avr@Rr}% - \def\avr@instr@adder@RrPreprocess{\avr@bit@negate}% - \csuse{avr@instr@adder@helper}% + \csuse{avr@instr@subber@helper}% % Set the result register \avr@reg@set{\avr@Rx}{1#5#6#7#8}% \avr@pc@inc% } -% SBCI - Substract Immediate +% SBCI - Substract Immediate with Carry \def\avr@instr@SBCI{\avr@instr@gen@regconst{0100}} \csdef{avr@instr@0100}#1#2#3#4#5#6#7#8#9\@nnil{% \avr@reg@get{1#5#6#7#8}{\avr@Rd}% @@ -183,8 +183,7 @@ \avr@flag@get C \@@carry% \xdef \avr@instr@extracarry {\avr@bit@negate \@@carry}% \avr@debug{SBCI - \%#2#3#4#5#6 <- #2#3#4#5#6(=\avr@Rd) - \avr@Rr -\@@carry}% - \def\avr@instr@adder@RrPreprocess{\avr@bit@negate}% - \csuse{avr@instr@adder@helper}% + \csuse{avr@instr@subber@helper}% % Set the result register \avr@reg@set{\avr@Rx}{1#5#6#7#8}% \avr@pc@inc% @@ -197,8 +196,7 @@ \avr@reg@get{#2#3#4#5#6}{\avr@Rd}% \def\avr@instr@extracarry{1}% \avr@debug{CP - #2#3#4#5#6(=\avr@Rd) - \%#1#7(=\avr@Rr)}% - \def\avr@instr@adder@RrPreprocess{\avr@bit@negate}% - \csuse{avr@instr@adder@helper}% + \csuse{avr@instr@subber@helper}% % Do not set the output register \avr@pc@inc% } @@ -211,8 +209,7 @@ \avr@flag@get C \@@carry% \xdef \avr@instr@extracarry {\avr@bit@negate \@@carry}% \avr@debug{CP - #2#3#4#5#6(=\avr@Rd) - \%#1#7(=\avr@Rr)}% - \def\avr@instr@adder@RrPreprocess{\avr@bit@negate}% - \csuse{avr@instr@adder@helper}% + \csuse{avr@instr@subber@helper}% % Do not set the output register \avr@pc@inc% } @@ -223,10 +220,9 @@ \avr@reg@get{1#5#6#7#8}{\avr@Rd}% \def\avr@Rr{#1#2#3#4#9}% \avr@flag@get C \@@carry% - \xdef \avr@instr@extracarry {\avr@bit@negate \@@carry}% + \xdef \avr@instr@extracarry{1}% \avr@debug{CPI - \%#2#3#4#5#6 <- #2#3#4#5#6(=\avr@Rd) - \avr@Rr -\@@carry}% - \def\avr@instr@adder@RrPreprocess{\avr@bit@negate}% - \csuse{avr@instr@adder@helper}% + \csuse{avr@instr@subber@helper}% % Set the result register \avr@pc@inc% } @@ -234,7 +230,6 @@ \csdef{avr@instr@adder@helper}{% % Convert the Bitstring to Integer values \avr@bin@tocount{\avr@Rd}{\avr@accA}% - \avr@bin@map{\avr@instr@adder@RrPreprocess}{\avr@Rr}{\avr@Rr}% \avr@bin@tocount{\avr@Rr}{\avr@accB}% \advance \avr@accA by \avr@accB\relax% \advance \avr@accA by \avr@instr@extracarry\relax% @@ -248,13 +243,14 @@ \avr@bin@msb@get{\avr@Rr}{\@@R}% \avr@bin@msb@get{\avr@Rd}{\@@D}% \avr@bin@msb@get{\avr@Rx}{\@@X}% + \avr@debug{{Rr7:\@@R} {Rd7:\@@D} {R7:\@@X}}% % \avr@debug{R: \@@R D: \@@D X:\@@X}% \def\avr@ADD@carry{% - \@@or {\@@and \@@D {\@@not \@@X}}% + \@@or {\@@and \@@R \@@D}% {% - \@@or{\@@and \@@R \@@D}% - {\@@and \@@R {\@@not \@@X}}}}% - \avr@flag@set C {\avr@instr@adder@RrPreprocess{\avr@ADD@carry}}% + \@@or{\@@and \@@R {\@@not \@@X}}% + {\@@and \@@X {\@@not \@@D}}}}% + \avr@flag@set C {\avr@ADD@carry}% % Two's Complement Overflow \def\@@tmp{\@@or% {\@@and \@@D {\@@and \@@R {\@@not \@@X}}}% @@ -269,11 +265,55 @@ {% \@@or{\@@and \@@R \@@D}% {\@@and \@@R {\@@not \@@X}}}}% - \avr@flag@set H {\avr@instr@adder@RrPreprocess{\avr@ADD@carry}}% + \avr@flag@set H {\avr@ADD@carry}% %% Update Dependend Flags (N, Z, S) \avr@flags@update \avr@Rx% } +\csdef{avr@instr@subber@helper}{% + % Convert the Bitstring to Integer values + \avr@bin@tocount{\avr@Rd}{\avr@accA}% + \avr@bin@negate{\avr@Rr}{\@@Rr}% + \avr@bin@tocount{\@@Rr}{\avr@accB}% + \advance \avr@accA by \avr@accB\relax% + \advance \avr@accA by \avr@instr@extracarry\relax% + \avr@count@modulo@byte{\avr@accA}% + \avr@count@tobin@b{\avr@accA}{\avr@Rx}% + % Calculate the Flags + \let\@@not=\avr@bit@negate% + \let\@@and=\avr@bit@and% + \let\@@or=\avr@bit@or% + %% Carry + \avr@bin@msb@get{\avr@Rr}{\@@R}% + \avr@bin@msb@get{\avr@Rd}{\@@D}% + \avr@bin@msb@get{\avr@Rx}{\@@X}% + \avr@debug{{Rr7:\@@R} {Rd7:\@@D} {R7:\@@X}}% + \def\avr@ADD@carry{% + \@@or {\@@and {\@@not \@@D} \@@R}% + {% + \@@or{\@@and \@@R \@@X}% + {\@@and \@@X {\@@not \@@D}}}}% + \avr@flag@set C {\avr@ADD@carry}% + % Two's Complement Overflow + \def\@@tmp{\@@or% + {\@@and \@@D {\@@and {\@@not \@@R} {\@@not \@@X}}}% + {\@@and {\@@not \@@D} {\@@and \@@R \@@X}}}% + \avr@flag@set V \@@tmp% + % Half Carry + \avr@bin@getbit{\avr@Rr}{3}{\@@R}% + \avr@bin@getbit{\avr@Rd}{3}{\@@D}% + \avr@bin@getbit{\avr@Rx}{3}{\@@X}% + \def\avr@ADD@carry{% + \@@or {\@@and {\@@not \@@D} \@@R}% + {% + \@@or{\@@and \@@R \@@X}% + {\@@and \@@X {\@@not \@@D}}}}% + \avr@flag@set H {\avr@ADD@carry}% + %% Update Dependend Flags (N, Z, S) + \avr@flags@update \avr@Rx% +} + + % LDI -- Load Immediate Value \def\avr@instr@LDI{\avr@instr@gen@regconst{1110}} \def\avr@instr@SER#1#2{\avr@instr@gen@regconst{1110}{#1}{#2}{11111111}} @@ -308,6 +348,16 @@ #2=\avr@count@tmpa\relax% } +\def\avr@instr@rjump@dec#1#2{% + \avr@bin@tocount{0000#1}{\avr@count@tmpa}% + \ifnum \avr@count@tmpa > 2047% + \avr@count@tmpb=\avr@count@tmpa% + \avr@count@tmpa=-4096% + \advance \avr@count@tmpa by \avr@count@tmpb\relax% + \fi% + #2=\avr@count@tmpa\relax% +} + % BRBC -- Branch if Bit in SREG is cleared \def\avr@instr@BRBC#1#2#3{% ADD PC, Bit, Offset \avr@instr@jump@enc{#3}{\@@offset}% @@ -417,6 +467,52 @@ \avr@pc@inc% } +% RJMP +% #1 = Offset +% FIXME latex assembler +\csdef{avr@instr@1100}#1\@nnil{ + \avr@instr@rjump@dec{#1}{\avr@count@tmpa}% + \avr@debug{RJMP \the\avr@count@tmpa}% + \avr@pc@add{\avr@count@tmpa}% + \avr@pc@inc% +} + +% RCALL +\csdef{avr@instr@1101}#1\@nnil{ + \avr@count@tobin@w{\the\avr@pc}{\@@pc}% + \avr@instr@rjump@dec{#1}{\avr@count@tmpa}% + \avr@reg@get{\csuse{avr@r24}}{\@@A}% + \avr@reg@get{\csuse{avr@r25}}{\@@B}% + \avr@reg@get{\csuse{avr@r26}}{\@@C}% + \avr@debug{RCALL \the\avr@count@tmpa {r24:\@@A} {r25:\@@B} {r26:\@@C}}% + \avr@pc@add{\avr@count@tmpa}% + \avr@bin@word@low{\@@pc}{\@@low}% + \avr@bin@word@high{\@@pc}{\@@high}% + \avr@mem@set{\@@low}{\the\avr@stackptr}% + \advance\avr@stackptr by -1\relax% + \avr@mem@set{\@@high}{\the\avr@stackptr}% + \advance\avr@stackptr by -1\relax% + \avr@pc@inc% + \avr@debug{ done}% +} + +% RET +\def\avr@instr@RET#1{% + \avr@code@set{1001010100001000}{#1}% +} +\csdef{avr@instr@1001010100001000}\@nnil{% + \avr@reg@get{\csuse{avr@r24}}{\@@X}% + \avr@debug{RET (r24=\@@X)}% + \advance\avr@stackptr by 1\relax + \avr@mem@get{\the\avr@stackptr}{\@@high}% + \advance\avr@stackptr by 1\relax + \avr@mem@get{\the\avr@stackptr}{\@@low}% + \avr@bin@tocount{\@@high \@@low}{\avr@pc}% + \avr@pc@inc\relax% + \avr@debug{ done }% +} + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Data transfert instructions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -444,6 +540,30 @@ \avr@pc@inc% } +% PUSH +\def\avr@instr@PUSH#1#2{% PC, Reg + \avr@code@set{1001001#21111}{#1}% +} + +\csdef{avr@instr@1001001:1111}#1\@nnil{% + \avr@reg@get{#1}{\avr@Rr}% + \avr@debug{PUSH #1(=\avr@Rr)}% + \avr@mem@set{\avr@Rr}{\the\avr@stackptr}% + \advance\avr@stackptr by -1\relax% + \avr@pc@inc% +} + +% POP +\def\avr@instr@POP#1#2{% PC, Reg + \avr@code@set{1001000#21111}{#1}% +} +\csdef{avr@instr@1001000:1111}#1\@nnil{% + \advance\avr@stackptr by 1\relax% + \avr@debug{POP #1}% + \avr@mem@get{\the\avr@stackptr}{\avr@Rr}% + \avr@reg@set{\avr@Rr}{#1}% + \avr@pc@inc% +} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -615,8 +735,7 @@ \avr@debug{NEG: #1(=\avr@Rr)}% \def\avr@Rd{00000000}% \def\avr@instr@extracarry{1}% - \def\avr@instr@adder@RrPreprocess{\avr@bit@negate}% - \csuse{avr@instr@adder@helper}% + \csuse{avr@instr@subber@helper}% % Set the result register \avr@reg@set{\avr@Rx}{#1}% \avr@pc@inc% diff --git a/avr.memory.tex b/avr.memory.tex index b83d539..cee4fab 100644 --- a/avr.memory.tex +++ b/avr.memory.tex @@ -5,6 +5,7 @@ \avr@flag@init% \avr@reg@init% \avr@pc@init% + \avr@stack@init% } \newcount\avr@accA @@ -94,8 +95,8 @@ \def\avr@flags@update#1{% % Negate Flag - \avr@bin@msb@get{#1}{\@@X}% - \avr@flag@set N \@@X% + \avr@bin@msb@get{#1}{\@@N}% + \avr@flag@set N \@@N% % Zero Flag \avr@bin@tocount{#1}{\avr@count@tmpa}% \ifnum \avr@count@tmpa = 0% @@ -105,8 +106,8 @@ \fi% % Signed Flag \avr@flag@get V \@@V% - \edef\@@tmp{\avr@bit@xor \@@X \@@V}% - \avr@flag@set S \@@V% + \edef\@@tmp{\avr@bit@xor \@@N \@@V}% + \avr@flag@set S \@@tmp% } %% Registers @@ -211,6 +212,47 @@ \csxdef{avr@code@#2}{#1}% } %% RAM +\newcount\avr@stackptr +\def\avr@stack@init{ + \avr@stackptr=0% +} + +\def\avr@stack@SPL@get#1{% + \avr@count@tobin@w{\avr@stackptr}{\@@stack}% + \avr@bin@word@low{\@@stack}{#1}% +} +\def\avr@stack@SPH@get#1{% + \avr@count@tobin@w{\avr@stackptr}{\@@stack}% + \avr@bin@word@high{\@@stack}{#1}% +} + +\def\avr@stack@SPL@set#1{% + \avr@count@tobin@w{\avr@stackptr}{\@@stack}% + \avr@bin@word@high{\@@stack}{\@@high}% + \avr@bin@tocount{\@@high #1}{\avr@stackptr}% + \avr@debug{ SP=\the\avr@stackptr} +} + +\def\avr@stack@SPH@set#1{% + \avr@count@tobin@w{\avr@stackptr}{\@@stack}% + \avr@bin@word@low{\@@stack}{\@@low}% + \avr@bin@tocount{#1\@@low}{\avr@stackptr}% + \avr@debug{ SP=\the\avr@stackptr} +} + +\def\avr@mem@set#1#2{% Bitstring, Address (as number) + \avr@debug{ MEM W *#2=#1}% + \csxdef{avr@mem@#2}{#1}% +} + +\def\avr@mem@get#1#2{% Address (as number), Target Macro + \ifcsdef{avr@mem@#1}{% + \edef#2{\csuse{avr@mem@#1}}% + }{% + \edef#2{00000000}% + }% + \avr@debug{ MEM R *#1==#2}% +} %%% Local Variables: diff --git a/avr.testsuite.tex b/avr.testsuite.tex index a672f5d..fd52238 100644 --- a/avr.testsuite.tex +++ b/avr.testsuite.tex @@ -87,7 +87,7 @@ \avr@test@helper{00001111}{00010000}% \avr@test@REG{r17}{11111111}% - \avr@test@SREG{00000101}% + \avr@test@SREG{00010101}% } \appto\avr@test{\avr@test@SUB} @@ -110,7 +110,7 @@ \avr@test@helper{00000000}{00000000}{00000000}{00000001}% \avr@test@REG{r17}{11111111}% \avr@test@REG{r18}{11111111}% - \avr@test@SREG{00100101}% + \avr@test@SREG{00110101}% \avr@test@helper{00000000}{10000000}{00000000}{00000001}% \avr@test@REG{r17}{00000000}% @@ -204,11 +204,11 @@ \avr@instr@stepn{2}% \avr@test@REG{r30}{11111111} - \avr@test@SREG{00000101} + \avr@test@SREG{00010101} \avr@instr@stepn{1}% \avr@test@REG{r30}{11111101} - \avr@test@SREG{00000100} + \avr@test@SREG{00010100} } \preto\avr@test{\avr@test@SUBI} @@ -279,7 +279,7 @@ \avr@instr@stepn{2}% \avr@test@REG{r20}{11111111} - \avr@test@SREG{00100101} + \avr@test@SREG{00110101} \avr@instr@stepn{1}% \avr@test@REG{r20}{00000001} @@ -296,7 +296,7 @@ \avr@instr@stepn{2}% \avr@test@REG{r20}{11111110} - \avr@test@SREG{00000101} + \avr@test@SREG{00010101} \avr@instr@stepn{1}% \avr@test@REG{r20}{00000001} @@ -336,7 +336,7 @@ \avr@instr@stepn{2}% \avr@test@REG{r20}{11000100} - \avr@test@SREG{00000101} + \avr@test@SREG{00010101} } \preto\avr@test{\avr@test@ASR} @@ -372,7 +372,7 @@ \avr@instr@stepn{1}% \avr@test@REG{r20}{10000000} - \avr@test@SREG{00011100} + \avr@test@SREG{00001100} \avr@instr@stepn{1}% \avr@test@REG{r20}{01000000} @@ -385,11 +385,64 @@ int main() { } \end{filecontents*} \def\avr@test@emptymain{% + \avr@test@setup{Empty Main Function}% \avrloadc{empty-main.c} - \avr@instr@stepn{3} + \avr@instr@stepn{50} } \preto\avr@test{\avr@test@emptymain} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{filecontents*}{sum-rec.c} +#include + +char sum(char n) { + if (n <= 1) { + return n; + } + return n + sum(n-1); +} + +int main() { + UDR = sum(4); + asm volatile ("break"); +} +\end{filecontents*} + +\def\avr@test@sumRec{% + \avr@test@setup{Summing Recursive}% + \avrloadc{sum-rec.c} + \avr@instr@stepn{1000} + \avr@test@REG{r24}{00001010} +} + +\preto\avr@test{\avr@test@sumRec} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{filecontents*}{fibonacci-rec.c} +#include + +char fib(char n) { + if (n <= 1) { + return 1; + } + return fib(n-1) + fib(n-2); +} + +int main() { + UDR = fib(5); + asm volatile ("break"); +} +\end{filecontents*} + +\def\avr@test@fibRec{% + \avr@test@setup{Fibonacci Recursive}% + \avrloadc{fibonacci-rec.c} + \avr@instr@stepn{1000} + \avr@test@REG{r24}{00001000} +} +\preto\avr@test{\avr@test@fibRec} + + %%% Local Variables: %%% mode: latex diff --git a/avr.tex b/avr.tex index 47556b6..dff803c 100644 --- a/avr.tex +++ b/avr.tex @@ -15,6 +15,7 @@ \input{avr.bitops} \input{avr.memory} \input{avr.instr} +\input{avr.io} \input{avr.testsuite}