+/* Handle the special case of using all float registers, as exercised
+ * in check/carg.c.
+ * For example:
+ * putargr_f JIT_F0 $ARG
+ * where JIT_F0 is %f32 and $ARG is %f31 and if %f30 (the mapping for %f31)
+ * is live, the jit_get_reg() call might return %f30, but, because it is
+ * live, will spill/reload it, generating assembly:
+ *
+ * std %f30, [ %fp + OFFS ]
+ * fmovd %f32, %f30
+ * fmovs %f30, %f31
+ * ldd [ %fp + OFFS ], %f30
+ *
+ * what basically becomes a noop as it restores the old value.
+ */
+#define get_sng_reg(u) _get_sng_reg(_jit, u)
+static jit_int32_t
+_get_sng_reg(jit_state_t *_jit, jit_int32_t r0)
+{
+ jit_int32_t reg, tmp;
+ /* Attempt to get a nospill register */
+ reg = jit_get_reg(CLASS_SNG | jit_class_nospill | jit_class_chk);
+ if (reg == JIT_NOREG) {
+ /* Will need to spill, so allow spilling it. */
+ reg = jit_get_reg(CLASS_SNG);
+ /* If the special condition happens, allocate another one.
+ * This will generate uglier machine code (code for floats
+ * is already ugly), but will work, but doing a double
+ * spill/reload; the first one being a noop. */
+ if (rn(reg) == r0 - 1) {
+ tmp = reg;
+ reg = jit_get_reg(CLASS_SNG);
+ jit_unget_reg(tmp);
+ }
+ }
+ return (reg);
+}
+