Add branch_division stress test

Use integer log routine to stress test the branch division combo

Change-Id: I816d115998473e4d9caa312eaf20b359805b068f
diff --git a/tests/riscv-tests/BUILD b/tests/riscv-tests/BUILD
index e593b53..811032e 100644
--- a/tests/riscv-tests/BUILD
+++ b/tests/riscv-tests/BUILD
@@ -91,8 +91,7 @@
 [kelvin_binary(
     name = "rv32um_{}".format(test),
     srcs = [
-      "@riscv-tests//:isa/rv32um/{}.S".format(test),
-
+        "@riscv-tests//:isa/rv32um/{}.S".format(test),
     ],
     copts = [
         "-Itests/riscv-tests",
@@ -105,7 +104,6 @@
     ],
 ) for test in RV32UM_TESTS]
 
-
 kelvin_binary(
     name = "branch_modulo_test",
     srcs = [
@@ -115,3 +113,13 @@
         "//crt:crt_header",
     ],
 )
+
+kelvin_binary(
+    name = "branch_div_test",
+    srcs = [
+        "branch_div_test.cc",
+    ],
+    deps = [
+        "//crt:crt_header",
+    ],
+)
diff --git a/tests/riscv-tests/branch_div_test.cc b/tests/riscv-tests/branch_div_test.cc
new file mode 100644
index 0000000..74344fc
--- /dev/null
+++ b/tests/riscv-tests/branch_div_test.cc
@@ -0,0 +1,68 @@
+// Copyright 2023 Google LLC
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Use the routine of finding the integer part of log_3 to stress test
+// branch/div op combinations.
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "crt/kelvin.h"
+
+template <typename T>
+T get_int_log3(T a) {
+  T int_log3 = 0;
+  if (a < 3) return 0;
+  // Use do/while loop to compile the code without jump
+  do {
+    int_log3++;
+    a /= 3;
+  } while (a >= 3);
+  return int_log3;
+}
+
+template <typename T>
+T int_pow3(T a) {
+  T result = 1;
+  for (T i = 0; i < a; ++i) {
+    result *= 3;
+  }
+  return result;
+}
+
+uint32_t rand_uint32_input() {
+  uint32_t a = static_cast<uint32_t>(
+      ((rand() & 0xffff) << 16) |  // NOLINT(runtime/threadsafe_fn)
+      (rand() & 0xffff));          // NOLINT(runtime/threadsafe_fn)
+  return (a > 0) ? a : 1;
+}
+
+int32_t rand_int32_input() {
+  int32_t a = ((rand() & 0x7fff) << 16) |  // NOLINT(runtime/threadsafe_fn)
+              (rand() & 0xffff);           // NOLINT(runtime/threadsafe_fn)
+  return (a > 0) ? a : 1;
+}
+
+int main() {
+  constexpr int kSeed = 1000;
+  srand(kSeed);
+  uint32_t uint32_input = rand_uint32_input();
+  int32_t int32_input = rand_int32_input();
+  auto uint32_log3 = get_int_log3<uint32_t>(uint32_input);
+  printf("Unsigned input: %u, integer log3: %u\n", uint32_input, uint32_log3);
+  auto test = int_pow3<uint32_t>(uint32_log3);
+  // Make the check like this to prevent overflow
+  if (!(test <= uint32_input && test >= uint32_input / 3)) {
+    printf("Invalid log_3 %u for %u\n", uint32_log3, uint32_input);
+    exit(-1);
+  }
+  auto int32_log3 = get_int_log3<int32_t>(int32_input);
+  printf("Signed intput:%d, integer log3: %d\n", int32_input, int32_log3);
+  auto test1 = int_pow3<int32_t>(int32_log3);
+  if (!(test1 <= int32_input && test1 >= int32_input / 3)) {
+    printf("Invalid log_3 %d for %d\n", int32_log3, int32_input);
+    exit(-1);
+  }
+  return 0;
+}