support putL(LABEL); function
diff --git a/readme.md b/readme.md
index 1c46e53..3031c17 100644
--- a/readme.md
+++ b/readme.md
@@ -1,5 +1,5 @@
 
-Xbyak 4.00 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
+Xbyak 4.02 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
 =============
 
 Abstract
@@ -235,6 +235,7 @@
 
 History
 -------------
+* 2013/Jun/21 ver 4.02 add putL(LABEL) function to put the address of the label
 * 2013/Jun/21 ver 4.01 vpsllw, vpslld, vpsllq, vpsraw, vpsrad, vpsrlw, vpsrld, vpsrlq support (ymm, ymm, xmm).
                        support vpbroadcastb, vpbroadcastw, vpbroadcastd, vpbroadcastq(thanks to Gabest).
 * 2013/May/30 ver 4.00 support AVX2, VEX-encoded GPR-instructions
diff --git a/readme.txt b/readme.txt
index 1ee8bbb..a5a4067 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,5 +1,5 @@
 

-    C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 4.01

+    C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 4.02

 

 -----------------------------------------------------------------------------

 ◎概要

@@ -244,6 +244,7 @@
 -----------------------------------------------------------------------------

 ◎履歴

 

+2013/06/21 ver 4.02 LABELの指すアドレスを書き込むputL(LABEL)関数の追加。

 2013/06/21 ver 4.01 vpsllw, vpslld, vpsllq, vpsraw, vpsrad, vpsrlw, vpsrld, vpsrlq support (ymm, ymm, xmm)

                     support vpbroadcastb, vpbroadcastw, vpbroadcastd, vpbroadcastq(thanks to Gabest)

 2013/05/30 ver 4.00 AVX2, VEX-encoded GPR-instructionをサポート

diff --git a/sample/Makefile b/sample/Makefile
index 35a285c..279707d 100644
--- a/sample/Makefile
+++ b/sample/Makefile
@@ -1,4 +1,4 @@
-TARGET = test quantize bf toyvm test_util memfunc static_buf
+TARGET = test quantize bf toyvm test_util memfunc static_buf jmp_table
 XBYAK_INC=../xbyak/xbyak.h
 
 BOOST_EXIST=$(shell echo "\#include <boost/spirit/core.hpp>" | (gcc -E - 2>/dev/null) | grep "boost/spirit/core.hpp" >/dev/null && echo "1")
@@ -12,7 +12,7 @@
 endif
 
 ifeq ($(BIT),64)
-TARGET += test64 bf64 memfunc64 test_util64 static_buf64
+TARGET += test64 bf64 memfunc64 test_util64 static_buf64 jmp_table64
 ifeq ($(BOOST_EXIST),1)
 TARGET += calc64 #calc2_64
 endif
@@ -26,7 +26,7 @@
 
 CFLAGS_WARN=-Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith -pedantic
 
-CFLAGS=-g -O2 -fomit-frame-pointer -DXBYAK_NO_OP_NAMES -Wall -I../ $(CFLAGS_WARN)
+CFLAGS=-g -O2 -fomit-frame-pointer -Wall -I../ $(CFLAGS_WARN)
 
 test:
 	$(CXX) $(CFLAGS) test0.cpp -o $@ -m32
@@ -66,6 +66,10 @@
 	$(CXX) $(CFLAGS) static_buf.cpp -o $@ -m32
 static_buf64:
 	$(CXX) $(CFLAGS) static_buf.cpp -o $@ -m64
+jmp_table:
+	$(CXX) $(CFLAGS) jmp_table.cpp -o $@ -m32
+jmp_table64:
+	$(CXX) $(CFLAGS) jmp_table.cpp -o $@ -m64
 
 clean:
 	rm -rf *.o $(TARGET) *.exe
@@ -86,3 +90,5 @@
 static_buf64: static_buf.cpp $(XBYAK_INC)
 test_util : test_util.cpp $(XBYAK_INC) ../xbyak/xbyak_util.h
 test_util2 : test_util.cpp $(XBYAK_INC) ../xbyak/xbyak_util.h
+jmp_table: jmp_table.cpp $(XBYAK_INC)
+jmp_table64: jmp_table.cpp $(XBYAK_INC)
diff --git a/sample/bf.cpp b/sample/bf.cpp
index 13c9718..2c38486 100644
--- a/sample/bf.cpp
+++ b/sample/bf.cpp
@@ -1,3 +1,4 @@
+#define XBYAK_NO_OP_NAMES
 #include "xbyak/xbyak.h"
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/sample/calc.cpp b/sample/calc.cpp
index 01c568d..a1e83f2 100644
--- a/sample/calc.cpp
+++ b/sample/calc.cpp
@@ -10,6 +10,7 @@
 #include <stdio.h>
 #include <sstream>
 #include <map>
