[Mono-devel-list] [PATCH] Inlinded Atomic ops (x86 asm)
Patrik Torstensson
patrik.torstensson at gmail.com
Sat Dec 11 06:32:01 EST 2004
Hey,
Here is a updated patch that implements Interlocked functions as x86
asm. This patch uses a common path for Inc/Dec.
Cheers,
Patrik Torstensson
-------------- next part --------------
Index: mini-ops.h
===================================================================
--- mini-ops.h (revision 37561)
+++ mini-ops.h (working copy)
@@ -399,8 +399,11 @@
MINI_OP(OP_SAVE_LMF, "save_lmf")
MINI_OP(OP_RESTORE_LMF, "restore_lmf")
+/* atomic specific */
+MINI_OP(OP_ATOMIC_ADD_IMM_I4, "atomic_add_imm_i4")
+MINI_OP(OP_ATOMIC_ADD_I4, "atomic_add_i4")
+MINI_OP(OP_ATOMIC_EXCHANGE_I4, "atomic_exchange_i4")
-
/* x86 specific */
MINI_OP(OP_X86_TEST_NULL, "x86_test_null")
MINI_OP(OP_X86_COMPARE_MEMBASE_REG,"x86_compare_membase_reg")
Index: inssel-x86.brg
===================================================================
--- inssel-x86.brg (revision 37561)
+++ inssel-x86.brg (working copy)
@@ -705,4 +705,44 @@
mono_bblock_add_inst (s->cbb, tree);
}
+reg: OP_ATOMIC_ADD_IMM_I4 (base, OP_ICONST) {
+ tree->opcode = OP_ATOMIC_ADD_IMM_I4;
+ tree->inst_basereg = state->left->tree->inst_basereg;
+ tree->inst_offset = state->left->tree->inst_offset;
+ tree->dreg = state->reg1;
+ tree->inst_imm = state->right->tree->inst_c0;
+
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+stmt: CEE_STIND_I4 (OP_REGVAR, OP_ATOMIC_ADD_IMM_I4 (base, OP_ICONST)) {
+ tree->opcode = OP_ATOMIC_ADD_IMM_I4;
+ tree->inst_basereg = state->right->left->tree->inst_basereg;
+ tree->inst_offset = state->right->left->tree->inst_offset;
+ tree->dreg = state->left->tree->dreg;
+ tree->inst_imm = state->right->right->tree->inst_c0;
+
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+reg: OP_ATOMIC_ADD_I4 (base, reg) {
+ tree->opcode = OP_ATOMIC_ADD_I4;
+ tree->inst_basereg = state->left->tree->inst_basereg;
+ tree->inst_offset = state->left->tree->inst_offset;
+ tree->dreg = state->reg1;
+ tree->sreg2 = state->right->reg1;
+
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
+reg: OP_ATOMIC_EXCHANGE_I4 (base, reg) {
+ tree->opcode = OP_ATOMIC_EXCHANGE_I4;
+ tree->dreg = state->reg1;
+ tree->sreg2 = state->right->reg1;
+ tree->inst_basereg = state->left->tree->inst_basereg;
+ tree->inst_offset = state->left->tree->inst_offset;
+
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
%%
Index: mini-x86.c
===================================================================
--- mini-x86.c (revision 37562)
+++ mini-x86.c (working copy)
@@ -3336,6 +3336,53 @@
x86_mov_reg_mem (code, ins->dreg, ins->inst_offset, 4);
break;
}
+ case OP_ATOMIC_ADD_I4: {
+ x86_mov_reg_imm (code, ins->dreg, ins->sreg2);
+ x86_prefix (code, X86_LOCK_PREFIX);
+ x86_xadd_membase_reg (code, ins->inst_basereg, ins->inst_offset, ins->dreg, 4);
+ x86_alu_reg_imm (code, X86_ADD, ins->dreg, ins->sreg2);
+ break;
+ }
+ case OP_ATOMIC_ADD_IMM_I4: {
+ x86_mov_reg_imm (code, ins->dreg, ins->inst_imm);
+ x86_prefix (code, X86_LOCK_PREFIX);
+ x86_xadd_membase_reg (code, ins->inst_basereg, ins->inst_offset, ins->dreg, 4);
+ x86_alu_reg_imm (code, X86_ADD, ins->dreg, ins->inst_imm);
+ break;
+ }
+ case OP_ATOMIC_EXCHANGE_I4: {
+ guchar *br[2];
+ int sreg2 = ins->sreg2;
+
+ /* cmpxchg uses eax as comperand, need to make sure we can use it */
+ if (ins->dreg != X86_EAX) {
+ x86_push_reg (code, X86_EAX);
+ }
+
+ if (ins->sreg2 == X86_EAX) {
+ x86_push_reg (code, X86_EDX);
+ x86_mov_reg_reg (code, X86_EDX, X86_EAX, 4);
+ sreg2 = X86_EDX;
+ }
+
+ x86_mov_reg_membase (code, X86_EAX, ins->inst_basereg, ins->inst_offset, 4);
+
+ br [0] = code; x86_prefix (code, X86_LOCK_PREFIX);
+ x86_cmpxchg_membase_reg (code, ins->inst_basereg, ins->inst_offset, sreg2);
+ br [1] = code; x86_branch8 (code, X86_CC_NE, -1, FALSE);
+ x86_patch (br [1], br [0]);
+
+ if (ins->dreg != X86_EAX) {
+ x86_mov_reg_reg (code, ins->dreg, X86_EAX, 4);
+ x86_pop_reg (code, X86_EAX);
+ }
+
+ if (ins->sreg2 != sreg2) {
+ x86_pop_reg (code, X86_EDX);
+ }
+
+ break;
+ }
default:
g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
g_assert_not_reached ();
@@ -3906,7 +3953,37 @@
ins->inst_i1 = args [1];
}
#endif
- }
+ } else if (strcmp (cmethod->klass->name, "Interlocked") == 0) {
+ if (strcmp (cmethod->name, "Increment") == 0 && fsig->params [0]->type == MONO_TYPE_I4) {
+ MonoInst *ins_iconst;
+
+ MONO_INST_NEW (cfg, ins, OP_ATOMIC_ADD_IMM_I4);
+ MONO_INST_NEW (cfg, ins_iconst, OP_ICONST);
+ ins_iconst->inst_c0 = 1;
+
+ ins->inst_i0 = args [0];
+ ins->inst_i1 = ins_iconst;
+ } else if (strcmp (cmethod->name, "Decrement") == 0 && fsig->params [0]->type == MONO_TYPE_I4) {
+ MonoInst *ins_iconst;
+
+ MONO_INST_NEW (cfg, ins, OP_ATOMIC_ADD_IMM_I4);
+ MONO_INST_NEW (cfg, ins_iconst, OP_ICONST);
+ ins_iconst->inst_c0 = -1;
+
+ ins->inst_i0 = args [0];
+ ins->inst_i1 = ins_iconst;
+ } else if (strcmp (cmethod->name, "Exchange") == 0 && fsig->params [0]->type == MONO_TYPE_I4) {
+ MONO_INST_NEW (cfg, ins, OP_ATOMIC_EXCHANGE_I4);
+
+ ins->inst_i0 = args [0];
+ ins->inst_i1 = args [1];
+ } else if (strcmp (cmethod->name, "Add") == 0 && fsig->params [0]->type == MONO_TYPE_I4) {
+ MONO_INST_NEW (cfg, ins, OP_ATOMIC_ADD_I4);
+
+ ins->inst_i0 = args [0];
+ ins->inst_i1 = args [1];
+ }
+ }
return ins;
}
Index: cpu-pentium.md
===================================================================
--- cpu-pentium.md (revision 37561)
+++ cpu-pentium.md (working copy)
@@ -565,3 +565,6 @@
sext_i1: dest:i src1:i len:3
sext_i2: dest:i src1:i len:3
x86_tls_get: dest:i len:20
+atomic_add_imm_i4: src1:b src2:i dest:i len:15
+atomic_add_i4: src1:b src2:i dest:i len:16
+atomic_exchange_i4: src1:b src2:i dest:i len:14
More information about the Mono-devel-list
mailing list