diff --git a/src/org/sosy_lab/java_smt/api/FloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/api/FloatingPointFormulaManager.java
index 62bb3afbe4..5820a8593e 100644
--- a/src/org/sosy_lab/java_smt/api/FloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/api/FloatingPointFormulaManager.java
@@ -34,6 +34,9 @@
  */
 public interface FloatingPointFormulaManager {
 
+  /** Creates a formula for the given floating point rounding mode. */
+  FloatingPointRoundingModeFormula makeRoundingMode(FloatingPointRoundingMode pRoundingMode);
+
   /**
    * Creates a floating point formula representing the given double value with the specified type.
    */
diff --git a/src/org/sosy_lab/java_smt/api/FloatingPointRoundingModeFormula.java b/src/org/sosy_lab/java_smt/api/FloatingPointRoundingModeFormula.java
index ead8fc04af..b9fb69fd73 100644
--- a/src/org/sosy_lab/java_smt/api/FloatingPointRoundingModeFormula.java
+++ b/src/org/sosy_lab/java_smt/api/FloatingPointRoundingModeFormula.java
@@ -11,8 +11,11 @@
 import com.google.errorprone.annotations.Immutable;
 
 /**
- * Formula representing a rounding mode for floating-point operations. This is currently unused by
- * the API but necessary for traversal of formulas with such terms.
+ * Formula representing a rounding mode for floating-point operations.
+ *
+ * 
Rounding mode formulas are used by floating-point formulas to select the rounding mode for the
+ * operation. Use {@link FloatingPointFormulaManager#makeRoundingMode(FloatingPointRoundingMode)} to
+ * wrap a {@link org.sosy_lab.java_smt.api.FloatingPointRoundingMode} value inside a new formula.
  */
 @Immutable
 public interface FloatingPointRoundingModeFormula extends Formula {}
diff --git a/src/org/sosy_lab/java_smt/api/FunctionDeclarationKind.java b/src/org/sosy_lab/java_smt/api/FunctionDeclarationKind.java
index a203fa1f2d..bb8a3929ba 100644
--- a/src/org/sosy_lab/java_smt/api/FunctionDeclarationKind.java
+++ b/src/org/sosy_lab/java_smt/api/FunctionDeclarationKind.java
@@ -252,21 +252,6 @@ public enum FunctionDeclarationKind {
   /** Equal over floating points. */
   FP_EQ,
 
-  /** Rounding over floating points. */
-  FP_ROUND_EVEN,
-
-  /** Rounding over floating points. */
-  FP_ROUND_AWAY,
-
-  /** Rounding over floating points. */
-  FP_ROUND_POSITIVE,
-
-  /** Rounding over floating points. */
-  FP_ROUND_NEGATIVE,
-
-  /** Rounding over floating points. */
-  FP_ROUND_ZERO,
-
   /** Rounding over floating points. */
   FP_ROUND_TO_INTEGRAL,
 
diff --git a/src/org/sosy_lab/java_smt/basicimpl/AbstractFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/basicimpl/AbstractFloatingPointFormulaManager.java
index 47c847afe2..a653948bb3 100644
--- a/src/org/sosy_lab/java_smt/basicimpl/AbstractFloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/basicimpl/AbstractFloatingPointFormulaManager.java
@@ -22,6 +22,7 @@
 import org.sosy_lab.java_smt.api.FloatingPointFormulaManager;
 import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
 import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
 import org.sosy_lab.java_smt.api.Formula;
 import org.sosy_lab.java_smt.api.FormulaType;
 import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType;
@@ -60,6 +61,12 @@ private TFormulaInfo getRoundingMode(FloatingPointRoundingMode pFloatingPointRou
     return roundingModes.computeIfAbsent(pFloatingPointRoundingMode, this::getRoundingModeImpl);
   }
 
+  @Override
+  public FloatingPointRoundingModeFormula makeRoundingMode(
+      FloatingPointRoundingMode pRoundingMode) {
+    return getFormulaCreator().encapsulateRoundingMode(getRoundingMode(pRoundingMode));
+  }
+
   protected FloatingPointFormula wrap(TFormulaInfo pTerm) {
     return getFormulaCreator().encapsulateFloatingPoint(pTerm);
   }
diff --git a/src/org/sosy_lab/java_smt/basicimpl/FormulaCreator.java b/src/org/sosy_lab/java_smt/basicimpl/FormulaCreator.java
index 748fdd7b3b..cf383fde5a 100644
--- a/src/org/sosy_lab/java_smt/basicimpl/FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/basicimpl/FormulaCreator.java
@@ -160,6 +160,14 @@ protected FloatingPointFormula encapsulateFloatingPoint(TFormulaInfo pTerm) {
     return new FloatingPointFormulaImpl<>(pTerm);
   }
 
+  protected FloatingPointRoundingModeFormula encapsulateRoundingMode(TFormulaInfo pTerm) {
+    checkArgument(
+        getFormulaType(pTerm).isFloatingPointRoundingModeType(),
+        "Floatingpoint rounding mode formula has unexpected type: %s",
+        getFormulaType(pTerm));
+    return new FloatingPointRoundingModeFormulaImpl<>(pTerm);
+  }
+
   protected  ArrayFormula encapsulateArray(
       TFormulaInfo pTerm, FormulaType pIndexType, FormulaType pElementType) {
     checkArgument(
diff --git a/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingFloatingPointFormulaManager.java
index 74b1677375..817fb05ff1 100644
--- a/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingFloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/delegate/debugging/DebuggingFloatingPointFormulaManager.java
@@ -17,6 +17,7 @@
 import org.sosy_lab.java_smt.api.FloatingPointFormulaManager;
 import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
 import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
 import org.sosy_lab.java_smt.api.Formula;
 import org.sosy_lab.java_smt.api.FormulaType;
 import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType;
@@ -31,6 +32,15 @@ public class DebuggingFloatingPointFormulaManager implements FloatingPointFormul
     debugging = pDebugging;
   }
 
+  @Override
+  public FloatingPointRoundingModeFormula makeRoundingMode(
+      FloatingPointRoundingMode pRoundingMode) {
+    debugging.assertThreadLocal();
+    FloatingPointRoundingModeFormula result = delegate.makeRoundingMode(pRoundingMode);
+    debugging.addFormulaTerm(result);
+    return result;
+  }
+
   @Override
   public FloatingPointFormula makeNumber(double n, FloatingPointType type) {
     debugging.assertThreadLocal();
diff --git a/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsFloatingPointFormulaManager.java
index 415b7cb00f..f1669369c8 100644
--- a/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsFloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/delegate/statistics/StatisticsFloatingPointFormulaManager.java
@@ -19,6 +19,7 @@
 import org.sosy_lab.java_smt.api.FloatingPointFormulaManager;
 import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
 import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
 import org.sosy_lab.java_smt.api.Formula;
 import org.sosy_lab.java_smt.api.FormulaType;
 import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType;
@@ -34,6 +35,13 @@ class StatisticsFloatingPointFormulaManager implements FloatingPointFormulaManag
     stats = checkNotNull(pStats);
   }
 
+  @Override
+  public FloatingPointRoundingModeFormula makeRoundingMode(
+      FloatingPointRoundingMode pRoundingMode) {
+    stats.fpOperations.getAndIncrement();
+    return delegate.makeRoundingMode(pRoundingMode);
+  }
+
   @Override
   public FloatingPointFormula makeNumber(double pN, FloatingPointType pType) {
     stats.fpOperations.getAndIncrement();
diff --git a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedFloatingPointFormulaManager.java b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedFloatingPointFormulaManager.java
index 3d922f71a8..f0e1049c75 100644
--- a/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedFloatingPointFormulaManager.java
+++ b/src/org/sosy_lab/java_smt/delegate/synchronize/SynchronizedFloatingPointFormulaManager.java
@@ -19,6 +19,7 @@
 import org.sosy_lab.java_smt.api.FloatingPointFormulaManager;
 import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
 import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
 import org.sosy_lab.java_smt.api.Formula;
 import org.sosy_lab.java_smt.api.FormulaType;
 import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType;
@@ -35,6 +36,14 @@ class SynchronizedFloatingPointFormulaManager implements FloatingPointFormulaMan
     sync = checkNotNull(pSync);
   }
 
+  @Override
+  public FloatingPointRoundingModeFormula makeRoundingMode(
+      FloatingPointRoundingMode pRoundingMode) {
+    synchronized (sync) {
+      return delegate.makeRoundingMode(pRoundingMode);
+    }
+  }
+
   @Override
   public FloatingPointFormula makeNumber(double pN, FloatingPointType pType) {
     synchronized (sync) {
diff --git a/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFormulaCreator.java b/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFormulaCreator.java
index f946331319..f9fa6e30e7 100644
--- a/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/bitwuzla/BitwuzlaFormulaCreator.java
@@ -33,6 +33,8 @@
 import org.sosy_lab.java_smt.api.BooleanFormula;
 import org.sosy_lab.java_smt.api.FloatingPointFormula;
 import org.sosy_lab.java_smt.api.FloatingPointNumber;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
 import org.sosy_lab.java_smt.api.Formula;
 import org.sosy_lab.java_smt.api.FormulaType;
 import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType;
@@ -131,6 +133,14 @@ assert getFormulaType(pTerm).isFloatingPointType()
     return new BitwuzlaFloatingPointFormula(pTerm);
   }
 
+  @Override
+  protected FloatingPointRoundingModeFormula encapsulateRoundingMode(Term pTerm) {
+    assert getFormulaType(pTerm).isFloatingPointRoundingModeType()
+        : String.format(
+            "%s is no FP rounding mode, but %s (%s)", pTerm, pTerm.sort(), getFormulaType(pTerm));
+    return new BitwuzlaFloatingPointRoundingModeFormula(pTerm);
+  }
+
   @Override
   @SuppressWarnings("MethodTypeParameterName")
   protected  ArrayFormula encapsulateArray(
@@ -584,7 +594,19 @@ public Object convertValue(Term term) {
       return term.to_bool();
     }
     if (sort.is_rm()) {
-      return term.to_rm();
+      if (term.is_rm_value_rna()) {
+        return FloatingPointRoundingMode.NEAREST_TIES_AWAY;
+      } else if (term.is_rm_value_rne()) {
+        return FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN;
+      } else if (term.is_rm_value_rtn()) {
+        return FloatingPointRoundingMode.TOWARD_NEGATIVE;
+      } else if (term.is_rm_value_rtp()) {
+        return FloatingPointRoundingMode.TOWARD_POSITIVE;
+      } else if (term.is_rm_value_rtz()) {
+        return FloatingPointRoundingMode.TOWARD_ZERO;
+      } else {
+        throw new IllegalArgumentException(String.format("Unknown rounding mode: %s", term));
+      }
     }
     if (sort.is_bv()) {
       return new BigInteger(term.to_bv(), 2);
diff --git a/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FormulaCreator.java b/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FormulaCreator.java
index 23e7328956..875cce7bef 100644
--- a/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/cvc4/CVC4FormulaCreator.java
@@ -26,6 +26,7 @@
 import edu.stanford.CVC4.Integer;
 import edu.stanford.CVC4.Kind;
 import edu.stanford.CVC4.Rational;
+import edu.stanford.CVC4.RoundingMode;
 import edu.stanford.CVC4.Type;
 import edu.stanford.CVC4.vectorExpr;
 import edu.stanford.CVC4.vectorType;
@@ -41,6 +42,8 @@
 import org.sosy_lab.java_smt.api.FloatingPointFormula;
 import org.sosy_lab.java_smt.api.FloatingPointNumber;
 import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
 import org.sosy_lab.java_smt.api.Formula;
 import org.sosy_lab.java_smt.api.FormulaType;
 import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType;
@@ -264,6 +267,15 @@ assert getFormulaType(pTerm).isFloatingPointType()
     return new CVC4FloatingPointFormula(pTerm);
   }
 
+  @Override
+  protected FloatingPointRoundingModeFormula encapsulateRoundingMode(Expr pTerm) {
+    assert getFormulaType(pTerm).isFloatingPointRoundingModeType()
+        : String.format(
+            "%s is no FP rounding mode, but %s (%s)",
+            pTerm, pTerm.getType(), getFormulaType(pTerm));
+    return new CVC4FloatingPointRoundingModeFormula(pTerm);
+  }
+
   @Override
   @SuppressWarnings("MethodTypeParameterName")
   protected  ArrayFormula encapsulateArray(
@@ -323,8 +335,7 @@ public  R visit(FormulaVisitor visitor, Formula formula, final Expr f) {
       } else if (type.isFloatingPoint()) {
         return visitor.visitConstant(formula, convertFloatingPoint(f));
       } else if (type.isRoundingMode()) {
-        // TODO is this correct?
-        return visitor.visitConstant(formula, f.getConstRoundingMode());
+        return visitor.visitConstant(formula, convertRoundingMode(f));
       } else if (type.isString()) {
         return visitor.visitConstant(formula, f.getConstString());
       } else if (type.isArray()) {
@@ -613,6 +624,9 @@ public Object convertValue(Expr expForType, Expr value) {
     } else if (valueType.isFloatingPoint()) {
       return convertFloatingPoint(value);
 
+    } else if (valueType.isRoundingMode()) {
+      return convertRoundingMode(value);
+
     } else if (valueType.isString()) {
       return unescapeUnicodeForSmtlib(value.getConstString().toString());
 
@@ -648,4 +662,21 @@ private FloatingPointNumber convertFloatingPoint(Expr fpExpr) {
         expWidth,
         mantWidth);
   }
+
+  private FloatingPointRoundingMode convertRoundingMode(Expr pExpr) {
+    RoundingMode rm = pExpr.getConstRoundingMode();
+    if (rm.equals(RoundingMode.roundNearestTiesToAway)) {
+      return FloatingPointRoundingMode.NEAREST_TIES_AWAY;
+    } else if (rm.equals(RoundingMode.roundNearestTiesToEven)) {
+      return FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN;
+    } else if (rm.equals(RoundingMode.roundTowardNegative)) {
+      return FloatingPointRoundingMode.TOWARD_NEGATIVE;
+    } else if (rm.equals(RoundingMode.roundTowardPositive)) {
+      return FloatingPointRoundingMode.TOWARD_POSITIVE;
+    } else if (rm.equals(RoundingMode.roundTowardZero)) {
+      return FloatingPointRoundingMode.TOWARD_ZERO;
+    } else {
+      throw new IllegalArgumentException(String.format("Unknown rounding mode: %s", pExpr));
+    }
+  }
 }
diff --git a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FormulaCreator.java b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FormulaCreator.java
index 946b6be069..f326da1590 100644
--- a/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/cvc5/CVC5FormulaCreator.java
@@ -27,6 +27,7 @@
 import io.github.cvc5.Kind;
 import io.github.cvc5.Op;
 import io.github.cvc5.Pair;
+import io.github.cvc5.RoundingMode;
 import io.github.cvc5.Solver;
 import io.github.cvc5.Sort;
 import io.github.cvc5.Term;
@@ -44,6 +45,8 @@
 import org.sosy_lab.java_smt.api.EnumerationFormula;
 import org.sosy_lab.java_smt.api.FloatingPointFormula;
 import org.sosy_lab.java_smt.api.FloatingPointNumber;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
 import org.sosy_lab.java_smt.api.Formula;
 import org.sosy_lab.java_smt.api.FormulaType;
 import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType;
@@ -315,6 +318,15 @@ assert getFormulaType(pTerm).isFloatingPointType()
     return new CVC5FloatingPointFormula(pTerm);
   }
 
+  @Override
+  protected FloatingPointRoundingModeFormula encapsulateRoundingMode(Term pTerm) {
+    assert getFormulaType(pTerm).isFloatingPointRoundingModeType()
+        : String.format(
+            "%s is no FP rounding mode, but %s (%s)",
+            pTerm, pTerm.getSort(), getFormulaType(pTerm));
+    return new CVC5FloatingPointRoundingModeFormula(pTerm);
+  }
+
   @Override
   @SuppressWarnings("MethodTypeParameterName")
   protected  ArrayFormula encapsulateArray(
@@ -399,7 +411,7 @@ public  R visit(FormulaVisitor visitor, Formula formula, final Term f) {
         return visitor.visitConstant(formula, convertFloatingPoint(f));
 
       } else if (f.isRoundingModeValue()) {
-        return visitor.visitConstant(formula, f.getRoundingModeValue());
+        return visitor.visitConstant(formula, convertRoundingMode(f));
 
       } else if (f.isConstArray()) {
         Term constant = f.getConstArrayBase();
@@ -816,6 +828,9 @@ public Object convertValue(Term expForType, Term value) {
       } else if (value.isFloatingPointValue()) {
         return convertFloatingPoint(value);
 
+      } else if (value.isRoundingModeValue()) {
+        return convertRoundingMode(value);
+
       } else if (value.isBooleanValue()) {
         return value.getBooleanValue();
 
@@ -845,6 +860,23 @@ private FloatingPointNumber convertFloatingPoint(Term value) throws CVC5ApiExcep
     return FloatingPointNumber.of(bits, expWidth, mantWidth);
   }
 
+  private FloatingPointRoundingMode convertRoundingMode(Term pTerm) throws CVC5ApiException {
+    RoundingMode rm = pTerm.getRoundingModeValue();
+    if (rm.equals(RoundingMode.ROUND_NEAREST_TIES_TO_AWAY)) {
+      return FloatingPointRoundingMode.NEAREST_TIES_AWAY;
+    } else if (rm.equals(RoundingMode.ROUND_NEAREST_TIES_TO_EVEN)) {
+      return FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN;
+    } else if (rm.equals(RoundingMode.ROUND_TOWARD_NEGATIVE)) {
+      return FloatingPointRoundingMode.TOWARD_NEGATIVE;
+    } else if (rm.equals(RoundingMode.ROUND_TOWARD_POSITIVE)) {
+      return FloatingPointRoundingMode.TOWARD_POSITIVE;
+    } else if (rm.equals(RoundingMode.ROUND_TOWARD_ZERO)) {
+      return FloatingPointRoundingMode.TOWARD_ZERO;
+    } else {
+      throw new IllegalArgumentException(String.format("Unknown rounding mode: %s", pTerm));
+    }
+  }
+
   private Term accessVariablesCache(String name, Sort sort) {
     Term existingVar = variablesCache.get(name, sort.toString());
     Preconditions.checkNotNull(
diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FormulaCreator.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FormulaCreator.java
index ff35694c4a..276cb236b8 100644
--- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5FormulaCreator.java
@@ -71,7 +71,6 @@
 import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.MSAT_TAG_OR;
 import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.MSAT_TAG_PLUS;
 import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.MSAT_TAG_TIMES;
-import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.MSAT_TAG_UNKNOWN;
 import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_decl_get_arg_type;
 import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_decl_get_name;
 import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_decl_get_tag;
@@ -105,6 +104,10 @@
 import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_get_type;
 import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_constant;
 import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_false;
+import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_fp_roundingmode_minus_inf;
+import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_fp_roundingmode_nearest_even;
+import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_fp_roundingmode_plus_inf;
+import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_fp_roundingmode_zero;
 import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_number;
 import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_true;
 import static org.sosy_lab.java_smt.solvers.mathsat5.Mathsat5NativeApi.msat_term_is_uf;
@@ -127,6 +130,8 @@
 import org.sosy_lab.java_smt.api.FloatingPointFormula;
 import org.sosy_lab.java_smt.api.FloatingPointNumber;
 import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
 import org.sosy_lab.java_smt.api.Formula;
 import org.sosy_lab.java_smt.api.FormulaType;
 import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType;
@@ -291,6 +296,12 @@ protected FloatingPointFormula encapsulateFloatingPoint(Long pTerm) {
     return new Mathsat5FloatingPointFormula(pTerm);
   }
 
+  @Override
+  protected FloatingPointRoundingModeFormula encapsulateRoundingMode(Long pTerm) {
+    assert getFormulaType(pTerm).isFloatingPointRoundingModeType();
+    return new Mathsat5FloatingPointRoundingModeFormula(pTerm);
+  }
+
   @Override
   @SuppressWarnings("MethodTypeParameterName")
   protected  ArrayFormula encapsulateArray(
@@ -333,6 +344,19 @@ public  R visit(FormulaVisitor visitor, Formula formula, final Long f) {
       return visitor.visitConstant(formula, true);
     } else if (msat_term_is_false(environment, f)) {
       return visitor.visitConstant(formula, false);
+    } else if (msat_is_fp_roundingmode_type(environment, msat_term_get_type(f))) {
+      if (msat_term_is_fp_roundingmode_nearest_even(environment, f)) {
+        return visitor.visitConstant(formula, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN);
+      } else if (msat_term_is_fp_roundingmode_plus_inf(environment, f)) {
+        return visitor.visitConstant(formula, FloatingPointRoundingMode.TOWARD_POSITIVE);
+      } else if (msat_term_is_fp_roundingmode_minus_inf(environment, f)) {
+        return visitor.visitConstant(formula, FloatingPointRoundingMode.TOWARD_NEGATIVE);
+      } else if (msat_term_is_fp_roundingmode_zero(environment, f)) {
+        return visitor.visitConstant(formula, FloatingPointRoundingMode.TOWARD_ZERO);
+      } else {
+        throw new IllegalArgumentException(
+            "Unknown rounding mode " + msat_decl_get_name(msat_term_get_decl(f)));
+      }
     } else if (msat_term_is_constant(environment, f)) {
       return visitor.visitFreeVariable(formula, msat_term_repr(f));
     } else if (msat_is_enum_type(environment, msat_term_get_type(f))) {
@@ -516,22 +540,6 @@ private FunctionDeclarationKind getDeclarationKind(long pF) {
         return FunctionDeclarationKind.FP_IS_SUBNORMAL;
       case MSAT_TAG_FP_ISNORMAL:
         return FunctionDeclarationKind.FP_IS_NORMAL;
-
-      case MSAT_TAG_UNKNOWN:
-        switch (msat_decl_get_name(decl)) {
-          case "`fprounding_even`":
-            return FunctionDeclarationKind.FP_ROUND_EVEN;
-          case "`fprounding_plus_inf`":
-            return FunctionDeclarationKind.FP_ROUND_POSITIVE;
-          case "`fprounding_minus_inf`":
-            return FunctionDeclarationKind.FP_ROUND_NEGATIVE;
-          case "`fprounding_zero`":
-            return FunctionDeclarationKind.FP_ROUND_ZERO;
-
-          default:
-            return FunctionDeclarationKind.OTHER;
-        }
-
       case MSAT_TAG_FLOOR:
         return FunctionDeclarationKind.FLOOR;
 
diff --git a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java
index f0862ddaf8..aa8556f983 100644
--- a/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java
+++ b/src/org/sosy_lab/java_smt/solvers/mathsat5/Mathsat5NativeApi.java
@@ -652,6 +652,14 @@ public static native long msat_simplify(
 
   public static native boolean msat_term_is_bv_comp(long e, long t);
 
+  public static native boolean msat_term_is_fp_roundingmode_nearest_even(long e, long t);
+
+  public static native boolean msat_term_is_fp_roundingmode_zero(long e, long t);
+
+  public static native boolean msat_term_is_fp_roundingmode_plus_inf(long e, long t);
+
+  public static native boolean msat_term_is_fp_roundingmode_minus_inf(long e, long t);
+
   public static native boolean msat_term_is_quantifier(long e, long t);
 
   public static native boolean msat_term_is_forall(long e, long t);
diff --git a/src/org/sosy_lab/java_smt/solvers/z3/Z3FormulaCreator.java b/src/org/sosy_lab/java_smt/solvers/z3/Z3FormulaCreator.java
index bde94b3e5f..f38c6837aa 100644
--- a/src/org/sosy_lab/java_smt/solvers/z3/Z3FormulaCreator.java
+++ b/src/org/sosy_lab/java_smt/solvers/z3/Z3FormulaCreator.java
@@ -47,6 +47,7 @@
 import org.sosy_lab.java_smt.api.FloatingPointNumber;
 import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
 import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
 import org.sosy_lab.java_smt.api.Formula;
 import org.sosy_lab.java_smt.api.FormulaType;
 import org.sosy_lab.java_smt.api.FormulaType.ArrayFormulaType;
@@ -366,6 +367,13 @@ protected FloatingPointFormula encapsulateFloatingPoint(Long pTerm) {
     return storePhantomReference(new Z3FloatingPointFormula(getEnv(), pTerm), pTerm);
   }
 
+  @Override
+  protected FloatingPointRoundingModeFormula encapsulateRoundingMode(Long pTerm) {
+    assert getFormulaType(pTerm).isFloatingPointRoundingModeType();
+    cleanupReferences();
+    return storePhantomReference(new Z3FloatingPointRoundingModeFormula(getEnv(), pTerm), pTerm);
+  }
+
   @Override
   protected StringFormula encapsulateString(Long pTerm) {
     assert getFormulaType(pTerm).isStringType()
@@ -791,16 +799,6 @@ private FunctionDeclarationKind getDeclarationKind(long f) {
         return FunctionDeclarationKind.FP_GT;
       case Z3_OP_FPA_EQ:
         return FunctionDeclarationKind.FP_EQ;
-      case Z3_OP_FPA_RM_NEAREST_TIES_TO_EVEN:
-        return FunctionDeclarationKind.FP_ROUND_EVEN;
-      case Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAY:
-        return FunctionDeclarationKind.FP_ROUND_AWAY;
-      case Z3_OP_FPA_RM_TOWARD_POSITIVE:
-        return FunctionDeclarationKind.FP_ROUND_POSITIVE;
-      case Z3_OP_FPA_RM_TOWARD_NEGATIVE:
-        return FunctionDeclarationKind.FP_ROUND_NEGATIVE;
-      case Z3_OP_FPA_RM_TOWARD_ZERO:
-        return FunctionDeclarationKind.FP_ROUND_ZERO;
       case Z3_OP_FPA_ROUND_TO_INTEGRAL:
         return FunctionDeclarationKind.FP_ROUND_TO_INTEGRAL;
       case Z3_OP_FPA_TO_FP_UNSIGNED:
diff --git a/src/org/sosy_lab/java_smt/test/FloatingPointFormulaManagerTest.java b/src/org/sosy_lab/java_smt/test/FloatingPointFormulaManagerTest.java
index 74390241cf..3f87193507 100644
--- a/src/org/sosy_lab/java_smt/test/FloatingPointFormulaManagerTest.java
+++ b/src/org/sosy_lab/java_smt/test/FloatingPointFormulaManagerTest.java
@@ -32,15 +32,21 @@
 import org.sosy_lab.java_smt.api.FloatingPointNumber;
 import org.sosy_lab.java_smt.api.FloatingPointNumber.Sign;
 import org.sosy_lab.java_smt.api.FloatingPointRoundingMode;
+import org.sosy_lab.java_smt.api.FloatingPointRoundingModeFormula;
+import org.sosy_lab.java_smt.api.Formula;
 import org.sosy_lab.java_smt.api.FormulaType;
 import org.sosy_lab.java_smt.api.FormulaType.FloatingPointType;
+import org.sosy_lab.java_smt.api.FunctionDeclaration;
+import org.sosy_lab.java_smt.api.FunctionDeclarationKind;
 import org.sosy_lab.java_smt.api.InterpolatingProverEnvironment;
 import org.sosy_lab.java_smt.api.Model;
 import org.sosy_lab.java_smt.api.Model.ValueAssignment;
 import org.sosy_lab.java_smt.api.NumeralFormula;
 import org.sosy_lab.java_smt.api.ProverEnvironment;
+import org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier;
 import org.sosy_lab.java_smt.api.SolverContext.ProverOptions;
 import org.sosy_lab.java_smt.api.SolverException;
+import org.sosy_lab.java_smt.api.visitors.FormulaVisitor;
 
 public class FloatingPointFormulaManagerTest
     extends SolverBasedTest0.ParameterizedSolverBasedTest0 {
@@ -87,6 +93,67 @@ public void floatingPointType() {
         .isEqualTo(type.getMantissaSize());
   }
 
+  @Test
+  public void roundingModeVisitor() {
+    FloatingPointFormula variable =
+        fpmgr.makeVariable("a", FormulaType.getSinglePrecisionFloatingPointType());
+    FloatingPointFormula original =
+        fpmgr.sqrt(variable, FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN);
+
+    for (FloatingPointRoundingMode rm : FloatingPointRoundingMode.values()) {
+      if (solver == Solvers.MATHSAT5 && rm == FloatingPointRoundingMode.NEAREST_TIES_AWAY) {
+        // SKIP MathSAT does not support rounding mode "nearest-ties-away"
+        continue;
+      }
+      // Build a term with a different rounding mode, then replace it in the visitor
+      FloatingPointFormula substituted =
+          (FloatingPointFormula)
+              mgr.visit(
+                  fpmgr.sqrt(variable, rm),
+                  new FormulaVisitor() {
+                    @Override
+                    public Formula visitFreeVariable(Formula f, String name) {
+                      return f;
+                    }
+
+                    @Override
+                    public Formula visitConstant(Formula f, Object value) {
+                      assertThat(f).isInstanceOf(FloatingPointRoundingModeFormula.class);
+                      assertThat(value).isInstanceOf(FloatingPointRoundingMode.class);
+                      assertThat(value).isEqualTo(rm);
+
+                      // Return the default rounding mode
+                      return fpmgr.makeRoundingMode(FloatingPointRoundingMode.NEAREST_TIES_TO_EVEN);
+                    }
+
+                    @Override
+                    public Formula visitFunction(
+                        Formula f, List args, FunctionDeclaration> functionDeclaration) {
+                      assertThat(functionDeclaration.getKind())
+                          .isEqualTo(FunctionDeclarationKind.FP_SQRT);
+                      assertThat(args).hasSize(2);
+                      return mgr.makeApplication(
+                          functionDeclaration,
+                          mgr.visit(args.get(0), this),
+                          mgr.visit(args.get(1), this));
+                    }
+
+                    @Override
+                    public Formula visitQuantifier(
+                        BooleanFormula f,
+                        Quantifier quantifier,
+                        List boundVariables,
+                        BooleanFormula body) {
+                      throw new IllegalArgumentException(
+                          String.format("Unexpected quantifier %s", quantifier));
+                    }
+                  });
+
+      // Check that after the substitution the rounding mode is the default again
+      assertThat(original).isEqualTo(substituted);
+    }
+  }
+
   @Test
   public void negative() throws SolverException, InterruptedException {
     for (double d : new double[] {-1, -2, -0.0, Double.NEGATIVE_INFINITY}) {