+#define XBYAK_NO_OP_NAMES
 #include "xbyak/xbyak.h"
 #ifdef _MSC_VER
 	#pragma warning(disable : 4127) // for boost(constant condition)
diff --git a/sample/calc2.cpp b/sample/calc2.cpp
index ce2b222..fc7afa9 100644
--- a/sample/calc2.cpp
+++ b/sample/calc2.cpp
@@ -22,6 +22,7 @@
 #include <assert.h>
 #include <string>
 #include <vector>
+#define XBYAK_NO_OP_NAMES
 #include "xbyak/xbyak.h"
 
 enum Operand {
diff --git a/sample/jmp_table.cpp b/sample/jmp_table.cpp
new file mode 100644
index 0000000..415f74e
--- /dev/null
+++ b/sample/jmp_table.cpp
@@ -0,0 +1,132 @@
+/*
+	sample of move(reg, LABEL);, L(LABEL), putL(LABEL);
+*/
+#include <stdio.h>
+#define XBYAK_NO_OP_NAMES
+#include <xbyak/xbyak.h>
+
+const int expectTbl[] = {
+	5, 9, 12
+};
+
+struct Code : Xbyak::CodeGenerator {
+	explicit Code(int mode, size_t size, void *p)
+		: Xbyak::CodeGenerator(size, p)
+	{
+		inLocalLabel();
+#ifdef XBYAK64
+		const Xbyak::Reg64& a = rax;
+		const Xbyak::Reg64& c = rcx;
+#ifdef XBYAK64_WIN
+		mov(rax, rcx);
+#else
+		mov(rax, rdi);
+#endif
+#else
+		const Xbyak::Reg32& a = eax;
+		const Xbyak::Reg32& c = ecx;
+		mov(a, ptr [esp + 4]);
+#endif
+
+		switch (mode) {
+		case 0:
+			mov(c, ".jmp_table");
+			lea(c, ptr [c + a * 8]);
+			jmp(c);
+		align(8);
+			L(".jmp_table");
+			mov(a, expectTbl[0]);
+			ret();
+		align(8);
+			mov(a, expectTbl[1]);
+			ret();
+		align(8);
+			mov(a, expectTbl[2]);
+			ret();
+			break;
+
+		case 1:
+			/*
+				the label for putL is defined when called
+			*/
+			mov(c, ".jmp_table");
+			jmp(ptr [c + a * (int)sizeof(size_t)]);
+		L(".label1");
+			mov(a, expectTbl[0]);
+			jmp(".end");
+		L(".label2");
+			mov(a, expectTbl[1]);
+			jmp(".end");
+		L(".label3");
+			mov(a, expectTbl[2]);
+			jmp(".end");
+		L(".end");
+			ret();
+
+			/*
+				this table should be in code segment
+			*/
+			align(8);
+		L(".jmp_table");
+		putL(".label1");
+		putL(".label2");
+		putL(".label3");
+			break;
+
+		case 2:
+			/*
+				the label for putL is not defined when called
+			*/
+			jmp(".in");
+			align(8);
+			/*
+				this table should be in code segment
+			*/
+		L(".jmp_table");
+		putL(".label1");
+		putL(".label2");
+		putL(".label3");
+		L(".in");
+			mov(c, ".jmp_table");
+			jmp(ptr [c + a * (int)sizeof(size_t)]);
+		L(".label1");
+			mov(a, expectTbl[0]);
+			jmp(".end");
+		L(".label2");
+			mov(a, expectTbl[1]);
+			jmp(".end");
+		L(".label3");
+			mov(a, expectTbl[2]);
+			jmp(".end");
+		L(".end");
+			ret();
+			break;
+		}
+		outLocalLabel();
+	}
+};
+
+int main()
+	try
+{
+	for (int mode = 0; mode < 3; mode++) {
+		printf("mode=%d\n", mode);
+		for (int grow = 0; grow < 2; grow++) {
+			printf("auto grow=%s\n", grow ? "on" : "off");
+			Code c(mode, grow ? 10 : 4096, grow ? Xbyak::AutoGrow : 0);
+			int (*f)(int) = c.getCode<int (*)(int)>();
+			c.ready();
+			for (int i = 0; i < 3; i++) {
+				const int a = expectTbl[i];
+				const int b = f(i);
+				if (a != b) {
+					printf("ERR i=%d, a=%d, b=%d\n", i, a, b);
+					exit(1);
+				}
+			}
+		}
+	}
+	puts("ok");
+} catch (Xbyak::Error e) {
+	printf("ERR %s\n", Xbyak::ConvertErrorToString(e));
+}
diff --git a/sample/memfunc.cpp b/sample/memfunc.cpp
index eeedaa9..a98dd73 100644
--- a/sample/memfunc.cpp
+++ b/sample/memfunc.cpp
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
+#define XBYAK_NO_OP_NAMES
 #include <xbyak/xbyak.h>
 
 struct A {
diff --git a/sample/quantize.cpp b/sample/quantize.cpp
index 401f886..f028927 100644
--- a/sample/quantize.cpp
+++ b/sample/quantize.cpp
@@ -42,6 +42,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
+#define XBYAK_NO_OP_NAMES
 #include "xbyak/xbyak.h"
 #ifdef _MSC_VER
 	#pragma warning(disable : 4996) // scanf
diff --git a/sample/static_buf.cpp b/sample/static_buf.cpp
index d5f4183..a2ef0e2 100644
--- a/sample/static_buf.cpp
+++ b/sample/static_buf.cpp
@@ -2,6 +2,7 @@
 	sample to use static memory
 */
 #include <stdio.h>
+#define XBYAK_NO_OP_NAMES
 #include "xbyak/xbyak.h"
 
 MIE_ALIGN(4096) char buf[4096];
diff --git a/sample/test0.cpp b/sample/test0.cpp
index c54ecc8..93cfa9d 100644
--- a/sample/test0.cpp
+++ b/sample/test0.cpp
@@ -4,6 +4,7 @@
 #endif
 #include <stdio.h>
 #include <stdlib.h>
+#define XBYAK_NO_OP_NAMES
 #include "xbyak/xbyak.h"
 
 class Sample : public Xbyak::CodeGenerator {
diff --git a/sample/toyvm.cpp b/sample/toyvm.cpp
index aa2e3ad..a98b7ce 100644
--- a/sample/toyvm.cpp
+++ b/sample/toyvm.cpp
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 #include <memory.h>
 #include <vector>
+#define XBYAK_NO_OP_NAMES
 #include "xbyak/xbyak.h"
 #include "xbyak/xbyak_util.h"
 #define NUM_OF_ARRAY(x) (sizeof(x) / sizeof(x[0]))
diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h
index 0ee884f..aebf5df 100644
--- a/xbyak/xbyak.h
+++ b/xbyak/xbyak.h
@@ -85,7 +85,7 @@
 
 enum {
 	DEFAULT_MAX_CODE_SIZE = 4096,
-	VERSION = 0x4001 /* 0xABCD = A.BC(D) */
+	VERSION = 0x4002 /* 0xABCD = A.BC(D) */
 };
 
 #ifndef MIE_INTEGER_TYPE_DEFINED
@@ -1637,6 +1637,7 @@
 			throw ERR_BAD_COMBINATION;
 		}
 	}
+	// QQQ : rewrite this function with putL
 	void mov(
 #ifdef XBYAK64
 		const Reg64& reg,
@@ -1673,6 +1674,31 @@
 		jmp.mode = isAutoGrow() ? inner::LaddTop : inner::Labs;
 		label_.addUndefinedLabel(label, jmp);
 	}
+	/*
+		put address of label to buffer
+		@note the put size is 4(32-bit), 8(64-bit)
+	*/
+	void putL(const char *label)
+	{
+		const int jmpSize = (int)sizeof(size_t);
+		if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory();
+		size_t offset = 0;
+		if (label_.getOffset(&offset, label)) {
+			if (isAutoGrow()) {
+				db(uint64(0), jmpSize);
+				save(size_ - jmpSize, offset, jmpSize, inner::LaddTop);
+			} else {
+				db(size_t(top_) + offset, jmpSize);
+			}
+			return;
+		}
+		db(uint64(0), jmpSize);
+		JmpLabel jmp;
+		jmp.endOfJmp = size_;
+		jmp.jmpSize = jmpSize;
+		jmp.mode = isAutoGrow() ? inner::LaddTop : inner::Labs;
+		label_.addUndefinedLabel(label, jmp);
+	}
 	void cmpxchg8b(const Address& addr) { opModM(addr, Reg32(1), 0x0F, B11000111); }
 #ifdef XBYAK64
 	void cmpxchg16b(const Address& addr) { opModM(addr, Reg64(1), 0x0F, B11000111); }
diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h
index 5d6939e..e2ef2bd 100644
--- a/xbyak/xbyak_mnemonic.h
+++ b/xbyak/xbyak_mnemonic.h
@@ -1,4 +1,4 @@
-const char *getVersionString() const { return "4.001"; }
+const char *getVersionString() const { return "4.002"; }
 void packssdw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x6B); }
 void packsswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x63); }
 void packuswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x67); }