-// XXX: offs is 8bit only
-#define emith_ctx_read(r, offs) { \
- EMIT_OP_MODRM(0x8b, 1, r, xBP); \
- EMIT(offs, u8); /* mov tmp, [ebp+#offs] */ \
+#define emith_deref_op(op, r, rs, offs) do { \
+ /* mov r <-> [ebp+#offs] */ \
+ if ((offs) >= 0x80) { \
+ EMIT_OP_MODRM(op, 2, r, rs); \
+ EMIT(offs, u32); \
+ } else { \
+ EMIT_OP_MODRM(op, 1, r, rs); \
+ EMIT(offs, u8); \
+ } \
+} while (0)
+
+#define is_abcdx(r) (xAX <= (r) && (r) <= xDX)
+
+#define emith_read_r_r_offs(r, rs, offs) \
+ emith_deref_op(0x8b, r, rs, offs)
+
+#define emith_write_r_r_offs(r, rs, offs) \
+ emith_deref_op(0x89, r, rs, offs)
+
+// note: don't use prefixes on this
+#define emith_read8_r_r_offs(r, rs, offs) do { \
+ int r_ = r; \
+ if (!is_abcdx(r)) \
+ r_ = rcache_get_tmp(); \
+ emith_deref_op(0x8a, r_, rs, offs); \
+ if ((r) != r_) { \
+ emith_move_r_r(r, r_); \
+ rcache_free_tmp(r_); \
+ } \
+} while (0)
+
+#define emith_write8_r_r_offs(r, rs, offs) do {\
+ int r_ = r; \
+ if (!is_abcdx(r)) { \
+ r_ = rcache_get_tmp(); \
+ emith_move_r_r(r_, r); \
+ } \
+ emith_deref_op(0x88, r_, rs, offs); \
+ if ((r) != r_) \
+ rcache_free_tmp(r_); \
+} while (0)
+
+#define emith_read16_r_r_offs(r, rs, offs) { \
+ EMIT(0x66, u8); /* operand override */ \
+ emith_read_r_r_offs(r, rs, offs); \
+}
+
+#define emith_write16_r_r_offs(r, rs, offs) { \
+ EMIT(0x66, u8); \
+ emith_write_r_r_offs(r, rs, offs); \