+#define emith_add_r_r(d, s) \
+ EMIT_OP_MODRM(0x01, 3, s, d)
+
+#define emith_sub_r_r(d, s) \
+ EMIT_OP_MODRM(0x29, 3, s, d)
+
+#define emith_adc_r_r(d, s) \
+ EMIT_OP_MODRM(0x11, 3, s, d)
+
+#define emith_sbc_r_r(d, s) \
+ EMIT_OP_MODRM(0x19, 3, s, d) /* SBB */
+
+#define emith_or_r_r(d, s) \
+ EMIT_OP_MODRM(0x09, 3, s, d)
+
+#define emith_and_r_r(d, s) \
+ EMIT_OP_MODRM(0x21, 3, s, d)
+
+#define emith_eor_r_r(d, s) \
+ EMIT_OP_MODRM(0x31, 3, s, d) /* XOR */
+
+#define emith_tst_r_r(d, s) \
+ EMIT_OP_MODRM(0x85, 3, s, d) /* TEST */
+
+#define emith_cmp_r_r(d, s) \
+ EMIT_OP_MODRM(0x39, 3, s, d)
+
+// fake teq - test equivalence - get_flags(d ^ s)
+#define emith_teq_r_r(d, s) { \
+ emith_push(d); \
+ emith_eor_r_r(d, s); \
+ emith_pop(d); \
+}
+
+#define emith_mvn_r_r(d, s) { \
+ if (d != s) \
+ emith_move_r_r(d, s); \
+ EMIT_OP_MODRM(0xf7, 3, 2, d); /* NOT d */ \
+}
+
+#define emith_negc_r_r(d, s) { \
+ int tmp_ = rcache_get_tmp(); \
+ emith_move_r_imm(tmp_, 0); \
+ emith_sbc_r_r(tmp_, s); \
+ emith_move_r_r(d, tmp_); \
+ rcache_free_tmp(tmp_); \
+}
+
+#define emith_neg_r_r(d, s) { \
+ if (d != s) \
+ emith_move_r_r(d, s); \
+ EMIT_OP_MODRM(0xf7, 3, 3, d); /* NEG d */ \
+}
+
+// _r_r_r
+#define emith_eor_r_r_r(d, s1, s2) { \
+ if (d == s1) { \
+ emith_eor_r_r(d, s2); \
+ } else if (d == s2) { \
+ emith_eor_r_r(d, s1); \
+ } else { \
+ emith_move_r_r(d, s1); \
+ emith_eor_r_r(d, s2); \
+ } \
+}
+
+#define emith_or_r_r_r_lsl(d, s1, s2, lslimm) { \
+ int tmp_ = rcache_get_tmp(); \
+ emith_lsl(tmp_, s2, lslimm); \
+ emith_or_r_r(tmp_, s1); \
+ emith_move_r_r(d, tmp_); \
+ rcache_free_tmp(tmp_); \
+}
+
+// _r_imm