Sfoglia il codice sorgente

Implement 64:32->32 division and use it to avoid arithmetic overflow in time_from_samples()

Keir Fraser 3 anni fa
parent
commit
7fca1c9315
3 ha cambiato i file con 14 aggiunte e 1 eliminazioni
  1. 2 0
      inc/util.h
  2. 1 1
      src/floppy.c
  3. 11 0
      src/util.c

+ 2 - 0
inc/util.h

@@ -74,6 +74,8 @@ int snprintf(char *str, size_t size, const char *format, ...)
 #define htobe16(x) _rev16(x)
 #define htobe32(x) _rev32(x)
 
+uint32_t udiv64(uint64_t dividend, uint32_t divisor);
+
 /* Board-specific callouts */
 void board_init(void);
 void act_led(bool_t on);

+ 1 - 1
src/floppy.c

@@ -22,7 +22,7 @@
 #define TIM_PSC (SYSCLK_MHZ / SAMPLE_MHZ)
 #define sample_ns(x) (((x) * SAMPLE_MHZ) / 1000)
 #define sample_us(x) ((x) * SAMPLE_MHZ)
-#define time_from_samples(x) ((x) * TIME_MHZ / SAMPLE_MHZ)
+#define time_from_samples(x) udiv64((uint64_t)(x) * TIME_MHZ, SAMPLE_MHZ)
 
 #define write_pin(pin, level) \
     gpio_write_pin(gpio_##pin, pin_##pin, level ? O_TRUE : O_FALSE)

+ 11 - 0
src/util.c

@@ -142,6 +142,17 @@ char *strcpy(char *dest, const char *src)
     return dest;
 }
 
+/* 64:32->32q division requiring 32:32->64 multiply. Cortex M3+ */
+uint32_t udiv64(uint64_t dividend, uint32_t divisor)
+{
+    uint32_t x, q = 0;
+    for (x = 1u<<31; x != 0; x >>= 1) {
+        if (((uint64_t)(q|x)*divisor) <= dividend)
+            q |= x;
+    }
+    return q;
+}
+
 /*
  * Local variables:
  * mode: C