fork download
  1. #include <avr/io.h>
  2. #include <stdio.h>
  3.  
  4. #include <util/setbaud.h>
  5.  
  6. void uart_init (void)
  7. {
  8. UBRR0H = UBRRH_VALUE;
  9. UBRR0L = UBRRL_VALUE;
  10. #if USE_2X
  11. UCSR0A |= _BV(U2X0);
  12. #else
  13. UCSR0A &= ~(_BV(U2X0));
  14. #endif
  15. UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
  16. UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */
  17. }
  18.  
  19. int uart_putchar (char c, FILE *stream)
  20. {
  21. loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
  22. UDR0 = c;
  23. return 0;
  24. }
  25.  
  26. FILE uart_output = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
  27.  
  28. // Returns the index of the highest 1-bit in an integer, starting with 1,
  29. // or zero if the operand is zero.
  30. // Working version. Uses r16 for temporary and mov's the result into %[res].
  31. #if 0
  32. static uint8_t highest_bit (uint32_t op)
  33. {
  34. uint8_t res;
  35. __asm__(
  36. " cpse %D[op],__zero_reg__\n"
  37. " rjmp foundD%=\n"
  38. " cpse %C[op],__zero_reg__\n"
  39. " rjmp foundC%=\n"
  40. " cpse %B[op],__zero_reg__\n"
  41. " rjmp foundB%=\n"
  42. " cpse %A[op],__zero_reg__\n"
  43. " rjmp foundA%=\n"
  44. " clr r16\n"
  45. " rjmp end%=\n"
  46. "foundD%=:\n"
  47. " ldi r16,0x18\n"
  48. " mov r17,%D[op]\n"
  49. " rjmp examine%=\n"
  50. "foundC%=:\n"
  51. " ldi r16,0x10\n"
  52. " mov r17,%C[op]\n"
  53. " rjmp examine%=\n"
  54. "foundB%=:\n"
  55. " ldi r16,0x08\n"
  56. " mov r17,%B[op]\n"
  57. " rjmp examine%=\n"
  58. "foundA%=:\n"
  59. " ldi r16,0x00\n"
  60. " mov r17,%A[op]\n"
  61. "examine%=:\n"
  62. " bst r17,7\n"
  63. " brts bit7%=\n"
  64. " bst r17,6\n"
  65. " brts bit6%=\n"
  66. " bst r17,5\n"
  67. " brts bit5%=\n"
  68. " bst r17,4\n"
  69. " brts bit4%=\n"
  70. " bst r17,3\n"
  71. " brts bit3%=\n"
  72. " bst r17,2\n"
  73. " brts bit2%=\n"
  74. " bst r17,1\n"
  75. " brts bit1%=\n"
  76. " subi r16,0xFF\n"
  77. " rjmp end%=\n"
  78. "bit7%=:\n"
  79. " subi r16,0xF8\n"
  80. " rjmp end%=\n"
  81. "bit6%=:\n"
  82. " subi r16,0xF9\n"
  83. " rjmp end%=\n"
  84. "bit5%=:\n"
  85. " subi r16,0xFA\n"
  86. " rjmp end%=\n"
  87. "bit4%=:\n"
  88. " subi r16,0xFB\n"
  89. " rjmp end%=\n"
  90. "bit3%=:\n"
  91. " subi r16,0xFC\n"
  92. " rjmp end%=\n"
  93. "bit2%=:\n"
  94. " subi r16,0xFD\n"
  95. " rjmp end%=\n"
  96. "bit1%=:\n"
  97. " subi r16,0xFE\n"
  98. "end%=:\n"
  99. " mov %[res],r16\n"
  100. : [res] "=r" (res)
  101. : [op] "r" (op)
  102. : "r16", "r17"
  103. );
  104. return res;
  105. }
  106. #endif
  107.  
  108. // Broken version. Works directly with %[res].
  109. // This code was obtained from the above code like that:
  110. // - remove the final mov instruction,
  111. // - remove r16 from clobber list,
  112. // - replace all use of r16 with %[res].
  113. // It's only "half" broken. While the main loop below should print out the numbers 0-32.
  114. // with this code it prints:
  115. // 0 1 1 1 1 1 1 1 1 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
  116. static uint8_t highest_bit (uint32_t op)
  117. {
  118. uint8_t res;
  119. __asm__(
  120. " cpse %D[op],__zero_reg__\n"
  121. " rjmp foundD%=\n"
  122. " cpse %C[op],__zero_reg__\n"
  123. " rjmp foundC%=\n"
  124. " cpse %B[op],__zero_reg__\n"
  125. " rjmp foundB%=\n"
  126. " cpse %A[op],__zero_reg__\n"
  127. " rjmp foundA%=\n"
  128. " clr %[res]\n"
  129. " rjmp end%=\n"
  130. "foundD%=:\n"
  131. " ldi %[res],0x18\n"
  132. " mov r17,%D[op]\n"
  133. " rjmp examine%=\n"
  134. "foundC%=:\n"
  135. " ldi %[res],0x10\n"
  136. " mov r17,%C[op]\n"
  137. " rjmp examine%=\n"
  138. "foundB%=:\n"
  139. " ldi %[res],0x08\n"
  140. " mov r17,%B[op]\n"
  141. " rjmp examine%=\n"
  142. "foundA%=:\n"
  143. " ldi %[res],0x00\n"
  144. " mov r17,%A[op]\n"
  145. "examine%=:\n"
  146. " bst r17,7\n"
  147. " brts bit7%=\n"
  148. " bst r17,6\n"
  149. " brts bit6%=\n"
  150. " bst r17,5\n"
  151. " brts bit5%=\n"
  152. " bst r17,4\n"
  153. " brts bit4%=\n"
  154. " bst r17,3\n"
  155. " brts bit3%=\n"
  156. " bst r17,2\n"
  157. " brts bit2%=\n"
  158. " bst r17,1\n"
  159. " brts bit1%=\n"
  160. " subi %[res],0xFF\n"
  161. " rjmp end%=\n"
  162. "bit7%=:\n"
  163. " subi %[res],0xF8\n"
  164. " rjmp end%=\n"
  165. "bit6%=:\n"
  166. " subi %[res],0xF9\n"
  167. " rjmp end%=\n"
  168. "bit5%=:\n"
  169. " subi %[res],0xFA\n"
  170. " rjmp end%=\n"
  171. "bit4%=:\n"
  172. " subi %[res],0xFB\n"
  173. " rjmp end%=\n"
  174. "bit3%=:\n"
  175. " subi %[res],0xFC\n"
  176. " rjmp end%=\n"
  177. "bit2%=:\n"
  178. " subi %[res],0xFD\n"
  179. " rjmp end%=\n"
  180. "bit1%=:\n"
  181. " subi %[res],0xFE\n"
  182. "end%=:\n"
  183. : [res] "=r" (res)
  184. : [op] "r" (op)
  185. : "r17"
  186. );
  187. return res;
  188. }
  189.  
  190. int main ()
  191. {
  192. uart_init();
  193. stdout = &uart_output;
  194.  
  195. printf("%d", highest_bit(0));
  196. for (int i = 0; i < 32; i++) {
  197. printf(" %d", highest_bit((uint32_t)1 << i));
  198. }
  199. printf("\n");
  200. }
  201.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty