From 44fe73ff8f6fbebd21175cbb32dad7b6d59c98c1 Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Mon, 29 Sep 2014 22:59:42 +0200 Subject: [PATCH] SBC/CPC: Fix Calculation of Zero Flag For the Sub/Compare with carry, the old Z flag is also used to AND the newZ: newZ = (result==0) & oldZ --- avr.instr.tex | 13 +++++++++--- avr.testsuite.tex | 1 + tests/float.c | 22 +++++++------------- tests/mul.c | 9 +++++++- tests/printf.c | 53 ++++++++++++++++++++++++++++++++++++++--------- tests/shift.c | 26 +++++++++++++++++++++++ tests/test-suite | 6 ++++-- 7 files changed, 100 insertions(+), 30 deletions(-) create mode 100644 tests/shift.c diff --git a/avr.instr.tex b/avr.instr.tex index f563366..0bccd8e 100644 --- a/avr.instr.tex +++ b/avr.instr.tex @@ -225,9 +225,12 @@ \avr@reg@get{1#5#6#7#8}{\avr@Rd}% \def\avr@Rr{#1#2#3#4#9}% \avr@flag@get C \@@carry% + \avr@flag@get Z \@@oldZ% \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}% \csuse{avr@instr@subber@helper}% + \avr@flag@get Z \@@newZ% + \avr@flag@set Z {\avr@bit@and \@@oldZ \@@newZ}% % Set the result register \avr@reg@set{\avr@Rx}{1#5#6#7#8}% \avr@pc@inc% @@ -251,9 +254,12 @@ \avr@reg@get{#1#7}{\avr@Rr}% \avr@reg@get{#2#3#4#5#6}{\avr@Rd}% \avr@flag@get C \@@carry% + \avr@flag@get Z \@@oldZ% \xdef \avr@instr@extracarry {\avr@bit@negate \@@carry}% - \avr@debug{CPC - #2#3#4#5#6(=\avr@Rd) - \%#1#7(=\avr@Rr)}% + \avr@debug{CPC - #2#3#4#5#6(=\avr@Rd) - \%#1#7(=\avr@Rr) - \@@carry}% \csuse{avr@instr@subber@helper}% + \avr@flag@get Z \@@newZ% + \avr@flag@set Z {\avr@bit@and \@@oldZ \@@newZ}% % Do not set the output register \avr@pc@inc% } @@ -415,8 +421,9 @@ }% \avr@flag@set C {\@@and {\@@not \@@X} \@@D}% \avr@flag@set N \@@X% - \avr@flag@set V {\@@and {\@@not \@@D} \@@X}% - \avr@flag@set S {\@@xor \@@X {\@@and {\@@not \@@D} \@@X}}% + \edef\@@V{\@@and {\@@not \@@D} \@@X}% + \avr@flag@set V \@@V% + \avr@flag@set S {\@@xor \@@X \@@V}% % Set the Result \avr@regw@set{\avr@Rx}{11#3#4}% \avr@pc@inc% diff --git a/avr.testsuite.tex b/avr.testsuite.tex index acf1fbf..ebbcd9a 100644 --- a/avr.testsuite.tex +++ b/avr.testsuite.tex @@ -34,6 +34,7 @@ }{% \avr@error{UDR unequal: #1 != \avr@UDR}% }% + \def\avr@UDR{}% } % Hook Macro for the tests diff --git a/tests/float.c b/tests/float.c index aebeb5a..af6a8ed 100644 --- a/tests/float.c +++ b/tests/float.c @@ -17,31 +17,25 @@ int main(void) { stdout = &mystdout; - printf("Hello, world!"); + volatile float a = 0.23; + volatile float b = 0.43; + + printf("%.2f", 1/ (a * b * 3)); asm volatile("break;"); - - volatile float foo = 0.23; - printf("%.2f", foo); - - asm volatile("break;"); - - return 0; } /** - check-name: Print to Stdout and Float + check-name: Calculate with floats + compiler-opts: -Wl,-u,vfprintf -lm -lprintf_flt + check-start: \avr@instr@stepn{100000} - \avr@test@UDR{Hello, world!} - \xdef\avr@UDR{} + \avr@test@UDR{3.37} - \avr@instr@stepn{100000} - \avr@test@UDR{0.23} - \def\avr@UDR{} check-end: **/ diff --git a/tests/mul.c b/tests/mul.c index b151383..49f0555 100644 --- a/tests/mul.c +++ b/tests/mul.c @@ -17,8 +17,11 @@ int main() { volatile uint16_t y = 55; foo[5] = x * y; + foo[20] = 165; + + itoa((unsigned char)foo[20], &foo[6], 10); + itoa((signed char)foo[20], &foo[9], 10); - itoa(165, &foo[6], 10); asm volatile ("break"); } @@ -41,5 +44,9 @@ int main() { \avr@test@MEM{103}{00110110} % '6' \avr@test@MEM{104}{00110101} % '5' + \avr@test@MEM{105}{00101101} % '-' + \avr@test@MEM{106}{00111001} % '9' + \avr@test@MEM{107}{00110001} % '1' + check-end: */ diff --git a/tests/printf.c b/tests/printf.c index fc255ba..e8d14fb 100644 --- a/tests/printf.c +++ b/tests/printf.c @@ -1,20 +1,47 @@ #include #include -volatile char buffer[30]; +char buffer[30]; + +volatile char buf[3]; + +static int uart_putchar(char c, FILE *stream); +static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, + _FDEV_SETUP_WRITE); +static int +uart_putchar(char c, FILE *stream) +{ + UDR = c; + return 0; +} -volatile uint16_t xxx = 165; int main(void) { - asm volatile("break;"); + stdout = &mystdout; + + buf[0] = 'x'; + buf[1] = 'y'; + buf[2] = '\0'; + + puts(buf); - // sprintf(buffer, "%d", xxx); - __ultoa_invert(xxx, buffer, 10); asm volatile("break;"); + printf(":%c", buf[0]); + + asm volatile("break;"); + + printf(":%d:", buf[1]); + + asm volatile("break;"); + + volatile float x=0.23; + printf(":%.2f:", x); + + asm volatile("break;"); return 0; } @@ -22,15 +49,21 @@ main(void) /** check-name: Print to Stdout + compiler-opts: -Wl,-u,vfprintf -lm -lprintf_flt check-start: \avr@instr@stepn{100000} - \avr@instr@executed=0 - \avr@instr@stepn{100000} + \avr@test@UDR{xy^10} % ^10 == \n + \def\avr@UDR{} - \avr@test@MEM{96}{00110001} % '1' - \avr@test@MEM{97}{00110110} % '6' - \avr@test@MEM{98}{00110101} % '5' + \avr@instr@stepn{100000} + \avr@test@UDR{:x} + + \avr@instr@stepn{100000} + \avr@test@UDR{:121:} + + \avr@instr@stepn{100000} + \avr@test@UDR{:0.23:} check-end: **/ diff --git a/tests/shift.c b/tests/shift.c new file mode 100644 index 0000000..fe64b4c --- /dev/null +++ b/tests/shift.c @@ -0,0 +1,26 @@ +#include + +volatile char foo[30]; + +int main() { + foo[0] = 5; + foo[1] = 42; + foo[2] = foo[1] >> foo[0]; + foo[3] = foo[1] << (foo[0]>>2); + + + asm volatile ("break"); +} + +/* + check-name: Shift Operations + check-start: + \avr@instr@stepn{1000} + + \avr@test@MEM{96}{00000101} % 5 + \avr@test@MEM{97}{00101010} % 42 + \avr@test@MEM{98}{00000001} % 0 + \avr@test@MEM{99}{01010100} % 42 + + check-end: +*/ diff --git a/tests/test-suite b/tests/test-suite index 325c532..0422ca6 100755 --- a/tests/test-suite +++ b/tests/test-suite @@ -96,7 +96,8 @@ do_test() echo -n "TEST $test_name ($file)" cp HEADER "$file".tex - echo "\avrloadc[-lm -Os -mmcu=atmega8]{$file}" >> "$file".tex + get_value compiler-opts "$file" + echo "\avrloadc[-Os -mmcu=atmega8 $last_result]{$file}" >> "$file".tex awk '/check-start/,/check-end/ {print}' $file \ | egrep -v 'check-(start|end)' >> "$file".tex @@ -120,7 +121,8 @@ do_test() test_failed=1 else get_value BREAK "$file".output - echo " ($last_result)" + echo " ($last_result)" | sed 's/ instructions//' | tr -d "\n" + echo fi if [ "$test_failed" -eq "1" ]; then