[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