Merge branch 'dev'
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 3fad142..39dcc86 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -7,5 +7,6 @@
     runs-on: ubuntu-latest
     steps:
     - uses: actions/checkout@v2
+    - run: sudo apt update
     - run: sudo apt install nasm yasm g++-multilib tcsh
     - run: make test
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e92a621..bf72cf0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 2.6...3.0.2)
 
-project(xbyak LANGUAGES CXX VERSION 6.02)
+project(xbyak LANGUAGES CXX VERSION 6.03)
 
 file(GLOB headers xbyak/*.h)
 
diff --git a/gen/Makefile b/gen/Makefile
index c3cd0ea..9442f0d 100644
--- a/gen/Makefile
+++ b/gen/Makefile
@@ -1,6 +1,6 @@
 TARGET=../xbyak/xbyak_mnemonic.h
 BIN=sortline gen_code gen_avx512
-CFLAGS=-I../ -O2 -DXBYAK_NO_OP_NAMES -Wall -Wextra -Wno-missing-field-initializers
+CFLAGS=-I../ -O2 -DXBYAK_NO_OP_NAMES -Wall -Wextra -Wno-missing-field-initializers $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)
 all: $(TARGET) ../CMakeLists.txt ../meson.build
 sortline: sortline.cpp
 	$(CXX) $(CFLAGS) $< -o $@
diff --git a/meson.build b/meson.build
index a29dff6..94ed527 100644
--- a/meson.build
+++ b/meson.build
@@ -5,7 +5,7 @@
 project(
 	'xbyak',
 	'cpp',
-	version: '6.02',
+	version: '6.03',
 	license: 'BSD-3-Clause',
 	default_options: 'b_ndebug=if-release'
 )
diff --git a/readme.md b/readme.md
index 67ab861..1c0b5d7 100644
--- a/readme.md
+++ b/readme.md
@@ -1,6 +1,6 @@
 [![Build Status](https://github.com/herumi/xbyak/actions/workflows/main.yml/badge.svg)](https://github.com/herumi/xbyak/actions/workflows/main.yml)
 
-#lXbyak 6.02 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
+#lXbyak 6.03 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
 
 ## Abstract
 
@@ -19,6 +19,7 @@
 If you want to use them, then specify `-fno-operator-names` option to gcc/clang.
 
 ### News
+- MmapAllocator supports memfd with user-defined strings. see sample/memfd.cpp
 - strictly check address offset disp32 in a signed 32-bit integer. e.g., `ptr[(void*)0xffffffff]` causes an error.
   - define `XBYAK_OLD_DISP_CHECK` if you need an old check, but the option will be remoevd.
 - add `jmp(mem, T_FAR)`, `call(mem, T_FAR)` `retf()` for far absolute indirect jump.
@@ -469,6 +470,8 @@
 http://opensource.org/licenses/BSD-3-Clause
 
 ## History
+* 2022/Jan/28 ver 6.02 strict check the range of 32-bit dispacement
+* 2021/Dec/14 ver 6.01 support T_FAR jump/call and retf
 * 2021/Sep/14 ver 6.00 fully support AVX512-FP16
 * 2021/Sep/09 ver 5.997 fix vrndscale* to support {sae}
 * 2021/Sep/03 ver 5.996 fix v{add,sub,mul,div,max,min}{sd,ss} to support T_rd_sae.
diff --git a/readme.txt b/readme.txt
index 216190a..9630764 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,5 +1,5 @@
 

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

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

 

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

 ◎概要

@@ -400,6 +400,8 @@
 -----------------------------------------------------------------------------

 ◎履歴

 

+2022/01/28 ver 6.02 dispacementの32bit範囲チェックの厳密化

+2021/12/14 ver 6.01 T_FAR jump/callとretfをサポート

 2021/09/14 ver 6.00 AVX512-FP16を完全サポート

 2021/09/09 ver 5.997 vrndscale*を{sae}をサポートするよう修正

 2021/09/03 ver 5.996 v{add,sub,mul,div,max,min}{sd,ss}をT_rd_saeなどをサポートするよう修正

diff --git a/sample/Makefile b/sample/Makefile
index 0c100a3..7c910bb 100644
--- a/sample/Makefile
+++ b/sample/Makefile
@@ -37,6 +37,7 @@
 
 ifneq ($(OS),mac)
 TARGET += static_buf64
+TARGET += memfd
 endif
 
 
@@ -51,7 +52,7 @@
 
 CFLAGS_WARN=-Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith #-pedantic
 
-CFLAGS=-g -O2 -fomit-frame-pointer -Wall -I../ $(CFLAGS_WARN)
+CFLAGS=-g -O2 -fomit-frame-pointer -Wall -I../ $(CFLAGS_WARN) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)
 
 test:
 	$(CXX) $(CFLAGS) test0.cpp -o $@ -m32
@@ -95,6 +96,8 @@
 	$(CXX) $(CFLAGS) jmp_table.cpp -o $@ -m32
 jmp_table64:
 	$(CXX) $(CFLAGS) jmp_table.cpp -o $@ -m64
+memfd:
+	$(CXX) $(CFLAGS) memfd.cpp -o $@ -m64
 profiler: profiler.cpp ../xbyak/xbyak_util.h
 	$(CXX) $(CFLAGS) profiler.cpp -o $@
 profiler-vtune: profiler.cpp ../xbyak/xbyak_util.h
@@ -121,3 +124,4 @@
 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)
+memfd: memfd.cpp $(XBYAK_INC)
diff --git a/sample/memfd.cpp b/sample/memfd.cpp
new file mode 100644
index 0000000..1066c55
--- /dev/null
+++ b/sample/memfd.cpp
@@ -0,0 +1,39 @@
+/*
+	a sample to use MmapAllocator with an user-defined name
+	cat /proc/`psidof ./memfd`/maps
+
+7fca70b44000-7fca70b4a000 rw-p 00000000 00:00 0
+7fca70b67000-7fca70b68000 rwxs 00000000 00:05 19960170                   /memfd:xyz (deleted)
+7fca70b68000-7fca70b69000 rwxs 00000000 00:05 19960169                   /memfd:abc (deleted)
+7fca70b69000-7fca70b6a000 r--p 00029000 103:03 19136541                  /lib/x86_64-linux-gnu/ld-2.27.so
+7fca70b6a000-7fca70b6b000 rw-p 0002a000 103:03 19136541                  /lib/x86_64-linux-gnu/ld-2.27.so
+*/
+#define XBYAK_USE_MEMFD
+#include <xbyak/xbyak.h>
+#include <fstream>
+
+class Code : Xbyak::MmapAllocator, public Xbyak::CodeGenerator {
+public:
+    Code(const char *name, int v)
+        : Xbyak::MmapAllocator(name)
+        , Xbyak::CodeGenerator(4096, nullptr, this /* specify external MmapAllocator */)
+    {
+        mov(eax, v);
+        ret();
+    }
+};
+
+int main()
+{
+    Code c1("Xbyak::abc", 123);
+    Code c2("Xbyak::xyz", 456);
+    printf("c1 %d\n", c1.getCode<int (*)()>()());
+    printf("c2 %d\n", c2.getCode<int (*)()>()());
+	std::ifstream ifs("/proc/self/maps", std::ios::binary);
+	if (ifs) {
+		std::string line;
+		while (std::getline(ifs, line)) {
+			printf("%s\n", line.c_str());
+		}
+	}
+}
diff --git a/test/Makefile b/test/Makefile
index ac69b3e..b9dd413 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -22,7 +22,7 @@
 
 CFLAGS_WARN=-Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith
 
-CFLAGS=-O2 -fomit-frame-pointer -Wall -fno-operator-names -I../ -I./ $(CFLAGS_WARN) #-std=c++0x
+CFLAGS=-O2 -fomit-frame-pointer -Wall -fno-operator-names -I../ -I./ $(CFLAGS_WARN) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) #-std=c++0x
 make_nm:
 	$(CXX) $(CFLAGS) make_nm.cpp -o $@
 normalize_prefix: normalize_prefix.cpp ../xbyak/xbyak.h
@@ -95,7 +95,7 @@
 	$(MAKE) test_avx512
 
 clean:
-	rm -rf *.o $(TARGET) lib_run nm.cpp nm_frame make_512
+	$(RM) a.asm *.lst *.obj *.o $(TARGET) lib_run nm.cpp nm_frame make_512
 
 lib_run: lib_test.cpp lib_run.cpp lib.h
 	$(CXX) $(CFLAGS) lib_run.cpp lib_test.cpp -o lib_run
diff --git a/test/misc.cpp b/test/misc.cpp
index 0e1c3f4..140072e 100644
--- a/test/misc.cpp
+++ b/test/misc.cpp
@@ -23,6 +23,20 @@
 	} code;
 }
 
+CYBOZU_TEST_AUTO(badSSE)
+{
+	struct Code : Xbyak::CodeGenerator {
+		Code()
+		{
+			CYBOZU_TEST_EXCEPTION(paddd(xm16, xm1), Xbyak::Error);
+			CYBOZU_TEST_EXCEPTION(pslld(xm16, 1), Xbyak::Error);
+			CYBOZU_TEST_EXCEPTION(movapd(xm16, xm1), Xbyak::Error);
+			CYBOZU_TEST_EXCEPTION(movhpd(xm16, ptr[eax]), Xbyak::Error);
+			CYBOZU_TEST_EXCEPTION(pextrb(eax, xm16, 1), Xbyak::Error);
+		}
+	} code;
+}
+
 CYBOZU_TEST_AUTO(compOperand)
 {
 	using namespace Xbyak::util;
diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h
index b99ebfa..c5c38dd 100644
--- a/xbyak/xbyak.h
+++ b/xbyak/xbyak.h
@@ -142,7 +142,7 @@
 
 enum {
 	DEFAULT_MAX_CODE_SIZE = 4096,
-	VERSION = 0x6020 /* 0xABCD = A.BC(D) */
+	VERSION = 0x6030 /* 0xABCD = A.BC(D) */
 };
 
 #ifndef MIE_INTEGER_TYPE_DEFINED
@@ -383,6 +383,7 @@
 	custom allocator
 */
 struct Allocator {
+	explicit Allocator(const std::string& = "") {} // same interface with MmapAllocator
 	virtual uint8_t *alloc(size_t size) { return reinterpret_cast<uint8_t*>(AlignedMalloc(size, inner::ALIGN_PAGE_SIZE)); }
 	virtual void free(uint8_t *p) { AlignedFree(p); }
 	virtual ~Allocator() {}
@@ -414,10 +415,12 @@
 
 } // util
 #endif
-class MmapAllocator : Allocator {
+class MmapAllocator : public Allocator {
+	const std::string name_; // only used with XBYAK_USE_MEMFD
 	typedef XBYAK_STD_UNORDERED_MAP<uintptr_t, size_t> SizeList;
 	SizeList sizeList_;
 public:
+	explicit MmapAllocator(const std::string& name = "xbyak") : name_(name) {}
 	uint8_t *alloc(size_t size)
 	{
 		const size_t alignedSizeM1 = inner::ALIGN_PAGE_SIZE - 1;
@@ -435,7 +438,7 @@
 #endif
 		int fd = -1;
 #if defined(XBYAK_USE_MEMFD)
-		fd = memfd_create("xbyak", MFD_CLOEXEC);
+		fd = memfd_create(name_.c_str(), MFD_CLOEXEC);
 		if (fd != -1) {
 			mode = MAP_SHARED;
 			if (ftruncate(fd, size) != 0) XBYAK_THROW_RET(ERR_CANT_ALLOC, 0)
@@ -459,6 +462,8 @@
 		sizeList_.erase(i);
 	}
 };
+#else
+typedef Allocator MmapAllocator;
 #endif
 
 class Address;
@@ -1623,6 +1628,11 @@
 	{
 		return op1.isREG(i32e) && ((op2.isREG(i32e) && op1.getBit() == op2.getBit()) || op2.isMEM());
 	}
+	static inline bool isValidSSE(const Operand& op1)
+	{
+		// SSE instructions do not support XMM16 - XMM31
+		return !(op1.isXMM() && op1.getIdx() >= 16);
+	}
 	void rex(const Operand& op1, const Operand& op2 = Operand())
 	{
 		uint8_t rex = 0;
@@ -1965,6 +1975,7 @@
 	void opGen(const Operand& reg, const Operand& op, int code, int pref, bool isValid(const Operand&, const Operand&), int imm8 = NONE, int preCode = NONE)
 	{
 		if (isValid && !isValid(reg, op)) XBYAK_THROW(ERR_BAD_COMBINATION)
+		if (!isValidSSE(reg) || !isValidSSE(op)) XBYAK_THROW(ERR_NOT_SUPPORTED)
 		if (pref != NONE) db(pref);
 		if (op.isMEM()) {
 			opModM(op.getAddress(), reg.getReg(), 0x0F, preCode, code, (imm8 != NONE) ? 1 : 0);
@@ -1975,6 +1986,7 @@
 	}
 	void opMMX_IMM(const Mmx& mmx, int imm8, int code, int ext)
 	{
+		if (!isValidSSE(mmx)) XBYAK_THROW(ERR_NOT_SUPPORTED)
 		if (mmx.isXMM()) db(0x66);
 		opModR(Reg32(ext), mmx, 0x0F, code);
 		db(imm8);
@@ -1985,6 +1997,7 @@
 	}
 	void opMovXMM(const Operand& op1, const Operand& op2, int code, int pref)
 	{
+		if (!isValidSSE(op1) || !isValidSSE(op2)) XBYAK_THROW(ERR_NOT_SUPPORTED)
 		if (pref != NONE) db(pref);
 		if (op1.isXMM() && op2.isMEM()) {
 			opModM(op2.getAddress(), op1.getReg(), 0x0F, code);
@@ -1996,6 +2009,7 @@
 	}
 	void opExt(const Operand& op, const Mmx& mmx, int code, int imm, bool hasMMX2 = false)
 	{
+		if (!isValidSSE(op) || !isValidSSE(mmx)) XBYAK_THROW(ERR_NOT_SUPPORTED)
 		if (hasMMX2 && op.isREG(i32e)) { /* pextrw is special */
 			if (mmx.isXMM()) db(0x66);
 			opModR(op.getReg(), mmx, 0x0F, 0xC5); db(imm);
diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h
index 4676b56..9f309b6 100644
--- a/xbyak/xbyak_mnemonic.h
+++ b/xbyak/xbyak_mnemonic.h
@@ -1,4 +1,4 @@
-const char *getVersionString() const { return "6.02"; }
+const char *getVersionString() const { return "6.03"; }
 void adc(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x10, 2); }
 void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); }
 void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); }